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

ModelByHandle::isCachedByHandle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 2
nop 1
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.0.0
10
 */
11
12
namespace flipbox\spark\services;
13
14
use flipbox\spark\exceptions\ModelNotFoundException;
15
use flipbox\spark\models\Model as BaseModel;
16
use flipbox\spark\models\ModelWithHandle;
17
use flipbox\spark\records\Record;
18
use flipbox\spark\records\RecordWithHandle;
19
20
abstract class ModelByHandle extends Model
21
{
22
23
    /**
24
     * @var ModelWithHandle[]
25
     */
26
    protected $_cacheByHandle = [];
27
28
    /**
29
     * @return string
30
     */
31
    public static function modelClassInstance(): string
32
    {
33
        return ModelWithHandle::class;
34
    }
35
36
    /**
37
     * @param $identifier
38
     * @param string $toScenario
39
     * @return BaseModel|ModelWithHandle|null
40
     */
41 View Code Duplication
    public function find($identifier, string $toScenario = 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...
42
    {
43
44
        if (is_string($identifier)) {
45
46
            return $this->findByHandle($identifier, $toScenario);
47
48
        }
49
50
        return parent::find($identifier, $toScenario);
51
52
    }
53
54
55
    /*******************************************
56
     * FIND/GET BY HANDLE
57
     *******************************************/
58
59
    /**
60
     * @param string $handle
61
     * @param string|null $toScenario
62
     * @return ModelWithHandle|null
63
     */
64 View Code Duplication
    public function findByHandle(string $handle, 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...
65
    {
66
67
        // Check cache
68
        if (!$model = $this->findCacheByHandle($handle)) {
69
70
            // Find record in db
71
            if ($record = $this->findRecordByHandle($handle)) {
72
73
                /** @var ModelWithHandle $model */
74
                $model = $this->findByRecord($record, $toScenario);
75
76
            } else {
77
78
                $this->_cacheByHandle[$handle] = null;
79
80
                return null;
81
82
            }
83
84
        }
85
86
        return $model;
87
88
    }
89
90
    /**
91
     * @param string $handle
92
     * @param string|null $toScenario
93
     * @return ModelWithHandle|null
94
     * @throws ModelNotFoundException
95
     */
96 View Code Duplication
    public function getByHandle(string $handle, string $toScenario = null): ModelWithHandle
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...
97
    {
98
99
        if (!$model = $this->findByHandle($handle, $toScenario)) {
100
101
            $this->notFoundByHandleException($handle);
102
103
        }
104
105
        return $model;
106
107
    }
108
109
    /**
110
     * @param string $handle
111
     * @param string|null $toScenario
112
     * @return ModelWithHandle|null
113
     */
114
    public function freshFindByHandle(string $handle, string $toScenario = null)
115
    {
116
117
        // Find record in db
118
        if (!$record = $this->findRecordByHandle($handle)) {
119
            return null;
120
        }
121
122
        /** @var ModelWithHandle $model */
123
        $model = $this->create($record, $toScenario);
0 ignored issues
show
Documentation introduced by
$record is of type object<flipbox\spark\records\RecordWithHandle>, but the function expects a array.

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...
124
125
        return $model;
126
127
    }
128
129
    /**
130
     * @param string $handle
131
     * @param string|null $toScenario
132
     * @return ModelWithHandle
133
     * @throws ModelNotFoundException
134
     */
135 View Code Duplication
    public function freshGetByHandle(string $handle, string $toScenario = null): ModelWithHandle
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...
136
    {
137
138
        if (!$model = $this->freshFindByHandle($handle, $toScenario)) {
139
140
            $this->notFoundByHandleException($handle);
141
142
        }
143
144
        return $model;
145
146
    }
147
148
    /*******************************************
149
     * CACHE
150
     *******************************************/
151
152
    /**
153
     * @inheritdoc
154
     * @return BaseModel|ModelWithHandle|null
155
     */
156
    public function findCache($identifier)
157
    {
158
159
        if (is_string($identifier)) {
160
161
            return $this->findCacheByHandle($identifier);
162
163
        }
164
165
        return parent::findCache($identifier);
166
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172
    public function addToCache(BaseModel $model)
173
    {
174
175
        if ($model instanceof ModelWithHandle) {
176
177
            $this->cacheByHandle($model);
178
179
        }
180
181
        return parent::addToCache($model);
182
183
    }
184
185
    /**
186
     * Find an existing cache by handle
187
     *
188
     * @param string $handle
189
     * @return null
190
     */
191
    public function findCacheByHandle(string $handle)
192
    {
193
194
        // Check if already in addToCache
195
        if (!$this->isCachedByHandle($handle)) {
196
            return null;
197
        }
198
199
        return $this->_cacheByHandle[$handle];
200
201
    }
202
203
    /**
204
     * Identify whether in cache by handle
205
     *
206
     * @param string $handle
207
     * @return bool
208
     */
209
    private function isCachedByHandle(string $handle): bool
210
    {
211
        return array_key_exists($handle, $this->_cacheByHandle);
212
    }
213
214
    /**
215
     * @param ModelWithHandle $model
216
     * @return static
217
     */
218
    protected function cacheByHandle(ModelWithHandle $model)
219
    {
220
221
        // Check if already in cache
222
        if (!$this->isCachedByHandle($model->handle)) {
223
224
            // Cache it
225
            $this->_cacheByHandle[$model->handle] = $model;
226
227
        }
228
229
        return $this;
230
231
    }
232
233
    /**
234
     * @param Record $record
235
     * @return BaseModel|ModelWithHandle|null
236
     */
237 View Code Duplication
    public function findCacheByRecord(Record $record)
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...
238
    {
239
240
        if ($record instanceof RecordWithHandle) {
241
242
            // Check if already in cache by id
243
            if (!$this->isCachedByHandle($record->handle)) {
244
245
                return $this->findCacheByHandle($record->handle);
246
247
            }
248
249
        }
250
251
        return parent::findCacheByRecord($record);
252
253
    }
254
255
    /*******************************************
256
     * RECORD BY HANDLE
257
     *******************************************/
258
259
    /**
260
     * @param string $handle
261
     * @param string|null $toScenario
262
     * @return RecordWithHandle|null
263
     */
264
    protected function findRecordByHandle(string $handle, string $toScenario = null)
265
    {
266
267
        return $this->findRecordByCondition(
268
            [
269
                'handle' => $handle
270
            ],
271
            $toScenario
272
        );
273
274
    }
275
276
277
    /**
278
     * @param BaseModel $model
279
     * @param bool $mirrorScenario
280
     * @return RecordWithHandle|Record
281
     */
282
    public function toRecord(BaseModel $model, bool $mirrorScenario = true): Record
283
    {
284
285
        // Get existing record
286
        if ($model instanceof ModelWithHandle) {
287
288
            if ($record = $this->getRecordByCondition([
289
                'handle' => $model->handle
290
            ])
291
            ) {
292
293
                // Populate the record attributes
294
                $this->transferToRecord($model, $record, $mirrorScenario);
295
296
                return $record;
297
298
            }
299
300
        }
301
302
        return parent::toRecord($model, $mirrorScenario);
303
304
    }
305
306
    /*******************************************
307
     * EXCEPTIONS
308
     *******************************************/
309
310
    /**
311
     * @param string|null $handle
312
     * @throws ModelNotFoundException
313
     */
314
    protected function notFoundByHandleException(string $handle = null)
315
    {
316
317
        throw new ModelNotFoundException(
318
            sprintf(
319
                'Model does not exist with the handle "%s".',
320
                (string)$handle
321
            )
322
        );
323
324
    }
325
326
}
327