Passed
Push — master ( f2dea1...58a092 )
by Nate
04:47
created

Object::find()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
nc 3
cc 3
eloc 7
nop 2
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipbox/spark/blob/master/LICENSE
6
 * @link       https://github.com/flipbox/spark
7
 */
8
9
namespace flipbox\spark\services;
10
11
use craft\helpers\Json as JsonHelper;
12
use flipbox\spark\exceptions\ObjectNotFoundException;
13
use flipbox\spark\helpers\ArrayHelper;
14
use flipbox\spark\helpers\ObjectHelper;
15
use flipbox\spark\Records\Record;
16
use yii\base\Component;
17
use yii\base\InvalidConfigException;
18
use yii\base\Object as BaseObject;
19
use yii\db\QueryInterface;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.0.0
24
 */
25
abstract class Object extends Component
26
{
27
28
    use traits\Object;
29
30
    /**
31
     * @var BaseObject[]
32
     */
33
    protected $_cacheAll;
34
35
    /*******************************************
36
     * OBJECT CLASSES
37
     *******************************************/
38
39
    /**
40
     * @return string
41
     */
42
    public abstract static function objectClass(): string;
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
43
44
    /**
45
     * @return string
46
     */
47
    public static function objectClassInstance(): string
48
    {
49
        return BaseObject::class;
50
    }
51
52
    /*******************************************
53
     * CREATE
54
     *******************************************/
55
56
    /**
57
     * @param array $config
58
     * @throws InvalidConfigException
59
     * @return BaseObject
60
     */
61 View Code Duplication
    public function create($config = []): BaseObject
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
62
    {
63
64
        // Treat records as known data and set via config
65
        if ($config instanceof Record) {
66
            return $this->createFromRecord($config);
67
        }
68
69
        // Force Array
70
        if (!is_array($config)) {
71
            $config = ArrayHelper::toArray($config, [], false);
72
        }
73
74
        // Auto-set the class
75
        if ($class = static::objectClass()) {
76
            $config['class'] = $class;
77
        }
78
79
        return ObjectHelper::create(
80
            $config,
81
            static::objectClassInstance()
82
        );
83
84
    }
85
86
    /**
87
     * @param Record $record
88
     * @param string|null $toScenario
89
     * @throws InvalidConfigException
90
     * @return BaseObject
91
     */
92
    protected function createFromRecord(Record $record, string $toScenario = null): BaseObject
93
    {
94
95
        if (null !== $toScenario) {
96
            $record->setScenario($toScenario);
97
        }
98
99
        $config = $record->toArray();
100
101
        // Auto-set the class
102
        if ($class = static::objectClass()) {
103
            $config['class'] = $class;
104
        }
105
106
        return ObjectHelper::create(
107
            $config,
108
            static::objectClassInstance()
109
        );
110
111
    }
112
113
114
    /*******************************************
115
     * FIND/GET ALL
116
     *******************************************/
117
118
    /**
119
     * @param string $toScenario
120
     * @return BaseObject[]
121
     */
122 View Code Duplication
    public function findAll(string $toScenario = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123
    {
124
125
        // Check addToCache
126
        if (is_null($this->_cacheAll)) {
127
128
            $this->_cacheAll = [];
129
130
            // Find record in db
131
            if ($records = $this->findAllRecords()) {
132
133
                foreach ($records as $record) {
134
135
                    $this->_cacheAll[] = $this->findByRecord($record, $toScenario);
136
137
                }
138
139
            }
140
141
        }
142
143
        return $this->_cacheAll;
144
145
    }
146
147
    /**
148
     * @param string $toScenario
149
     * @return BaseObject[]
150
     * @throws ObjectNotFoundException
151
     */
152
    public function getAll(string $toScenario = null): array
153
    {
154
155
        if (!$objects = $this->findAll($toScenario)) {
156
157
            $this->notFoundException();
158
159
        }
160
161
        return $objects;
162
163
    }
164
165
    /*******************************************
166
     * FIND/GET
167
     *******************************************/
168
169
    /**
170
     * @param $identifier
171
     * @param string $toScenario
172
     * @return BaseObject|null
173
     */
174
    public function find($identifier, string $toScenario = null)
175
    {
176
177
        if ($identifier instanceof BaseObject) {
178
179
            $this->addToCache($identifier);
180
181
            return $identifier;
182
183
        } elseif ($identifier instanceof Record) {
184
185
            return $this->findByRecord($identifier, $toScenario);
186
187
        }
188
189
        return null;
190
191
    }
192
193
    /**
194
     * @param $identifier
195
     * @param string $toScenario
196
     * @return BaseObject
197
     * @throws ObjectNotFoundException
198
     */
199
    public function get($identifier, string $toScenario = null): BaseObject
200
    {
201
202
        // Find model by ID
203
        if (!$object = $this->find($identifier, $toScenario)) {
204
205
            $this->notFoundException();
206
207
        }
208
209
        return $object;
210
211
    }
212
213
    /*******************************************
214
     * FIND/GET BY QUERY
215
     *******************************************/
216
217
    /**
218
     * @param QueryInterface $query
219
     * @param string $toScenario
220
     * @return BaseObject[]
221
     */
222 View Code Duplication
    public function findAllByQuery(QueryInterface $query, string $toScenario = null): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
    {
224
225
        $objects = array();
226
227
        foreach ($query->all() as $record) {
228
            $objects[] = $this->findByRecord($record, $toScenario);
229
        }
230
231
        return $objects;
232
233
    }
234
235
    /**
236
     * @param QueryInterface $query
237
     * @param string $toScenario
238
     * @return BaseObject|null
239
     */
240 View Code Duplication
    public function findByQuery(QueryInterface $query, string $toScenario = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
    {
242
243
        /** @var Record $record */
244
        if (!$record = $query->one()) {
245
            return null;
246
        }
247
248
        return $this->findByRecord($record, $toScenario);
0 ignored issues
show
Documentation introduced by
$record is of type array|boolean, but the function expects a object<flipbox\spark\records\Record>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
249
250
    }
251
252
    /*******************************************
253
     * FIND/GET BY CONDITION
254
     *******************************************/
255
256
    /**
257
     * @param $condition
258
     * @param string $toScenario
259
     * @return BaseObject[]
260
     */
261 View Code Duplication
    public function findAllByCondition($condition, string $toScenario = null): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
262
    {
263
264
        $objects = [];
265
266
        // Find record in db
267
        if ($records = $this->findAllRecordsByCondition($condition)) {
268
269
            foreach ($records as $record) {
270
                $objects[] = $this->findByRecord($record, $toScenario);
271
            }
272
273
        }
274
275
        return $objects;
276
277
    }
278
279
    /**
280
     * @param $condition
281
     * @param string $toScenario
282
     * @return BaseObject[]
283
     * @throws ObjectNotFoundException
284
     */
285
    public function getAllByCondition($condition, string $toScenario = null): array
286
    {
287
288
        if (!$objects = $this->findAllByCondition($condition, $toScenario)) {
289
290
            $this->notFoundByConditionException($condition);
291
292
        }
293
294
        return $objects;
295
296
    }
297
298
    /**
299
     * @param $condition
300
     * @param string $toScenario
301
     * @return BaseObject|null
302
     */
303 View Code Duplication
    public function findByCondition($condition, string $toScenario = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
    {
305
306
        // Find record in db
307
        if ($record = $this->findRecordByCondition($condition)) {
308
            return $this->findByRecord($record, $toScenario);
309
        }
310
311
        return null;
312
313
    }
314
315
    /**
316
     * @param $condition
317
     * @param string $toScenario
318
     * @return BaseObject
319
     * @throws ObjectNotFoundException
320
     */
321
    public function getByCondition($condition, string $toScenario = null): BaseObject
322
    {
323
324
        if (!$object = $this->findByCondition($condition, $toScenario)) {
325
326
            $this->notFoundByConditionException($condition);
327
328
        }
329
330
        return $object;
331
332
    }
333
334
    /*******************************************
335
     * FIND/GET BY CRITERIA
336
     *******************************************/
337
338
    /**
339
     * @param $criteria
340
     * @param string $toScenario
341
     * @return BaseObject[]
342
     */
343 View Code Duplication
    public function findAllByCriteria($criteria, string $toScenario = null): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
344
    {
345
346
        $objects = [];
347
348
        // Find record in db
349
        if ($records = $this->findAllRecordsByCriteria($criteria)
350
        ) {
351
352
            foreach ($records as $record) {
353
                $objects[] = $this->findByRecord($record, $toScenario);
354
            }
355
356
        }
357
358
        return $objects;
359
360
    }
361
362
    /**
363
     * @param $criteria
364
     * @param string $toScenario
365
     * @return BaseObject[]
366
     * @throws ObjectNotFoundException
367
     */
368
    public function getAllByCriteria($criteria, string $toScenario = null): array
369
    {
370
371
        if (!$objects = $this->findAllByCriteria($criteria, $toScenario)) {
372
373
            $this->notFoundByCriteriaException($criteria);
374
375
        }
376
377
        return $objects;
378
379
    }
380
381
    /**
382
     * @param $criteria
383
     * @param string $toScenario
384
     * @return BaseObject|null
385
     */
386 View Code Duplication
    public function findByCriteria($criteria, string $toScenario = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
387
    {
388
389
        // Find record in db
390
        if ($record = $this->findRecordByCriteria($criteria)) {
391
            return $this->findByRecord($record, $toScenario);
392
        }
393
394
        return null;
395
396
    }
397
398
    /**
399
     * @param $criteria
400
     * @param string $toScenario
401
     * @return BaseObject
402
     * @throws ObjectNotFoundException
403
     */
404
    public function getByCriteria($criteria, string $toScenario = null): BaseObject
405
    {
406
407
        if (!$object = $this->findByCriteria($criteria, $toScenario)) {
408
409
            $this->notFoundByCriteriaException($criteria);
410
411
        }
412
413
        return $object;
414
415
    }
416
417
418
    /*******************************************
419
     * FIND/GET BY RECORD
420
     *******************************************/
421
422
    /**
423
     * @param Record $record
424
     * @param string $toScenario
425
     * @return BaseObject
426
     */
427 View Code Duplication
    public function findByRecord(Record $record, string $toScenario = null): BaseObject
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
428
    {
429
430
        // Check addToCache
431
        if (!$object = $this->findCacheByRecord($record)) {
432
433
            // New model
434
            $object = $this->createFromRecord($record, $toScenario);
435
436
            // Cache it
437
            $this->addToCache($object);
438
439
        }
440
441
        return $object;
442
443
    }
444
445
    /**
446
     * @param Record $record
447
     * @param string $toScenario
448
     * @return BaseObject
449
     */
450
    public function getByRecord(Record $record, string $toScenario = null): BaseObject
451
    {
452
        return $this->findByRecord($record, $toScenario);
453
    }
454
455
456
    /*******************************************
457
     * CACHE
458
     *******************************************/
459
460
    /**
461
     * @param $identifier
462
     * @return BaseObject|null
463
     */
464
    public function findCache($identifier)
465
    {
466
467
        if ($identifier instanceof Record) {
468
469
            return $this->findCacheByRecord($identifier);
470
471
        }
472
473
        return null;
474
475
    }
476
477
    /**
478
     * @param Record $record
479
     * @return BaseObject|null
480
     */
481
    public function findCacheByRecord(Record $record)
482
    {
483
        return null;
484
    }
485
486
    /**
487
     * @param BaseObject $object
488
     * @return static
489
     */
490
    public function addToCache(BaseObject $object)
491
    {
492
        return $this;
493
    }
494
495
496
    /*******************************************
497
     * EXCEPTIONS
498
     *******************************************/
499
500
    /**
501
     * @throws ObjectNotFoundException
502
     */
503
    protected function notFoundException()
504
    {
505
506
        throw new ObjectNotFoundException(
507
            sprintf(
508
                "Object does not exist."
509
            )
510
        );
511
512
    }
513
514
    /**
515
     * @param null $criteria
516
     * @throws ObjectNotFoundException
517
     */
518
    protected function notFoundByCriteriaException($criteria = null)
519
    {
520
521
        throw new ObjectNotFoundException(
522
            sprintf(
523
                'Object does not exist with the criteria "%s".',
524
                (string)JsonHelper::encode($criteria)
525
            )
526
        );
527
528
    }
529
530
    /**
531
     * @param null $condition
532
     * @throws ObjectNotFoundException
533
     */
534
    protected function notFoundByConditionException($condition = null)
535
    {
536
537
        throw new ObjectNotFoundException(
538
            sprintf(
539
                'Object does not exist with the condition "%s".',
540
                (string)JsonHelper::encode($condition)
541
            )
542
        );
543
544
    }
545
546
}
547