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\traits; |
10
|
|
|
|
11
|
|
|
use flipbox\spark\exceptions\ModelNotFoundException; |
12
|
|
|
use flipbox\spark\exceptions\RecordNotFoundException; |
13
|
|
|
use flipbox\spark\models\Model as BaseModel; |
14
|
|
|
use flipbox\spark\models\ModelWithId; |
15
|
|
|
use flipbox\spark\records\Record; |
16
|
|
|
use flipbox\spark\records\RecordWithId; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* @author Flipbox Factory <[email protected]> |
20
|
|
|
* @since 1.2.0 |
21
|
|
|
* |
22
|
|
|
* @method RecordWithId|null findRecordByCondition($condition, string $toScenario = null) |
23
|
|
|
*/ |
24
|
|
|
trait ModelById |
25
|
|
|
{ |
26
|
|
|
|
27
|
|
|
use Model; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var ModelWithId[] |
31
|
|
|
*/ |
32
|
|
|
protected $_cacheById = []; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @param Record $record |
36
|
|
|
* @param string|null $toScenario |
37
|
|
|
* @return BaseModel|ModelWithId |
38
|
|
|
*/ |
39
|
|
|
abstract protected function findByRecord(Record $record, string $toScenario = null): BaseModel; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @param array $config |
43
|
|
|
* @param string|null $toScenario |
44
|
|
|
* @return BaseModel|ModelWithId |
45
|
|
|
*/ |
46
|
|
|
abstract public function create($config = [], string $toScenario = null): BaseModel; |
47
|
|
|
|
48
|
|
|
/******************************************* |
49
|
|
|
* FIND/GET BY ID |
50
|
|
|
*******************************************/ |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param int $id |
54
|
|
|
* @param string|null $toScenario |
55
|
|
|
* @return ModelWithId|null |
56
|
|
|
*/ |
57
|
|
View Code Duplication |
public function findById(int $id, string $toScenario = null) |
|
|
|
|
58
|
|
|
{ |
59
|
|
|
|
60
|
|
|
// Check cache |
61
|
|
|
if (!$model = $this->findCacheById($id)) { |
|
|
|
|
62
|
|
|
|
63
|
|
|
// Find record in db |
64
|
|
|
if ($record = $this->findRecordById($id)) { |
65
|
|
|
|
66
|
|
|
$model = $this->findByRecord($record, $toScenario); |
67
|
|
|
|
68
|
|
|
} else { |
69
|
|
|
|
70
|
|
|
$this->_cacheById[$id] = null; |
71
|
|
|
|
72
|
|
|
return null; |
73
|
|
|
|
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
return $model; |
79
|
|
|
|
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @param int $id |
84
|
|
|
* @param string|null $toScenario |
85
|
|
|
* @return ModelWithId|null |
86
|
|
|
* @throws ModelNotFoundException |
87
|
|
|
*/ |
88
|
|
View Code Duplication |
public function getById(int $id, string $toScenario = null): ModelWithId |
|
|
|
|
89
|
|
|
{ |
90
|
|
|
|
91
|
|
|
if (!$model = $this->findById($id, $toScenario)) { |
92
|
|
|
|
93
|
|
|
$this->notFoundByIdException($id); |
94
|
|
|
|
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $model; |
98
|
|
|
|
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @param int $id |
103
|
|
|
* @param string|null $toScenario |
104
|
|
|
* @return ModelWithId|null |
105
|
|
|
*/ |
106
|
|
|
public function freshFindById(int $id, string $toScenario = null) |
107
|
|
|
{ |
108
|
|
|
|
109
|
|
|
// Find record in db |
110
|
|
|
if (!$record = $this->findRecordById($id)) { |
111
|
|
|
return null; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
$model = $this->create($record, $toScenario); |
|
|
|
|
115
|
|
|
|
116
|
|
|
return $model; |
117
|
|
|
|
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* @param int $id |
122
|
|
|
* @param string|null $toScenario |
123
|
|
|
* @return ModelWithId |
124
|
|
|
* @throws ModelNotFoundException |
125
|
|
|
*/ |
126
|
|
View Code Duplication |
public function freshGetById(int $id, string $toScenario = null): ModelWithId |
|
|
|
|
127
|
|
|
{ |
128
|
|
|
|
129
|
|
|
if (!$model = $this->freshFindById($id, $toScenario)) { |
130
|
|
|
|
131
|
|
|
$this->notFoundByIdException($id); |
132
|
|
|
|
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
return $model; |
136
|
|
|
|
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/******************************************* |
140
|
|
|
* CACHE |
141
|
|
|
*******************************************/ |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Find an existing cache by id |
145
|
|
|
* |
146
|
|
|
* @param int $id |
147
|
|
|
* @return null |
148
|
|
|
*/ |
149
|
|
|
public function findCacheById(int $id) |
150
|
|
|
{ |
151
|
|
|
|
152
|
|
|
// Check if already in cache |
153
|
|
|
if (!$this->isCachedById($id)) { |
154
|
|
|
return null; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
return $this->_cacheById[$id]; |
158
|
|
|
|
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Identify whether in cache by id |
163
|
|
|
* |
164
|
|
|
* @param int $id |
165
|
|
|
* @return bool |
166
|
|
|
*/ |
167
|
|
|
private function isCachedById(int $id): bool |
168
|
|
|
{ |
169
|
|
|
return array_key_exists($id, $this->_cacheById); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* @param ModelWithId $model |
175
|
|
|
* @return static |
176
|
|
|
*/ |
177
|
|
|
protected function cacheById(ModelWithId $model) |
178
|
|
|
{ |
179
|
|
|
|
180
|
|
|
if (null === $model->getId()) { |
181
|
|
|
return $this; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
// Check if already in cache |
185
|
|
|
if (!$this->isCachedById($model->getId())) { |
186
|
|
|
|
187
|
|
|
// Cache it |
188
|
|
|
$this->_cacheById[$model->getId()] = $model; |
189
|
|
|
|
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
return $this; |
193
|
|
|
|
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @param RecordWithId $record |
198
|
|
|
* @return ModelWithId|null |
199
|
|
|
*/ |
200
|
|
|
protected function findCacheByRecordById(RecordWithId $record) |
201
|
|
|
{ |
202
|
|
|
|
203
|
|
|
$value = $record->id; |
204
|
|
|
|
205
|
|
|
if ($value === null) { |
206
|
|
|
return null; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
return $this->findCacheById($value); |
210
|
|
|
|
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/******************************************* |
214
|
|
|
* RECORD BY ID |
215
|
|
|
*******************************************/ |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @param int $id |
219
|
|
|
* @param string|null $toScenario |
220
|
|
|
* @return RecordWithId|null |
221
|
|
|
*/ |
222
|
|
|
public function findRecordById(int $id, string $toScenario = null) |
223
|
|
|
{ |
224
|
|
|
|
225
|
|
|
return $this->findRecordByCondition( |
226
|
|
|
[ |
227
|
|
|
'id' => $id |
228
|
|
|
], |
229
|
|
|
$toScenario |
230
|
|
|
); |
231
|
|
|
|
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* @param int $id |
236
|
|
|
* @param string|null $toScenario |
237
|
|
|
* @return RecordWithId|null |
238
|
|
|
*/ |
239
|
|
|
public function getRecordById(int $id, string $toScenario = null) |
240
|
|
|
{ |
241
|
|
|
|
242
|
|
|
if (!$record = $this->findRecordById($id, $toScenario)) { |
243
|
|
|
|
244
|
|
|
$this->notFoundRecordByIdException($id); |
245
|
|
|
|
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
return $record; |
249
|
|
|
|
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* @param ModelWithId $model |
255
|
|
|
* @param bool $mirrorScenario |
256
|
|
|
* @return RecordWithId |
257
|
|
|
*/ |
258
|
|
|
protected function toRecordById(ModelWithId $model, bool $mirrorScenario = true): RecordWithId |
259
|
|
|
{ |
260
|
|
|
|
261
|
|
|
// Get record |
262
|
|
|
if (!$record = $this->findRecordById($model->getId())) { |
263
|
|
|
return null; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
// Populate the record attributes |
267
|
|
|
$this->transferToRecord($model, $record, $mirrorScenario); |
268
|
|
|
|
269
|
|
|
return $record; |
270
|
|
|
|
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/******************************************* |
274
|
|
|
* EXCEPTIONS |
275
|
|
|
*******************************************/ |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* @param int|null $id |
279
|
|
|
* @throws ModelNotFoundException |
280
|
|
|
*/ |
281
|
|
|
protected function notFoundByIdException(int $id = null) |
282
|
|
|
{ |
283
|
|
|
|
284
|
|
|
throw new ModelNotFoundException( |
285
|
|
|
sprintf( |
286
|
|
|
'Model does not exist with the id "%s".', |
287
|
|
|
(string)$id |
288
|
|
|
) |
289
|
|
|
); |
290
|
|
|
|
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* @param int|null $id |
295
|
|
|
* @throws RecordNotFoundException |
296
|
|
|
*/ |
297
|
|
|
protected function notFoundRecordByIdException(int $id = null) |
298
|
|
|
{ |
299
|
|
|
|
300
|
|
|
throw new RecordNotFoundException( |
301
|
|
|
sprintf( |
302
|
|
|
'Record does not exist with the id "%s".', |
303
|
|
|
(string)$id |
304
|
|
|
) |
305
|
|
|
); |
306
|
|
|
|
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
} |
310
|
|
|
|
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.