Passed
Push — master ( e00e24...e046f3 )
by Nate
06:00 queued 02:00
created

Element   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 355
Duplicated Lines 9.86 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 9
dl 35
loc 355
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
elementClass() 0 1 ?
A elementClassInstance() 0 4 1
A create() 0 13 1
B find() 24 24 4
B findById() 0 24 3
A get() 0 13 2
A getById() 0 13 2
A freshFindById() 0 4 1
A freshGetById() 0 12 2
A getQuery() 0 18 1
A findCache() 0 12 2
A addToCache() 0 8 1
A findCacheById() 0 16 2
A isCachedById() 11 11 2
A cacheById() 0 20 2
A notFoundException() 0 10 1
A notFoundByIdException() 0 11 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * @package    Spark
5
 * @author     Flipbox Factory <[email protected]>
6
 * @copyright  2010-2016 Flipbox Digital Limited
7
 * @license    https://github.com/FlipboxFactory/Craft3-Spark/blob/master/LICENSE
8
 * @link       https://github.com/FlipboxFactory/Craft3-Spark
9
 * @since      Class available since Release 1.1.0
10
 */
11
12
namespace flipbox\spark\services;
13
14
use Craft;
15
use craft\base\Element as BaseElement;
16
use craft\base\ElementInterface;
17
use craft\elements\db\ElementQueryInterface;
18
use flipbox\spark\exceptions\ElementNotFoundException;
19
use flipbox\spark\helpers\ElementHelper;
20
use flipbox\spark\helpers\QueryHelper;
21
use flipbox\spark\helpers\SiteHelper;
22
use yii\base\Component as BaseComponent;
23
24
abstract class Element extends BaseComponent
25
{
26
27
    /**
28
     * @var [ElementInterface[]]
29
     */
30
    protected $_cacheById = [];
31
32
    /*******************************************
33
     * ELEMENT CLASSES
34
     *******************************************/
35
36
    /**
37
     * @return string
38
     */
39
    public abstract static function elementClass(): string;
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
40
41
    /**
42
     * The element instance that this class interacts with
43
     *
44
     * @return string
45
     */
46
    public static function elementClassInstance(): string
47
    {
48
        return ElementInterface::class;
49
    }
50
51
    /*******************************************
52
     * CREATE
53
     *******************************************/
54
55
    /**
56
     * @param array $config
57
     * @return BaseElement|ElementInterface
58
     */
59
    public function create(array $config = [])
60
    {
61
62
        // Set the class the element should be
63
        $config['class'] = static::elementClass();
64
65
        // Create new model
66
        return ElementHelper::create(
67
            $config,
68
            static::elementClassInstance()
69
        );
70
71
    }
72
73
74
    /**
75
     * @param $identifier
76
     * @param int|null $siteId
77
     * @return BaseElement|ElementInterface|null
78
     */
79 View Code Duplication
    public function find($identifier, int $siteId = null)
1 ignored issue
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...
80
    {
81
82
        if ($identifier instanceof ElementInterface) {
83
84
            $this->addToCache($identifier);
85
86
            return $identifier;
87
88
        } elseif (is_numeric($identifier)) {
89
90
            return $this->findById($identifier, $siteId);
91
92
        } elseif (is_array($identifier)) {
93
94
            return $this->getQuery($identifier)
95
                ->siteId($siteId)
96
                ->one();
97
98
        }
99
100
        return null;
101
102
    }
103
104
    /**
105
     * @param int $id
106
     * @param int|null $siteId
107
     * @return BaseElement|ElementInterface|null
108
     */
109
    public function findById(int $id, int $siteId = null)
110
    {
111
112
        // Check cache
113
        if (!$element = $this->findCacheById($id, $siteId)) {
114
115
            // Find new element
116
            if ($element = $this->freshFindById($id, $siteId)) {
117
118
                // Cache it
119
                $this->addToCache($element);
120
121
            } else {
122
123
                // Cache nothing
124
                $this->_cacheById[$id] = $element;
125
126
            }
127
128
        }
129
130
        return $element;
131
132
    }
133
134
    /*******************************************
135
     * GET
136
     *******************************************/
137
138
    /**
139
     * @param $identifier
140
     * @param int|null $siteId
141
     * @return BaseElement|ElementInterface
142
     * @throws ElementNotFoundException
143
     */
144
    public function get($identifier, int $siteId = null)
145
    {
146
147
        // Find
148
        if (!$elemeny = $this->find($identifier, $siteId)) {
149
150
            $this->notFoundException();
151
152
        }
153
154
        return $elemeny;
155
156
    }
157
158
    /**
159
     * @param int $id
160
     * @param int|null $siteId
161
     * @return BaseElement|ElementInterface
162
     * @throws ElementNotFoundException
163
     */
164
    public function getById(int $id, int $siteId = null)
165
    {
166
167
        // Find by ID
168
        if (!$element = $this->findById($id, $siteId)) {
169
170
            $this->notFoundByIdException($id);
171
172
        }
173
174
        return $element;
175
176
    }
177
178
    /*******************************************
179
     * FRESH FIND
180
     *******************************************/
181
182
    /**
183
     * @param int $id
184
     * @param int|null $siteId
185
     * @return BaseElement|ElementInterface|null
186
     */
187
    public function freshFindById(int $id, int $siteId = null)
188
    {
189
        return Craft::$app->getElements()->getElementById($id, static::elementClass(), $siteId);
190
    }
191
192
    /**
193
     * @param $id
194
     * @param int|null $siteId
195
     * @return BaseElement|ElementInterface
196
     * @throws ElementNotFoundException
197
     */
198
    public function freshGetById($id, int $siteId = null)
199
    {
200
201
        if (!$element = $this->freshFindById($id, $siteId)) {
202
203
            $this->notFoundByIdException($id);
204
205
        }
206
207
        return $element;
208
209
    }
210
211
212
    /*******************************************
213
     * QUERY
214
     *******************************************/
215
216
    /**
217
     * Get query
218
     *
219
     * @param $criteria
220
     * @return ElementQueryInterface
221
     */
222
    public function getQuery($criteria = [])
223
    {
224
225
        /** @var ElementInterface $elementClass */
226
        $elementClass = static::elementClass();
227
228
        /** @var ElementQueryInterface $query */
229
        $query = $elementClass::find();
230
231
        // Configure it
232
        QueryHelper::configure(
233
            $query,
234
            $criteria
235
        );
236
237
        return $query;
238
239
    }
240
241
    /*******************************************
242
     * CACHE
243
     *******************************************/
244
245
    /**
246
     * @param $identifier
247
     * @param int|null $siteId
248
     * @return BaseElement|ElementInterface|null
249
     */
250
    public function findCache($identifier, int $siteId = null)
251
    {
252
253
        if (is_numeric($identifier)) {
254
255
            return $this->findCacheById($identifier, $siteId);
256
257
        }
258
259
        return null;
260
261
    }
262
263
    /**
264
     * @param ElementInterface $element
265
     * @return $this
266
     */
267
    public function addToCache(ElementInterface $element)
268
    {
269
270
        $this->cacheById($element);
271
272
        return $this;
273
274
    }
275
276
    /**
277
     * Find an existing cache by ID
278
     *
279
     * @param int $id
280
     * @param int|null $siteId
281
     * @return BaseElement|ElementInterface|null
282
     */
283
    public function findCacheById(int $id, int $siteId = null)
284
    {
285
286
        // Resolve siteId
287
        $siteId = SiteHelper::resolveSiteId($siteId);
288
289
        // Check if already in addToCache
290
        if ($this->isCachedById($id, $siteId)) {
291
292
            return $this->_cacheById[$siteId][$id];
293
294
        }
295
296
        return null;
297
298
    }
299
300
    /**
301
     * Identify whether in cached by ID
302
     *
303
     * @param int $id
304
     * @param int|null $siteId
305
     * @return bool
306
     */
307 View Code Duplication
    protected function isCachedById(int $id, int $siteId = 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...
308
    {
309
        // Resolve siteId
310
        $siteId = SiteHelper::resolveSiteId($siteId);
311
312
        if (!isset($this->_cacheById[$siteId])) {
313
            $this->_cacheById[$siteId] = [];
314
        }
315
316
        return array_key_exists($id, $this->_cacheById[$siteId]);
317
    }
318
319
    /**
320
     * @param ElementInterface $element
321
     * @return $this
322
     */
323
    protected function cacheById(ElementInterface $element)
324
    {
325
326
        /** @var BaseElement $element */
327
328
        $id = $element->id;
329
330
        $siteId = $element->siteId;
331
332
        // Check if already in cache
333
        if (!$this->isCachedById($id, $siteId)) {
334
335
            // Cache it
336
            $this->_cacheById[$siteId][$id] = $element;
337
338
        }
339
340
        return $this;
341
342
    }
343
344
    /*******************************************
345
     * EXCEPTIONS
346
     *******************************************/
347
348
    /**
349
     * @throws ElementNotFoundException
350
     */
351
    protected function notFoundException()
352
    {
353
354
        throw new ElementNotFoundException(
355
            sprintf(
356
                "Element does not exist."
357
            )
358
        );
359
360
    }
361
362
    /**
363
     * @param int|null $id
364
     * @throws ElementNotFoundException
365
     */
366
    protected function notFoundByIdException(int $id = null)
367
    {
368
369
        throw new ElementNotFoundException(
370
            sprintf(
371
                'Element does not exist with the id "%s".',
372
                (string)$id
373
            )
374
        );
375
376
    }
377
378
}
379