1 | <?php |
||
37 | class DataOperations |
||
38 | { |
||
39 | /** |
||
40 | * @var RecordWrapper |
||
41 | */ |
||
42 | private $wrapper; |
||
43 | |||
44 | /** |
||
45 | * Private instance of driver adapter. |
||
46 | * |
||
47 | * @var DriverAdapter |
||
48 | */ |
||
49 | private $adapter; |
||
50 | |||
51 | /** |
||
52 | * Copy of data to be manipulated in the operations. |
||
53 | * |
||
54 | * @var array |
||
55 | */ |
||
56 | private $data; |
||
57 | |||
58 | /** |
||
59 | * Fields that contained errors after save or update operations were performed. |
||
60 | * |
||
61 | * @var array |
||
62 | */ |
||
63 | private $invalidFields = []; |
||
64 | |||
65 | /** |
||
66 | * Set to true when the model holds multiple records. |
||
67 | * |
||
68 | * @var bool |
||
69 | */ |
||
70 | private $hasMultipleData; |
||
71 | |||
72 | /** |
||
73 | * An instance of the atiaa driver. |
||
74 | * |
||
75 | * @var Driver |
||
76 | */ |
||
77 | private $driver; |
||
78 | |||
79 | /** |
||
80 | * Used to indicate save operation is in save mode to create new items. |
||
81 | */ |
||
82 | const MODE_SAVE = 0; |
||
83 | |||
84 | /** |
||
85 | * Used to indicate save operation is in update mode to update existing items. |
||
86 | */ |
||
87 | const MODE_UPDATE = 1; |
||
88 | |||
89 | /** |
||
90 | * Create a new instance. |
||
91 | * |
||
92 | * @param \ntentan\nibii\RecordWrapper $wrapper |
||
93 | * @param Driver $driver |
||
94 | */ |
||
95 | 34 | public function __construct(RecordWrapper $wrapper, Driver $driver) |
|
101 | |||
102 | /** |
||
103 | * Perform the model save command. |
||
104 | * |
||
105 | * @param bool $hasMultipleData |
||
106 | * |
||
107 | * @return bool |
||
108 | */ |
||
109 | 10 | public function doSave(bool $hasMultipleData): bool |
|
147 | |||
148 | /** |
||
149 | * @return bool|array |
||
150 | */ |
||
151 | public function doValidate() |
||
159 | |||
160 | /** |
||
161 | * Save an individual record. |
||
162 | * |
||
163 | * @param array $record The record to be saved |
||
164 | * @param array $primaryKey The primary keys of the record |
||
165 | * |
||
166 | * @return array |
||
167 | */ |
||
168 | 10 | private function saveRecord(array &$record, array $primaryKey): array |
|
169 | { |
||
170 | $status = [ |
||
171 | 10 | 'success' => true, |
|
172 | 'pk_assigned' => null, |
||
173 | 'invalid_fields' => [], |
||
174 | ]; |
||
175 | |||
176 | // Determine if the primary key of the record is set. |
||
177 | 10 | $pkSet = $this->isPrimaryKeySet($primaryKey, $record); |
|
178 | |||
179 | // Reset the data in the model to contain only the data to be saved |
||
180 | 10 | $this->wrapper->setData($record); |
|
181 | |||
182 | // Execute all callbacks on the model |
||
183 | 10 | $this->wrapper->preSaveCallback(); |
|
184 | 10 | if ($pkSet) { |
|
185 | 2 | $this->wrapper->preUpdateCallback(); |
|
186 | } else { |
||
187 | 8 | $this->wrapper->preCreateCallback(); |
|
188 | } |
||
189 | |||
190 | // Validate the data |
||
191 | 10 | $validity = $this->validate($pkSet ? self::MODE_UPDATE : self::MODE_SAVE); |
|
192 | |||
193 | // Exit if data is invalid |
||
194 | 10 | if ($validity !== true) { |
|
195 | 4 | $status['invalid_fields'] = $validity; |
|
196 | 4 | $status['success'] = false; |
|
197 | |||
198 | 4 | return $status; |
|
199 | } |
||
200 | |||
201 | 6 | $record = $this->wrapper->getData(); |
|
202 | 6 | $record = reset($record) === false ? [] : reset($record); |
|
203 | |||
204 | // Save any relationships that are attached to the data |
||
205 | 6 | $relationships = $this->wrapper->getDescription()->getRelationships(); |
|
206 | 6 | $relationshipsWithData = []; |
|
207 | |||
208 | 6 | foreach ($relationships ?? [] as $model => $relationship) { |
|
209 | 6 | if (isset($record[$model])) { |
|
210 | $relationship->preSave($record, $record[$model]); |
||
211 | $relationshipsWithData[$model] = $relationship; |
||
212 | } |
||
213 | } |
||
214 | |||
215 | // Assign the data to the wrapper again |
||
216 | 6 | $this->wrapper->setData($record); |
|
217 | |||
218 | // Update or save the data and run post callbacks |
||
219 | 6 | if ($pkSet) { |
|
220 | 2 | $this->adapter->update($record); |
|
221 | 2 | $this->wrapper->postUpdateCallback(); |
|
222 | } else { |
||
223 | 4 | $this->adapter->insert($record); |
|
224 | 4 | $keyValue = $this->driver->getLastInsertId(); |
|
225 | 4 | $this->wrapper->{$primaryKey[0]} = $keyValue; |
|
226 | 4 | $this->wrapper->postCreateCallback($keyValue); |
|
227 | } |
||
228 | 6 | $this->wrapper->postSaveCallback(); |
|
229 | |||
230 | // Reset the data so it contains any modifications made by callbacks |
||
231 | 6 | $record = $this->wrapper->getData()[0]; |
|
232 | 6 | foreach ($relationshipsWithData as $model => $relationship) { |
|
233 | $relationship->postSave($record); |
||
234 | } |
||
235 | |||
236 | 6 | return $status; |
|
237 | } |
||
238 | |||
239 | /** |
||
240 | * @param int $mode |
||
241 | * |
||
242 | * @return bool|array |
||
243 | */ |
||
244 | 10 | private function validate(int $mode) |
|
269 | |||
270 | /** |
||
271 | * @param string|array $primaryKey |
||
272 | * @param array $data |
||
273 | * |
||
274 | * @return bool |
||
275 | */ |
||
276 | 10 | private function isPrimaryKeySet($primaryKey, array $data) : bool |
|
289 | |||
290 | /** |
||
291 | * @param mixed $property |
||
292 | * @param mixed $value |
||
293 | */ |
||
294 | 4 | private function assignValue(&$property, $value) : void |
|
302 | |||
303 | /** |
||
304 | * @return array |
||
305 | */ |
||
306 | public function getData() : array |
||
310 | |||
311 | /** |
||
312 | * @return array |
||
313 | */ |
||
314 | 10 | public function getInvalidFields() : array |
|
318 | |||
319 | /** |
||
320 | * @param string $primaryKey |
||
321 | * @param array $data |
||
322 | * |
||
323 | * @return bool |
||
324 | */ |
||
325 | public function isItemDeletable(string $primaryKey, array $data) : bool |
||
333 | } |
||
334 |