|
1
|
|
|
<?php |
|
2
|
|
|
namespace Suricate; |
|
3
|
|
|
|
|
4
|
|
|
/** |
|
5
|
|
|
* DBObject, Pseudo ORM Class |
|
6
|
|
|
* |
|
7
|
|
|
* Two types of variables are available : |
|
8
|
|
|
* - $dbVariables, an array of fields contained in linked SQL table |
|
9
|
|
|
* - $protectedVariables, an array of variables not stored in SQL |
|
10
|
|
|
* that can be triggered on access |
|
11
|
|
|
* |
|
12
|
|
|
* @package Suricate |
|
13
|
|
|
* @author Mathieu LESNIAK <[email protected]> |
|
14
|
|
|
*/ |
|
15
|
|
|
|
|
16
|
|
|
class DBObject implements Interfaces\IDBObject |
|
17
|
|
|
{ |
|
18
|
|
|
/* |
|
19
|
|
|
* @const TABLE_NAME : Linked SQL Table |
|
20
|
|
|
*/ |
|
21
|
|
|
const TABLE_NAME = ''; |
|
22
|
|
|
|
|
23
|
|
|
/* |
|
24
|
|
|
* @const TABLE_INDEX : Unique Id of the SQL Table |
|
25
|
|
|
*/ |
|
26
|
|
|
const TABLE_INDEX = ''; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* @const DB_CONFIG : Database configuration identifier |
|
30
|
|
|
*/ |
|
31
|
|
|
const DB_CONFIG = ''; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* @const RELATION_ONE_ONE : Relation one to one |
|
35
|
|
|
*/ |
|
36
|
|
|
const RELATION_ONE_ONE = 1; |
|
37
|
|
|
/** |
|
38
|
|
|
* @const RELATION_ONE_MANY : Relation one to many |
|
39
|
|
|
*/ |
|
40
|
|
|
const RELATION_ONE_MANY = 2; |
|
41
|
|
|
/** |
|
42
|
|
|
* @const RELATION_MANY_MANY : Relation many to many |
|
43
|
|
|
*/ |
|
44
|
|
|
const RELATION_MANY_MANY = 3; |
|
45
|
|
|
|
|
46
|
|
|
protected $dbVariables = []; |
|
47
|
|
|
protected $dbValues = []; |
|
48
|
|
|
|
|
49
|
|
|
protected $protectedVariables = []; |
|
50
|
|
|
protected $protectedValues = []; |
|
51
|
|
|
protected $loadedProtectedVariables = []; |
|
52
|
|
|
|
|
53
|
|
|
protected $readOnlyVariables = []; |
|
54
|
|
|
|
|
55
|
|
|
protected $relations = []; |
|
56
|
|
|
protected $relationValues = []; |
|
57
|
|
|
protected $loadedRelations = []; |
|
58
|
|
|
|
|
59
|
|
|
protected $dbLink = false; |
|
60
|
|
|
|
|
61
|
|
|
protected $validatorMessages = []; |
|
62
|
|
|
|
|
63
|
|
|
|
|
64
|
|
|
public function __construct() |
|
65
|
|
|
{ |
|
66
|
|
|
$this->setRelations(); |
|
67
|
|
|
} |
|
68
|
|
|
/** |
|
69
|
|
|
* Magic getter |
|
70
|
|
|
* |
|
71
|
|
|
* Try to get object property according this order : |
|
72
|
|
|
* <ul> |
|
73
|
|
|
* <li>$dbVariable</li> |
|
74
|
|
|
* <li>$protectedVariable (triggger call to accessToProtectedVariable() |
|
75
|
|
|
* if not already loaded)</li> |
|
76
|
|
|
* </ul> |
|
77
|
|
|
* |
|
78
|
|
|
* @param string $name Property name |
|
79
|
|
|
* @return Mixed Property value |
|
80
|
|
|
*/ |
|
81
|
|
|
public function __get($name) |
|
82
|
|
|
{ |
|
83
|
|
|
if ($this->isDBVariable($name)) { |
|
84
|
|
|
return $this->getDBVariable($name); |
|
85
|
|
|
} elseif ($this->isProtectedVariable($name)) { |
|
86
|
|
|
return $this->getProtectedVariable($name); |
|
87
|
|
|
} elseif ($this->isRelation($name)) { |
|
88
|
|
|
return $this->getRelation($name); |
|
89
|
|
|
} elseif (!empty($this->$name)) { |
|
90
|
|
|
return $this->$name; |
|
91
|
|
|
} else { |
|
92
|
|
|
throw new \InvalidArgumentException('Undefined property ' . $name); |
|
93
|
|
|
} |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* Magic setter |
|
98
|
|
|
* |
|
99
|
|
|
* Set a property to defined value |
|
100
|
|
|
* Assignment in this order : |
|
101
|
|
|
* - $dbVariable |
|
102
|
|
|
* - $protectedVariable |
|
103
|
|
|
* </ul> |
|
104
|
|
|
* @param string $name variable name |
|
105
|
|
|
* @param mixed $value variable value |
|
106
|
|
|
*/ |
|
107
|
|
|
public function __set($name, $value) |
|
108
|
|
|
{ |
|
109
|
|
|
if ($this->isDBVariable($name)) { |
|
110
|
|
|
$this->dbValues[$name] = $value; |
|
111
|
|
|
} elseif ($this->isProtectedVariable($name)) { |
|
112
|
|
|
$this->protectedValues[$name] = $value; |
|
113
|
|
|
} elseif ($this->isRelation($name)) { |
|
114
|
|
|
$this->relationValues[$name] = $value; |
|
115
|
|
|
} else { |
|
116
|
|
|
$this->$name = $value; |
|
117
|
|
|
} |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
public function __isset($name) |
|
121
|
|
|
{ |
|
122
|
|
|
if ($this->isDBVariable($name)) { |
|
123
|
|
|
return isset($this->dbValues[$name]); |
|
124
|
|
|
} elseif ($this->isProtectedVariable($name)) { |
|
125
|
|
|
// Load only one time protected variable automatically |
|
126
|
|
|
if (!$this->isProtectedVariableLoaded($name)) { |
|
127
|
|
|
$protectedAccessResult = $this->accessToProtectedVariable($name); |
|
128
|
|
|
|
|
129
|
|
|
if ($protectedAccessResult) { |
|
130
|
|
|
$this->markProtectedVariableAsLoaded($name); |
|
131
|
|
|
} |
|
132
|
|
|
} |
|
133
|
|
|
return isset($this->protectedValues[$name]); |
|
134
|
|
|
} elseif ($this->isRelation($name)) { |
|
135
|
|
|
if (!$this->isRelationLoaded($name)) { |
|
136
|
|
|
$relationResult = $this->loadRelation($name); |
|
137
|
|
|
|
|
138
|
|
|
if ($relationResult) { |
|
139
|
|
|
$this->markRelationAsLoaded($name); |
|
140
|
|
|
} |
|
141
|
|
|
} |
|
142
|
|
|
return isset($this->relationValues[$name]); |
|
143
|
|
|
} else { |
|
144
|
|
|
return false; |
|
145
|
|
|
} |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
/** |
|
149
|
|
|
* __sleep magic method, permits an inherited DBObject class to be serialized |
|
150
|
|
|
* @return Array of properties to serialize |
|
151
|
|
|
*/ |
|
152
|
|
|
public function __sleep() |
|
153
|
|
|
{ |
|
154
|
|
|
$this->dbLink = false; |
|
155
|
|
|
$this->relations= []; |
|
156
|
|
|
$reflection = new \ReflectionClass($this); |
|
157
|
|
|
$props = $reflection->getProperties(); |
|
158
|
|
|
$result = []; |
|
159
|
|
|
foreach ($props as $currentProperty) { |
|
160
|
|
|
$result[] = $currentProperty->name; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
return $result; |
|
164
|
|
|
} |
|
165
|
|
|
|
|
166
|
|
|
public function __wakeup() |
|
167
|
|
|
{ |
|
168
|
|
|
$this->setRelations(); |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
private function getDBVariable($name) |
|
172
|
|
|
{ |
|
173
|
|
|
if (isset($this->dbValues[$name])) { |
|
174
|
|
|
return $this->dbValues[$name]; |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
return null; |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
|
|
/** |
|
181
|
|
|
* Check if variable is from DB |
|
182
|
|
|
* @param string $name variable name |
|
183
|
|
|
* @return boolean |
|
184
|
|
|
*/ |
|
185
|
|
|
public function isDBVariable($name) |
|
186
|
|
|
{ |
|
187
|
|
|
return in_array($name, $this->dbVariables); |
|
188
|
|
|
} |
|
189
|
|
|
|
|
190
|
|
|
private function getProtectedVariable($name) |
|
191
|
|
|
{ |
|
192
|
|
|
// Variable exists, and is already loaded |
|
193
|
|
|
if (isset($this->protectedValues[$name]) && $this->isProtectedVariableLoaded($name)) { |
|
194
|
|
|
return $this->protectedValues[$name]; |
|
195
|
|
|
} |
|
196
|
|
|
// Variable has not been loaded |
|
197
|
|
|
if (!$this->isProtectedVariableLoaded($name)) { |
|
198
|
|
|
if ($this->accessToProtectedVariable($name)) { |
|
199
|
|
|
$this->markProtectedVariableAsLoaded($name); |
|
200
|
|
|
} |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
if (isset($this->protectedValues[$name])) { |
|
204
|
|
|
return $this->protectedValues[$name]; |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
return null; |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
private function getRelation($name) |
|
211
|
|
|
{ |
|
212
|
|
|
if (isset($this->relationValues[$name]) && $this->isRelationLoaded($name)) { |
|
213
|
|
|
return $this->relationValues[$name]; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
if (!$this->isRelationLoaded($name)) { |
|
217
|
|
|
if ($this->loadRelation($name)) { |
|
218
|
|
|
$this->markRelationAsLoaded($name); |
|
219
|
|
|
} |
|
220
|
|
|
} |
|
221
|
|
|
|
|
222
|
|
|
if (isset($this->relationValues[$name])) { |
|
223
|
|
|
return $this->relationValues[$name]; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
return null; |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* Check if variable is predefined relation |
|
231
|
|
|
* @param string $name variable name |
|
232
|
|
|
* @return boolean |
|
233
|
|
|
*/ |
|
234
|
|
|
protected function isRelation($name) |
|
235
|
|
|
{ |
|
236
|
|
|
return isset($this->relations[$name]); |
|
237
|
|
|
} |
|
238
|
|
|
/** |
|
239
|
|
|
* Define object relations |
|
240
|
|
|
* |
|
241
|
|
|
* @return object |
|
242
|
|
|
*/ |
|
243
|
|
|
protected function setRelations() |
|
244
|
|
|
{ |
|
245
|
|
|
$this->relations = []; |
|
246
|
|
|
|
|
247
|
|
|
return $this; |
|
248
|
|
|
} |
|
249
|
|
|
|
|
250
|
|
|
/** |
|
251
|
|
|
* Mark a protected variable as loaded |
|
252
|
|
|
* @param string $name varialbe name |
|
253
|
|
|
* @return void |
|
254
|
|
|
*/ |
|
255
|
|
|
public function markProtectedVariableAsLoaded($name) |
|
256
|
|
|
{ |
|
257
|
|
|
if ($this->isProtectedVariable($name)) { |
|
258
|
|
|
$this->loadedProtectedVariables[$name] = true; |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
|
|
262
|
|
|
/** |
|
263
|
|
|
* Mark a relation as loaded |
|
264
|
|
|
* @param string $name varialbe name |
|
265
|
|
|
* @return void |
|
266
|
|
|
*/ |
|
267
|
|
|
protected function markRelationAsLoaded($name) |
|
268
|
|
|
{ |
|
269
|
|
|
if ($this->isRelation($name)) { |
|
270
|
|
|
$this->loadedRelations[$name] = true; |
|
271
|
|
|
} |
|
272
|
|
|
} |
|
273
|
|
|
/** |
|
274
|
|
|
* Check if a relation already have been loaded |
|
275
|
|
|
* @param string $name Variable name |
|
276
|
|
|
* @return boolean |
|
277
|
|
|
*/ |
|
278
|
|
|
protected function isRelationLoaded($name) |
|
279
|
|
|
{ |
|
280
|
|
|
return isset($this->loadedRelations[$name]); |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
protected function loadRelation($name) |
|
284
|
|
|
{ |
|
285
|
|
|
if (isset($this->relations[$name])) { |
|
286
|
|
|
switch ($this->relations[$name]['type']) { |
|
287
|
|
|
case self::RELATION_ONE_ONE: |
|
288
|
|
|
return $this->loadRelationOneOne($name); |
|
289
|
|
|
case self::RELATION_ONE_MANY: |
|
290
|
|
|
return $this->loadRelationOneMany($name); |
|
291
|
|
|
case self::RELATION_MANY_MANY: |
|
292
|
|
|
return $this->loadRelationManyMany($name); |
|
293
|
|
|
} |
|
294
|
|
|
} |
|
295
|
|
|
|
|
296
|
|
|
return false; |
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
private function loadRelationOneOne($name) |
|
300
|
|
|
{ |
|
301
|
|
|
$target = $this->relations[$name]['target']; |
|
302
|
|
|
$source = $this->relations[$name]['source']; |
|
303
|
|
|
$this->relationValues[$name] = new $target(); |
|
304
|
|
|
$this->relationValues[$name]->load($this->$source); |
|
305
|
|
|
|
|
306
|
|
|
return true; |
|
307
|
|
|
} |
|
308
|
|
|
|
|
309
|
|
View Code Duplication |
private function loadRelationOneMany($name) |
|
|
|
|
|
|
310
|
|
|
{ |
|
311
|
|
|
$target = $this->relations[$name]['target']; |
|
312
|
|
|
$parentId = $this->{$this->relations[$name]['source']}; |
|
313
|
|
|
$parentIdField = isset($this->relations[$name]['target_field']) ? $this->relations[$name]['target_field'] : null; |
|
314
|
|
|
$validate = dataGet($this->relations[$name], 'validate', null); |
|
315
|
|
|
|
|
316
|
|
|
$this->relationValues[$name] = $target::loadForParentId($parentId, $parentIdField, $validate); |
|
317
|
|
|
|
|
318
|
|
|
return true; |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
View Code Duplication |
private function loadRelationManyMany($name) |
|
|
|
|
|
|
322
|
|
|
{ |
|
323
|
|
|
$pivot = $this->relations[$name]['pivot']; |
|
324
|
|
|
$sourceType = $this->relations[$name]['source_type']; |
|
325
|
|
|
$target = dataGet($this->relations[$name], 'target'); |
|
326
|
|
|
$validate = dataGet($this->relations[$name], 'validate', null); |
|
327
|
|
|
|
|
328
|
|
|
$this->relationValues[$name] = $pivot::loadFor($sourceType, $this->{$this->relations[$name]['source']}, $target, $validate); |
|
329
|
|
|
|
|
330
|
|
|
return true; |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
private function resetLoadedVariables() |
|
334
|
|
|
{ |
|
335
|
|
|
$this->loadedProtectedVariables = []; |
|
336
|
|
|
$this->loadedRelations = []; |
|
337
|
|
|
|
|
338
|
|
|
return $this; |
|
339
|
|
|
} |
|
340
|
|
|
|
|
341
|
|
|
/** |
|
342
|
|
|
* Check if requested property exists |
|
343
|
|
|
* |
|
344
|
|
|
* Check in following order: |
|
345
|
|
|
* <ul> |
|
346
|
|
|
* <li>$dbVariables</li> |
|
347
|
|
|
* <li>$protectedVariables</li> |
|
348
|
|
|
* <li>$relations</li> |
|
349
|
|
|
* <li>legacy property</li> |
|
350
|
|
|
* </ul> |
|
351
|
|
|
* @param string $property Property name |
|
352
|
|
|
* @return boolean true if exists |
|
353
|
|
|
*/ |
|
354
|
|
|
public function propertyExists($property) |
|
355
|
|
|
{ |
|
356
|
|
|
return $this->isDBVariable($property) |
|
357
|
|
|
|| $this->isProtectedVariable($property) |
|
358
|
|
|
|| $this->isRelation($property) |
|
359
|
|
|
|| property_exists($this, $property); |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
/** |
|
363
|
|
|
* Check if variable is a protected variable |
|
364
|
|
|
* @param string $name variable name |
|
365
|
|
|
* @return boolean |
|
366
|
|
|
*/ |
|
367
|
|
|
public function isProtectedVariable($name) |
|
368
|
|
|
{ |
|
369
|
|
|
return in_array($name, $this->protectedVariables); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
|
|
373
|
|
|
|
|
374
|
|
|
/** |
|
375
|
|
|
* Check if a protected variable already have been loaded |
|
376
|
|
|
* @param string $name Variable name |
|
377
|
|
|
* @return boolean |
|
378
|
|
|
*/ |
|
379
|
|
|
protected function isProtectedVariableLoaded($name) |
|
380
|
|
|
{ |
|
381
|
|
|
return isset($this->loadedProtectedVariables[$name]); |
|
382
|
|
|
} |
|
383
|
|
|
|
|
384
|
|
|
|
|
385
|
|
|
|
|
386
|
|
|
/** |
|
387
|
|
|
* Load ORM from Database |
|
388
|
|
|
* @param mixed $id SQL Table Unique id |
|
389
|
|
|
* @return mixed Loaded object or false on failure |
|
390
|
|
|
*/ |
|
391
|
|
|
public function load($id) |
|
392
|
|
|
{ |
|
393
|
|
|
$this->connectDB(); |
|
394
|
|
|
$this->resetLoadedVariables(); |
|
395
|
|
|
|
|
396
|
|
|
if ($id != '') { |
|
397
|
|
|
$query = "SELECT *"; |
|
398
|
|
|
$query .= " FROM `" . static::TABLE_NAME ."`"; |
|
399
|
|
|
$query .= " WHERE"; |
|
400
|
|
|
$query .= " `" . static::TABLE_INDEX . "` = :id"; |
|
401
|
|
|
|
|
402
|
|
|
$params = []; |
|
403
|
|
|
$params['id'] = $id; |
|
404
|
|
|
|
|
405
|
|
|
return $this->loadFromSql($query, $params); |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
return $this; |
|
409
|
|
|
} |
|
410
|
|
|
|
|
411
|
|
|
public function isLoaded() |
|
412
|
|
|
{ |
|
413
|
|
|
return $this->{static::TABLE_INDEX} !== null; |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
public function loadOrFail($id) |
|
417
|
|
|
{ |
|
418
|
|
|
$this->load($id); |
|
419
|
|
|
if ($id == '' || $this->{static::TABLE_INDEX} != $id) { |
|
420
|
|
|
throw (new Exception\ModelNotFoundException)->setModel(get_called_class()); |
|
421
|
|
|
} else { |
|
422
|
|
|
return $this; |
|
423
|
|
|
} |
|
424
|
|
|
} |
|
425
|
|
|
|
|
426
|
|
|
public static function loadOrCreate($arg) |
|
427
|
|
|
{ |
|
428
|
|
|
$obj = static::loadOrInstanciate($arg); |
|
429
|
|
|
$obj->save(); |
|
430
|
|
|
|
|
431
|
|
|
return $obj; |
|
432
|
|
|
} |
|
433
|
|
|
|
|
434
|
|
|
public static function loadOrInstanciate($arg) |
|
435
|
|
|
{ |
|
436
|
|
|
if (!is_array($arg)) { |
|
437
|
|
|
$arg = [static::TABLE_INDEX => $arg]; |
|
438
|
|
|
} |
|
439
|
|
|
|
|
440
|
|
|
$sql = "SELECT *"; |
|
441
|
|
|
$sql .= " FROM " . static::TABLE_NAME; |
|
442
|
|
|
$sql .= " WHERE "; |
|
443
|
|
|
|
|
444
|
|
|
$sqlArray = []; |
|
445
|
|
|
$params = []; |
|
446
|
|
|
$i = 0; |
|
447
|
|
|
foreach ($arg as $key => $val) { |
|
448
|
|
|
if (is_null($val)) { |
|
449
|
|
|
$sqlArray[] = '`' . $key . '` IS :arg' . $i; |
|
450
|
|
|
} else { |
|
451
|
|
|
$sqlArray[] = '`' . $key . '`=:arg' . $i; |
|
452
|
|
|
} |
|
453
|
|
|
$params['arg' .$i] = $val; |
|
454
|
|
|
$i++; |
|
455
|
|
|
} |
|
456
|
|
|
$sql .= implode(' AND ', $sqlArray); |
|
457
|
|
|
|
|
458
|
|
|
|
|
459
|
|
|
|
|
460
|
|
|
$calledClass = get_called_class(); |
|
461
|
|
|
$obj = new $calledClass; |
|
462
|
|
|
if (!$obj->loadFromSql($sql, $params)) { |
|
463
|
|
|
foreach($arg as $property => $value) { |
|
464
|
|
|
$obj->$property = $value; |
|
465
|
|
|
} |
|
466
|
|
|
} |
|
467
|
|
|
|
|
468
|
|
|
return $obj; |
|
469
|
|
|
} |
|
470
|
|
|
|
|
471
|
|
|
public function loadFromSql($sql, $sql_params = []) |
|
|
|
|
|
|
472
|
|
|
{ |
|
473
|
|
|
$this->connectDB(); |
|
474
|
|
|
$this->resetLoadedVariables(); |
|
475
|
|
|
|
|
476
|
|
|
$results = $this->dbLink->query($sql, $sql_params)->fetch(); |
|
|
|
|
|
|
477
|
|
|
|
|
478
|
|
|
if ($results !== false) { |
|
479
|
|
|
foreach ($results as $key => $value) { |
|
480
|
|
|
$this->$key = $value; |
|
481
|
|
|
} |
|
482
|
|
|
|
|
483
|
|
|
return $this; |
|
484
|
|
|
} |
|
485
|
|
|
|
|
486
|
|
|
return false; |
|
487
|
|
|
} |
|
488
|
|
|
|
|
489
|
|
|
/** |
|
490
|
|
|
* Construct an DBObject from an array |
|
491
|
|
|
* @param array $data associative array |
|
492
|
|
|
* @return DBObject Built DBObject |
|
493
|
|
|
*/ |
|
494
|
|
|
public static function instanciate($data = []) |
|
495
|
|
|
{ |
|
496
|
|
|
$calledClass = get_called_class(); |
|
497
|
|
|
$orm = new $calledClass; |
|
498
|
|
|
|
|
499
|
|
|
foreach ($data as $key => $val) { |
|
500
|
|
|
if ($orm->propertyExists($key)) { |
|
501
|
|
|
$orm->$key = $val; |
|
502
|
|
|
} |
|
503
|
|
|
} |
|
504
|
|
|
|
|
505
|
|
|
return $orm; |
|
506
|
|
|
} |
|
507
|
|
|
|
|
508
|
|
|
public static function create($data = []) |
|
509
|
|
|
{ |
|
510
|
|
|
$obj = static::instanciate($data); |
|
511
|
|
|
$obj->save(); |
|
512
|
|
|
|
|
513
|
|
|
return $obj; |
|
514
|
|
|
} |
|
515
|
|
|
|
|
516
|
|
|
/** |
|
517
|
|
|
* Delete record from SQL Table |
|
518
|
|
|
* |
|
519
|
|
|
* Delete record link to current object, according SQL Table unique id |
|
520
|
|
|
* @return null |
|
521
|
|
|
*/ |
|
522
|
|
|
public function delete() |
|
523
|
|
|
{ |
|
524
|
|
|
$this->connectDB(); |
|
525
|
|
|
|
|
526
|
|
|
if (static::TABLE_INDEX != '') { |
|
527
|
|
|
$query = "DELETE FROM `" . static::TABLE_NAME . "`"; |
|
528
|
|
|
$query .= " WHERE `" . static::TABLE_INDEX . "` = :id"; |
|
529
|
|
|
|
|
530
|
|
|
$queryParams = []; |
|
531
|
|
|
$queryParams['id'] = $this->{static::TABLE_INDEX}; |
|
532
|
|
|
|
|
533
|
|
|
$this->dbLink->query($query, $queryParams); |
|
|
|
|
|
|
534
|
|
|
} |
|
535
|
|
|
} |
|
536
|
|
|
|
|
537
|
|
|
/** |
|
538
|
|
|
* Save current object into db |
|
539
|
|
|
* |
|
540
|
|
|
* Call INSERT or UPDATE if unique index is set |
|
541
|
|
|
* @param boolean $forceInsert true to force insert instead of update |
|
542
|
|
|
* @return null |
|
543
|
|
|
*/ |
|
544
|
|
|
public function save($forceInsert = false) |
|
545
|
|
|
{ |
|
546
|
|
|
if (count($this->dbValues)) { |
|
547
|
|
|
$this->connectDB(); |
|
548
|
|
|
|
|
549
|
|
|
if ($this->{static::TABLE_INDEX} != '' && !$forceInsert) { |
|
550
|
|
|
$this->update(); |
|
551
|
|
|
$insert = false; |
|
552
|
|
|
} else { |
|
553
|
|
|
$this->insert(); |
|
554
|
|
|
$insert = true; |
|
555
|
|
|
} |
|
556
|
|
|
|
|
557
|
|
|
// Checking protected variables |
|
558
|
|
|
foreach ($this->protectedVariables as $variable) { |
|
559
|
|
|
// only if current protected_var is set |
|
560
|
|
|
if (isset($this->protectedValues[$variable]) && $this->isProtectedVariableLoaded($variable)) { |
|
561
|
|
|
if ($this->protectedValues[$variable] instanceof Interfaces\ICollection) { |
|
562
|
|
|
if ($insert) { |
|
563
|
|
|
$this->protectedValues[$variable]->setParentIdForAll($this->id); |
|
|
|
|
|
|
564
|
|
|
} |
|
565
|
|
|
$this->protectedValues[$variable]->save(); |
|
566
|
|
|
} |
|
567
|
|
|
} |
|
568
|
|
|
} |
|
569
|
|
|
} else { |
|
570
|
|
|
throw new \RuntimeException("Object " . get_called_class() . " has no properties to save"); |
|
571
|
|
|
} |
|
572
|
|
|
} |
|
573
|
|
|
|
|
574
|
|
|
/** |
|
575
|
|
|
* UPDATE current object into database |
|
576
|
|
|
* @return null |
|
577
|
|
|
*/ |
|
578
|
|
|
private function update() |
|
579
|
|
|
{ |
|
580
|
|
|
$this->connectDB(); |
|
581
|
|
|
|
|
582
|
|
|
$sqlParams = []; |
|
583
|
|
|
|
|
584
|
|
|
$sql = 'UPDATE `' . static::TABLE_NAME . '`'; |
|
585
|
|
|
$sql .= ' SET '; |
|
586
|
|
|
|
|
587
|
|
|
|
|
588
|
|
|
foreach ($this->dbValues as $key => $val) { |
|
589
|
|
|
if (!in_array($key, $this->readOnlyVariables)) { |
|
590
|
|
|
$sql .= ' `' . $key . '`=:' . $key .', '; |
|
591
|
|
|
$sqlParams[$key] = $val; |
|
592
|
|
|
} |
|
593
|
|
|
} |
|
594
|
|
|
$sql = substr($sql, 0, -2); |
|
595
|
|
|
$sql .= " WHERE `" . static::TABLE_INDEX . "` = :SuricateTableIndex"; |
|
596
|
|
|
|
|
597
|
|
|
$sqlParams[':SuricateTableIndex'] = $this->{static::TABLE_INDEX}; |
|
598
|
|
|
|
|
599
|
|
|
$this->dbLink->query($sql, $sqlParams); |
|
|
|
|
|
|
600
|
|
|
} |
|
601
|
|
|
|
|
602
|
|
|
/** |
|
603
|
|
|
* INSERT current object into database |
|
604
|
|
|
* @access private |
|
605
|
|
|
* @return null |
|
606
|
|
|
*/ |
|
607
|
|
|
private function insert() |
|
608
|
|
|
{ |
|
609
|
|
|
$this->connectDB(); |
|
610
|
|
|
|
|
611
|
|
|
$variables = array_diff($this->dbVariables, $this->readOnlyVariables); |
|
612
|
|
|
|
|
613
|
|
|
$sql = 'INSERT INTO `' . static::TABLE_NAME . '`'; |
|
614
|
|
|
$sql .= '(`'; |
|
615
|
|
|
$sql .= implode('`, `', $variables); |
|
616
|
|
|
$sql .= '`)'; |
|
617
|
|
|
$sql .= ' VALUES (:'; |
|
618
|
|
|
$sql .= implode(', :', $variables); |
|
619
|
|
|
$sql .= ')'; |
|
620
|
|
|
|
|
621
|
|
|
$sqlParams = []; |
|
622
|
|
|
foreach ($variables as $field) { |
|
623
|
|
|
$sqlParams[':' . $field] = $this->$field; |
|
624
|
|
|
} |
|
625
|
|
|
|
|
626
|
|
|
$this->dbLink->query($sql, $sqlParams); |
|
|
|
|
|
|
627
|
|
|
|
|
628
|
|
|
$this->{static::TABLE_INDEX} = $this->dbLink->lastInsertId(); |
|
|
|
|
|
|
629
|
|
|
} |
|
630
|
|
|
|
|
631
|
|
|
protected function connectDB() |
|
632
|
|
|
{ |
|
633
|
|
|
if (!$this->dbLink) { |
|
634
|
|
|
$this->dbLink = Suricate::Database(); |
|
635
|
|
|
if (static::DB_CONFIG != '') { |
|
636
|
|
|
$this->dbLink->setConfig(static::DB_CONFIG); |
|
637
|
|
|
} |
|
638
|
|
|
} |
|
639
|
|
|
} |
|
640
|
|
|
|
|
641
|
|
|
|
|
642
|
|
|
protected function accessToProtectedVariable($name) |
|
643
|
|
|
{ |
|
644
|
|
|
return false; |
|
645
|
|
|
} |
|
646
|
|
|
|
|
647
|
|
|
public function validate() |
|
648
|
|
|
{ |
|
649
|
|
|
return true; |
|
650
|
|
|
} |
|
651
|
|
|
|
|
652
|
|
|
public function getValidatorMessages() |
|
653
|
|
|
{ |
|
654
|
|
|
return $this->validatorMessages; |
|
655
|
|
|
} |
|
656
|
|
|
} |
|
657
|
|
|
|
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.