This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | class Ajde_Model extends Ajde_Object_Standard |
||
4 | { |
||
5 | const ENCRYPTION_PREFIX = '$$$ENCRYPTED$$$'; |
||
6 | |||
7 | protected $_connection; |
||
8 | protected $_table; |
||
9 | |||
10 | protected $_autoloadParents = false; |
||
11 | |||
12 | protected $_tableName; |
||
13 | protected $_displayField = null; |
||
14 | protected $_encrypedFields = []; |
||
15 | protected $_jsonFields = []; |
||
16 | |||
17 | protected $_hasMeta = false; |
||
18 | protected $_metaLookup = []; |
||
19 | public $_metaValues = []; |
||
20 | |||
21 | protected $_validators = []; |
||
22 | |||
23 | public static function extendController(Ajde_Controller $controller, $method, $arguments) |
||
24 | { |
||
25 | // Register getModel($name) function on Ajde_Controller |
||
26 | if ($method === 'getModel') { |
||
27 | if (!isset($arguments[0])) { |
||
28 | $arguments[0] = $controller->getModule(); |
||
29 | } |
||
30 | |||
31 | return self::getModel($arguments[0]); |
||
32 | } |
||
33 | // TODO: if last triggered in event cueue, throw exception |
||
34 | // throw new Ajde_Exception("Call to undefined method ".get_class($controller)."::$method()", 90006); |
||
35 | // Now, we give other callbacks in event cueue chance to return |
||
36 | } |
||
37 | |||
38 | /** |
||
39 | * @param string $name |
||
40 | * |
||
41 | * @return Ajde_Model |
||
42 | */ |
||
43 | public static function getModel($name) |
||
44 | { |
||
45 | $modelName = ucfirst($name).'Model'; |
||
46 | |||
47 | return new $modelName(); |
||
48 | } |
||
49 | |||
50 | /** |
||
51 | * @return Ajde_Collection |
||
52 | */ |
||
53 | public function getCollection() |
||
54 | { |
||
55 | $collectionName = $this->toCamelCase($this->_tableName).'Collection'; |
||
56 | |||
57 | return new $collectionName(); |
||
58 | } |
||
59 | |||
60 | public function __construct() |
||
61 | { |
||
62 | if (empty($this->_tableName)) { |
||
63 | $tableNameCC = str_replace('Model', '', get_class($this)); |
||
64 | $this->_tableName = $this->fromCamelCase($tableNameCC); |
||
65 | } |
||
66 | |||
67 | $this->_connection = Ajde_Db::getInstance()->getConnection(); |
||
68 | $this->_table = Ajde_Db::getInstance()->getTable($this->_tableName); |
||
69 | } |
||
70 | |||
71 | public function __set($name, $value) |
||
72 | { |
||
73 | $this->set($name, $value); |
||
74 | } |
||
75 | |||
76 | protected function _set($name, $value) |
||
77 | { |
||
78 | parent::_set($name, $value); |
||
79 | if ($this->isFieldEncrypted($name)) { |
||
80 | parent::_set($name, $this->encrypt($name)); |
||
81 | } |
||
82 | } |
||
83 | |||
84 | public function __get($name) |
||
85 | { |
||
86 | return $this->get($name); |
||
87 | } |
||
88 | |||
89 | protected function _get($name) |
||
90 | { |
||
91 | if ($this->isFieldEncrypted($name)) { |
||
92 | return $this->decrypt($name); |
||
93 | } |
||
94 | |||
95 | return parent::_get($name); |
||
96 | } |
||
97 | |||
98 | public function __isset($name) |
||
99 | { |
||
100 | return $this->has($name); |
||
101 | } |
||
102 | |||
103 | public function __toString() |
||
104 | { |
||
105 | if (empty($this->_data)) { |
||
106 | return ''; |
||
107 | } |
||
108 | |||
109 | return (string) $this->getPK(); |
||
110 | } |
||
111 | |||
112 | public function __sleep() |
||
113 | { |
||
114 | return ['_autoloadParents', '_displayField', '_encrypedFields', '_data']; |
||
115 | } |
||
116 | |||
117 | public function __wakeup() |
||
118 | { |
||
119 | $this->__construct(); |
||
120 | } |
||
121 | |||
122 | public function reset() |
||
123 | { |
||
124 | $this->_metaValues = []; |
||
125 | parent::reset(); |
||
126 | } |
||
127 | |||
128 | public function isEmpty($key) |
||
129 | { |
||
130 | $value = (string) $this->get($key); |
||
131 | |||
132 | return empty($value); |
||
133 | } |
||
134 | |||
135 | public function getPK() |
||
136 | { |
||
137 | if (empty($this->_data)) { |
||
138 | return; |
||
139 | } |
||
140 | $pk = $this->getTable()->getPK(); |
||
141 | |||
142 | return $this->has($pk) ? $this->get($pk) : null; |
||
143 | } |
||
144 | |||
145 | public function getDisplayField() |
||
146 | { |
||
147 | if (isset($this->_displayField)) { |
||
148 | return $this->_displayField; |
||
149 | } else { |
||
150 | return current($this->getTable()->getFieldNames()); |
||
151 | } |
||
152 | } |
||
153 | |||
154 | public function displayField() |
||
155 | { |
||
156 | $displayField = $this->getDisplayField(); |
||
157 | |||
158 | return $this->has($displayField) ? $this->get($displayField) : '(untitled model)'; |
||
159 | } |
||
160 | |||
161 | public function getPublishData() |
||
162 | { |
||
163 | return [ |
||
164 | 'title' => $this->displayField(), |
||
165 | 'message' => null, |
||
166 | 'image' => null, |
||
167 | 'url' => null, |
||
168 | ]; |
||
169 | } |
||
170 | |||
171 | public function getPublishRecipients() |
||
172 | { |
||
173 | return []; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * @return Ajde_Db_Adapter_Abstract |
||
178 | */ |
||
179 | public function getConnection() |
||
180 | { |
||
181 | return $this->_connection; |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * @return Ajde_Db_Table |
||
186 | */ |
||
187 | public function getTable() |
||
188 | { |
||
189 | return $this->_table; |
||
190 | } |
||
191 | |||
192 | public function populate($array) |
||
193 | { |
||
194 | // TODO: parse array and typecast to match fields settings |
||
195 | $this->_data = array_merge($this->_data, $array); |
||
196 | } |
||
197 | |||
198 | public function getValues($recursive = true) |
||
199 | { |
||
200 | $return = []; |
||
201 | foreach ($this->_data as $k => $v) { |
||
202 | if ($v instanceof self) { |
||
203 | if ($recursive) { |
||
204 | $return[$k] = $v->getValues(); |
||
205 | } else { |
||
206 | @$return[$k] = (string) $v; |
||
0 ignored issues
–
show
|
|||
207 | } |
||
208 | } else { |
||
209 | $return[$k] = $v; |
||
210 | } |
||
211 | } |
||
212 | |||
213 | return $return; |
||
214 | } |
||
215 | |||
216 | // Load model values |
||
217 | public function loadByPK($value) |
||
218 | { |
||
219 | $this->reset(); |
||
220 | $pk = $this->getTable()->getPK(); |
||
221 | |||
222 | return $this->loadByFields([$pk => $value]); |
||
223 | } |
||
224 | |||
225 | public function loadByField($field, $value) |
||
226 | { |
||
227 | return $this->loadByFields([$field => $value]); |
||
228 | } |
||
229 | |||
230 | public function loadByFields($array) |
||
231 | { |
||
232 | $sqlWhere = []; |
||
233 | $values = []; |
||
234 | foreach ($array as $field => $value) { |
||
235 | $sqlWhere[] = $field.' = ?'; |
||
236 | if ($this->isFieldEncrypted($field)) { |
||
237 | $values[] = $this->doEncrypt($value); |
||
238 | } else { |
||
239 | $values[] = $value; |
||
240 | } |
||
241 | } |
||
242 | $sql = 'SELECT * FROM '.$this->_table.' WHERE '.implode(' AND ', $sqlWhere).' LIMIT 1'; |
||
243 | |||
244 | return $this->_load($sql, $values); |
||
245 | } |
||
246 | |||
247 | protected function _load($sql, $values, $populate = true) |
||
248 | { |
||
249 | $statement = $this->getConnection()->prepare($sql); |
||
250 | $statement->execute($values); |
||
251 | $result = $statement->fetch(PDO::FETCH_ASSOC); |
||
252 | if ($result === false || empty($result)) { |
||
253 | return false; |
||
254 | } else { |
||
255 | if ($populate === true) { |
||
256 | $this->reset(); |
||
257 | $this->loadFromValues($result); |
||
258 | } |
||
259 | } |
||
260 | |||
261 | return true; |
||
262 | } |
||
263 | |||
264 | public function loadFromValues($values) |
||
265 | { |
||
266 | $this->populate($values); |
||
267 | if ($this->_autoloadParents === true) { |
||
268 | $this->loadParents(); |
||
269 | } |
||
270 | if ($this->_hasMeta === true) { |
||
271 | $this->populateMeta(); |
||
272 | } |
||
273 | } |
||
274 | |||
275 | private function getMetaTable() |
||
276 | { |
||
277 | return $this->getTable().'_meta'; |
||
278 | } |
||
279 | |||
280 | public function populateMeta($values = false, $override = true) |
||
281 | { |
||
282 | if (!$values) { |
||
283 | $values = $this->getMetaValues(); |
||
284 | } |
||
285 | foreach ($values as $metaId => $value) { |
||
0 ignored issues
–
show
The expression
$values of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
286 | if ($override || !$this->has('meta_'.$metaId)) { |
||
287 | $this->set('meta_'.$metaId, $value); |
||
288 | } |
||
289 | } |
||
290 | } |
||
291 | |||
292 | public function getMetaValues() |
||
293 | { |
||
294 | if (empty($this->_metaValues)) { |
||
295 | $meta = []; |
||
296 | if ($this->hasLoaded()) { |
||
297 | $sql = 'SELECT * FROM '.$this->getMetaTable().' WHERE '.$this->getTable().' = ?'; |
||
298 | $statement = $this->getConnection()->prepare($sql); |
||
299 | $statement->execute([$this->getPK()]); |
||
300 | $results = $statement->fetchAll(PDO::FETCH_ASSOC); |
||
301 | View Code Duplication | foreach ($results as $result) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
302 | if (isset($meta[$result['meta']])) { |
||
303 | if (is_array($meta[$result['meta']])) { |
||
304 | $meta[$result['meta']][] = $result['value']; |
||
305 | } else { |
||
306 | $meta[$result['meta']] = [ |
||
307 | $meta[$result['meta']], |
||
308 | $result['value'], |
||
309 | ]; |
||
310 | } |
||
311 | } else { |
||
312 | $meta[$result['meta']] = $result['value']; |
||
313 | } |
||
314 | } |
||
315 | } |
||
316 | $this->_metaValues = $meta; |
||
317 | } |
||
318 | |||
319 | return $this->_metaValues; |
||
320 | } |
||
321 | |||
322 | private function fuzzyMetaName($name) |
||
323 | { |
||
324 | return str_replace(' ', '_', strtolower($name)); |
||
325 | } |
||
326 | |||
327 | public function lookupMetaName($name) |
||
328 | { |
||
329 | if (empty($this->_metaLookup)) { |
||
330 | // We need to have the MetaModel here.. |
||
331 | $metaCollection = new MetaCollection(); |
||
332 | // disable join, as we don't get any metas which don't have a row yet |
||
333 | // $metaCollection->addFilter(new Ajde_Filter_Join($this->getMetaTable(), 'meta.id', 'meta')); |
||
334 | foreach ($metaCollection as $meta) { |
||
335 | /* @var $meta MetaModel */ |
||
336 | $this->_metaLookup[$this->fuzzyMetaName($meta->get('name'))] = $meta->getPK(); |
||
337 | } |
||
338 | } |
||
339 | if (isset($this->_metaLookup[$this->fuzzyMetaName($name)])) { |
||
340 | return $this->_metaLookup[$this->fuzzyMetaName($name)]; |
||
341 | } |
||
342 | |||
343 | return false; |
||
344 | } |
||
345 | |||
346 | public function getMetaValue($metaId) |
||
347 | { |
||
348 | if (!is_numeric($metaId)) { |
||
349 | $metaId = $this->lookupMetaName($metaId); |
||
350 | } |
||
351 | $values = $this->getMetaValues(); |
||
352 | if (isset($values[$metaId])) { |
||
353 | return $values[$metaId]; |
||
354 | } |
||
355 | |||
356 | return false; |
||
357 | } |
||
358 | |||
359 | public function getMediaModelFromMetaValue($metaId) |
||
360 | { |
||
361 | $metaValue = (int) $this->getMetaValue($metaId); |
||
362 | $media = new MediaModel(); |
||
363 | $media->loadByPK($metaValue); |
||
364 | |||
365 | return $media->hasLoaded() ? $media : false; |
||
366 | } |
||
367 | |||
368 | public function getNodeModelFromMetaValue($metaId) |
||
369 | { |
||
370 | $metaValue = (int) $this->getMetaValue($metaId); |
||
371 | $node = new NodeModel(); |
||
372 | $node->loadByPK($metaValue); |
||
373 | |||
374 | return $node->hasLoaded() ? $node : false; |
||
375 | } |
||
376 | |||
377 | public function saveMeta() |
||
378 | { |
||
379 | foreach ($this->getValues() as $key => $value) { |
||
380 | // don't ignore empty values |
||
381 | // if (substr($key, 0, 5) === 'meta_' && $value) { |
||
382 | if (substr($key, 0, 5) === 'meta_') { |
||
383 | $metaId = str_replace('meta_', '', $key); |
||
384 | $this->saveMetaValue($metaId, $value); |
||
385 | } |
||
386 | } |
||
387 | } |
||
388 | |||
389 | public function saveMetaValue($metaId, $value) |
||
390 | { |
||
391 | if (!is_numeric($metaId)) { |
||
392 | $metaId = $this->lookupMetaName($metaId); |
||
393 | } |
||
394 | |||
395 | $this->deleteMetaValue($metaId); |
||
396 | |||
397 | // Get meta stuff |
||
398 | $meta = new MetaModel(); |
||
399 | $meta->loadByPK($metaId); |
||
400 | $metaType = Ajde_Crud_Cms_Meta::fromType($meta->getType()); |
||
0 ignored issues
–
show
The method
getType does not exist on object<MetaModel> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
401 | |||
402 | // Before save |
||
403 | $value = $metaType->beforeSave($meta, $value, $this); |
||
404 | |||
405 | // Insert new ones |
||
406 | $sql = 'INSERT INTO '.$this->getMetaTable().' ('.$this->getTable().', meta, VALUE) VALUES (?, ?, ?)'; |
||
407 | $statement = $this->getConnection()->prepare($sql); |
||
408 | $statement->execute([$this->getPK(), $metaId, $value]); |
||
409 | |||
410 | // After save |
||
411 | $metaType->afterSave($meta, $value, $this); |
||
412 | |||
413 | $this->_metaValues[$metaId] = $value; |
||
414 | } |
||
415 | |||
416 | public function deleteMetaValue($metaId) |
||
417 | { |
||
418 | if (!is_numeric($metaId)) { |
||
419 | $metaId = $this->lookupMetaName($metaId); |
||
420 | } |
||
421 | |||
422 | // Delete old records |
||
423 | $sql = 'DELETE FROM '.$this->getMetaTable().' WHERE '.$this->getTable().' = ? AND meta = ?'; |
||
424 | $statement = $this->getConnection()->prepare($sql); |
||
425 | $statement->execute([$this->getPK(), $metaId]); |
||
426 | } |
||
427 | |||
428 | /** |
||
429 | * @param array $fields |
||
430 | */ |
||
431 | public function setEncryptedFields($fields) |
||
432 | { |
||
433 | $this->_encrypedFields = $fields; |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * @param string $field |
||
438 | */ |
||
439 | public function addEncryptedField($field) |
||
440 | { |
||
441 | $this->_encrypedFields[] = $field; |
||
442 | } |
||
443 | |||
444 | /** |
||
445 | * @return array |
||
446 | */ |
||
447 | public function getEncryptedFields() |
||
448 | { |
||
449 | return $this->_encrypedFields; |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * @param string $field |
||
454 | * |
||
455 | * @return bool |
||
456 | */ |
||
457 | public function isFieldEncrypted($field) |
||
458 | { |
||
459 | return in_array($field, $this->getEncryptedFields()); |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * @return array |
||
464 | */ |
||
465 | public function getJsonFields() |
||
466 | { |
||
467 | return $this->_jsonFields; |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * @param string $field |
||
472 | * |
||
473 | * @return bool |
||
474 | */ |
||
475 | public function isFieldJson($field) |
||
476 | { |
||
477 | return in_array($field, $this->getJsonFields()); |
||
478 | } |
||
479 | |||
480 | /** |
||
481 | * @return bool |
||
482 | */ |
||
483 | public function save() |
||
484 | { |
||
485 | if (method_exists($this, 'beforeSave')) { |
||
486 | $this->beforeSave(); |
||
0 ignored issues
–
show
The method
beforeSave does not exist on object<Ajde_Model> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
487 | } |
||
488 | $pk = $this->getTable()->getPK(); |
||
489 | |||
490 | $sqlSet = []; |
||
491 | $values = []; |
||
492 | |||
493 | // encryption |
||
494 | foreach ($this->getEncryptedFields() as $field) { |
||
495 | if ($this->has($field)) { |
||
496 | parent::_set($field, $this->encrypt($field)); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_set() instead of save() ). Are you sure this is correct? If so, you might want to change this to $this->_set() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
497 | } |
||
498 | } |
||
499 | |||
500 | foreach ($this->getTable()->getFieldNames() as $field) { |
||
501 | // Don't save a field is it's empty or not set |
||
502 | if ($this->has($field)) { |
||
503 | if ($this->getTable()->getFieldProperties($field, |
||
504 | 'type') === Ajde_Db::FIELD_TYPE_DATE && parent::_get($field) instanceof DateTime |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of save() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
505 | ) { |
||
506 | $sqlSet[] = $field.' = ?'; |
||
507 | $values[] = parent::_get($field)->format('Y-m-d h:i:s'); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of save() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
508 | } elseif ($this->getTable()->getFieldProperties($field, |
||
509 | 'isAutoUpdate') && !$this->get($field) instanceof Ajde_Db_Function |
||
510 | ) { |
||
511 | // just ignore this field |
||
512 | } elseif ($this->isEmpty($field) && !$this->getTable()->getFieldProperties($field, 'isRequired')) { |
||
513 | $sqlSet[] = $field.' = NULL'; |
||
514 | } elseif (!$this->isEmpty($field)) { |
||
515 | if ($this->get($field) instanceof Ajde_Db_Function) { |
||
516 | $sqlSet[] = $field.' = '.(string) $this->get($field); |
||
517 | View Code Duplication | } elseif ($this->getTable()->getFieldProperties($field, 'type') === Ajde_Db::FIELD_TYPE_SPATIAL) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
518 | $pointValues = explode(' ', (string) parent::_get($field)); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of save() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
519 | $sqlSet[] = $field.' = PointFromWKB(POINT('.str_replace(',', '.', |
||
520 | (float) $pointValues[0]).','.str_replace(',', '.', (float) $pointValues[1]).'))'; |
||
521 | } else { |
||
522 | $sqlSet[] = $field.' = ?'; |
||
523 | $value = parent::_get($field); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of save() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
524 | if (is_float($value)) { |
||
525 | $values[] = $value; |
||
526 | } else { |
||
527 | $values[] = (string) $value; |
||
528 | } |
||
529 | } |
||
530 | } elseif ($this->get($field) === 0 || $this->get($field) === '0') { |
||
531 | $sqlSet[] = $field.' = ?'; |
||
532 | $values[] = (string) parent::_get($field); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of save() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
533 | } else { |
||
534 | // Field is required but has an empty value.. |
||
535 | // (shouldn't have passed validation) |
||
536 | // TODO: set to empty string or ignore? |
||
537 | } |
||
538 | } |
||
539 | } |
||
540 | $values[] = $this->getPK(); |
||
541 | $sql = 'UPDATE '.$this->_table.' SET '.implode(', ', $sqlSet).' WHERE '.$pk.' = ?'; |
||
542 | $statement = $this->getConnection()->prepare($sql); |
||
543 | $return = $statement->execute($values); |
||
544 | if ($this->_hasMeta === true) { |
||
545 | $this->saveMeta(); |
||
546 | } |
||
547 | if (method_exists($this, 'afterSave')) { |
||
548 | $this->afterSave(); |
||
0 ignored issues
–
show
The method
afterSave does not exist on object<Ajde_Model> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
549 | } |
||
550 | |||
551 | return $return; |
||
552 | } |
||
553 | |||
554 | public function insert($pkValue = null, $skipBeforeInsert = false) |
||
555 | { |
||
556 | if (method_exists($this, 'beforeInsert') && $skipBeforeInsert === false) { |
||
557 | $this->beforeInsert(); |
||
0 ignored issues
–
show
|
|||
558 | } |
||
559 | $pk = $this->getTable()->getPK(); |
||
560 | if (isset($pkValue)) { |
||
561 | $this->set($pk, $pkValue); |
||
562 | } else { |
||
563 | $this->set($pk, null); |
||
564 | } |
||
565 | $sqlFields = []; |
||
566 | $sqlValues = []; |
||
567 | $values = []; |
||
568 | |||
569 | // encryption |
||
570 | foreach ($this->getEncryptedFields() as $field) { |
||
571 | if ($this->has($field)) { |
||
572 | parent::_set($field, $this->encrypt($field)); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_set() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_set() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
573 | } |
||
574 | } |
||
575 | |||
576 | foreach ($this->getTable()->getFieldNames() as $field) { |
||
577 | // Don't save a field is it's empty or not set |
||
578 | if ($this->has($field) && $this->getTable()->getFieldProperties($field, |
||
579 | 'type') === Ajde_Db::FIELD_TYPE_DATE && parent::_get($field) instanceof DateTime |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
580 | ) { |
||
581 | $sqlFields[] = $field; |
||
582 | $sqlValues[] = '?'; |
||
583 | $values[] = parent::_get($field)->format('Y-m-d h:i:s'); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
584 | } else { |
||
585 | if ($this->has($field) && !$this->isEmpty($field)) { |
||
586 | if ($this->get($field) instanceof Ajde_Db_Function) { |
||
587 | $sqlFields[] = $field; |
||
588 | $sqlValues[] = (string) $this->get($field); |
||
589 | View Code Duplication | } elseif ($this->getTable()->getFieldProperties($field, 'type') === Ajde_Db::FIELD_TYPE_SPATIAL) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
590 | $sqlFields[] = $field; |
||
591 | $pointValues = explode(' ', (string) parent::_get($field)); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
592 | $sqlValues[] = 'PointFromWKB(POINT('.str_replace(',', '.', |
||
593 | (float) $pointValues[0]).','.str_replace(',', '.', (float) $pointValues[1]).'))'; |
||
594 | } else { |
||
595 | $sqlFields[] = $field; |
||
596 | $sqlValues[] = '?'; |
||
597 | $value = parent::_get($field); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
598 | if (is_float($value)) { |
||
599 | $values[] = $value; |
||
600 | } else { |
||
601 | $values[] = (string) $value; |
||
602 | } |
||
603 | } |
||
604 | } else { |
||
605 | if ($this->has($field) && ($this->get($field) === 0 || $this->get($field) === '0')) { |
||
606 | $sqlFields[] = $field; |
||
607 | $sqlValues[] = '?'; |
||
608 | $values[] = (string) parent::_get($field); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
609 | } else { |
||
610 | parent::_set($field, null); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_set() instead of insert() ). Are you sure this is correct? If so, you might want to change this to $this->_set() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
611 | } |
||
612 | } |
||
613 | } |
||
614 | } |
||
615 | $sql = 'INSERT INTO '.$this->_table.' ('.implode(', ', $sqlFields).') VALUES ('.implode(', ', |
||
616 | $sqlValues).')'; |
||
617 | $statement = $this->getConnection()->prepare($sql); |
||
618 | $return = $statement->execute($values); |
||
619 | if (!isset($pkValue)) { |
||
620 | $this->set($pk, $this->getConnection()->lastInsertId()); |
||
621 | } |
||
622 | if ($this->_hasMeta === true) { |
||
623 | $this->saveMeta(); |
||
624 | } |
||
625 | if (method_exists($this, 'afterInsert')) { |
||
626 | $this->afterInsert(); |
||
0 ignored issues
–
show
|
|||
627 | } |
||
628 | |||
629 | return $return; |
||
630 | } |
||
631 | |||
632 | public function delete() |
||
633 | { |
||
634 | if (method_exists($this, 'beforeDelete')) { |
||
635 | $this->beforeDelete(); |
||
0 ignored issues
–
show
|
|||
636 | } |
||
637 | $id = $this->getPK(); |
||
638 | $pk = $this->getTable()->getPK(); |
||
639 | $sql = 'DELETE FROM '.$this->_table.' WHERE '.$pk.' = ? LIMIT 1'; |
||
640 | $statement = $this->getConnection()->prepare($sql); |
||
641 | try { |
||
642 | $return = $statement->execute([$id]); |
||
643 | } catch (Ajde_Db_IntegrityException $e) { |
||
644 | return false; |
||
645 | } |
||
646 | if (method_exists($this, 'afterDelete')) { |
||
647 | $this->afterDelete(); |
||
0 ignored issues
–
show
|
|||
648 | } |
||
649 | |||
650 | return $return; |
||
651 | } |
||
652 | |||
653 | public function hasParent($parent) |
||
654 | { |
||
655 | if (!$parent instanceof Ajde_Db_Table) { |
||
656 | // throws error if no table can be found |
||
657 | $parent = new Ajde_Db_Table($parent); |
||
658 | } |
||
659 | $fk = $this->getTable()->getFK($parent); |
||
660 | |||
661 | return $fk; |
||
662 | } |
||
663 | |||
664 | public function getParents() |
||
665 | { |
||
666 | return $this->getTable()->getParents(); |
||
667 | } |
||
668 | |||
669 | public function exists() |
||
670 | { |
||
671 | return (bool) $this->getPK(); |
||
672 | } |
||
673 | |||
674 | public function hasLoaded() |
||
675 | { |
||
676 | return !empty($this->_data); |
||
677 | } |
||
678 | |||
679 | public function hasParentLoaded($parent) |
||
680 | { |
||
681 | return $this->has($parent) && $this->get($parent) instanceof self && $this->get($parent)->hasLoaded(); |
||
682 | } |
||
683 | |||
684 | public function loadParents() |
||
685 | { |
||
686 | foreach ($this->getParents() as $column) { |
||
687 | $this->loadParent($column); |
||
688 | } |
||
689 | } |
||
690 | |||
691 | public function loadParent($column) |
||
692 | { |
||
693 | if (empty($this->_data)) { |
||
694 | // TODO: |
||
695 | throw new Ajde_Exception('Model '.(string) $this->getTable().' not loaded when loading parent'); |
||
696 | } |
||
697 | if ($this->hasParentLoaded($column)) { |
||
698 | return; |
||
699 | } |
||
700 | if (!$this->has($column)) { |
||
701 | // No value for FK field |
||
702 | return false; |
||
703 | } |
||
704 | $parentModel = $this->getParentModel($column); |
||
705 | if ($parentModel === false) { |
||
706 | // TODO: |
||
707 | throw new Ajde_Exception('Could not load parent model \''.$column."'"); |
||
708 | } |
||
709 | if ($parentModel->getTable()->getPK() != $this->getParentField($column)) { |
||
710 | // TODO: |
||
711 | throw new Ajde_Exception('Constraints on non primary key fields are currently not supported'); |
||
712 | } |
||
713 | $parentModel->loadByPK($this->get($column)); |
||
714 | $this->set($column, $parentModel); |
||
715 | } |
||
716 | |||
717 | /** |
||
718 | * @param string $column |
||
719 | * |
||
720 | * @return Ajde_Model |
||
721 | */ |
||
722 | public function getParentModel($column) |
||
723 | { |
||
724 | $parentModelName = ucfirst($this->getParentTable($column)).'Model'; |
||
725 | if (!class_exists($parentModelName)) { |
||
726 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by Ajde_Model::getParentModel of type Ajde_Model .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
727 | } |
||
728 | |||
729 | return new $parentModelName(); |
||
730 | } |
||
731 | |||
732 | public function getParentTable($column) |
||
733 | { |
||
734 | $fk = $this->getTable()->getFK($column); |
||
735 | |||
736 | return strtolower($fk['parent_table']); |
||
737 | } |
||
738 | |||
739 | public function getParentField($column) |
||
740 | { |
||
741 | $fk = $this->getTable()->getFK($column); |
||
742 | |||
743 | return strtolower($fk['parent_field']); |
||
744 | } |
||
745 | |||
746 | public function getAutoloadParents() |
||
747 | { |
||
748 | return $this->_autoloadParents; |
||
749 | } |
||
750 | |||
751 | public function addValidator($fieldName, Ajde_Model_ValidatorAbstract $validator) |
||
752 | { |
||
753 | $validator->setModel($this); |
||
754 | if (!isset($this->_validators[$fieldName])) { |
||
755 | $this->_validators[$fieldName] = []; |
||
756 | } |
||
757 | $this->_validators[$fieldName][] = $validator; |
||
758 | } |
||
759 | |||
760 | public function getValidators() |
||
761 | { |
||
762 | return $this->_validators; |
||
763 | } |
||
764 | |||
765 | public function getValidatorsFor($fieldName) |
||
766 | { |
||
767 | if (!isset($this->_validators[$fieldName])) { |
||
768 | $this->_validators[$fieldName] = []; |
||
769 | } |
||
770 | |||
771 | return $this->_validators[$fieldName]; |
||
772 | } |
||
773 | |||
774 | public function validate($fieldOptions = []) |
||
775 | { |
||
776 | if (method_exists($this, 'beforeValidate')) { |
||
777 | $return = $this->beforeValidate(); |
||
0 ignored issues
–
show
|
|||
778 | if ($return !== true && $return !== false) { |
||
779 | // TODO: |
||
780 | throw new Ajde_Exception(sprintf('beforeValidate() must return either TRUE or FALSE')); |
||
781 | } |
||
782 | if ($return === false) { |
||
783 | return false; |
||
784 | } |
||
785 | } |
||
786 | |||
787 | if (!$this->hasLoaded()) { |
||
788 | return false; |
||
789 | } |
||
790 | $errors = []; |
||
791 | $validator = $this->_getValidator(); |
||
792 | |||
793 | $valid = $validator->validate($fieldOptions); |
||
794 | if (!$valid) { |
||
795 | $errors = $validator->getErrors(); |
||
796 | } |
||
797 | $this->setValidationErrors($errors); |
||
0 ignored issues
–
show
The method
setValidationErrors does not exist on object<Ajde_Model> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
798 | |||
799 | if (method_exists($this, 'afterValidate')) { |
||
800 | $this->afterValidate(); |
||
0 ignored issues
–
show
|
|||
801 | } |
||
802 | |||
803 | return $valid; |
||
804 | } |
||
805 | |||
806 | public function getValidationErrors() |
||
807 | { |
||
808 | return parent::getValidationErrors(); |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Ajde_Object_Standard as the method getValidationErrors() does only exist in the following sub-classes of Ajde_Object_Standard : AclModel , Ajde_Acl , Ajde_Acl_Proxy_Model , Ajde_Lang_Proxy_Model , Ajde_Model , Ajde_Model_Revision , Ajde_Model_With_Acl , Ajde_Model_With_AclI18n , Ajde_Model_With_AclI18nRevision , Ajde_Model_With_AclRevision , Ajde_Model_With_I18n , Ajde_Model_With_Revision , Ajde_Shop_Cart , Ajde_Shop_Cart_Item , Ajde_Shop_Transaction , Ajde_User , CartItemModel , CartModel , EmailModel , FormModel , LogModel , MailerlogModel , MediaModel , MediatypeModel , MenuModel , MetaModel , NodeModel , NodetypeModel , ProductModel , RevisionModel , SettingModel , SsoModel , SubmissionModel , TagModel , TemplateModel , TestModel , TransactionItemModel , TransactionModel , UserModel , UsergroupModel , VatModel . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
809 | } |
||
810 | |||
811 | /** |
||
812 | * @return Ajde_Model_Validator |
||
813 | */ |
||
814 | private function _getValidator() |
||
815 | { |
||
816 | return new Ajde_Model_Validator($this); |
||
817 | } |
||
818 | |||
819 | public function hash() |
||
820 | { |
||
821 | $str = implode('', $this->valuesAsSingleDimensionArray()); |
||
822 | |||
823 | return md5($str); |
||
824 | } |
||
825 | |||
826 | public function isEncrypted($field) |
||
827 | { |
||
828 | return substr_count(Ajde_Component_String::decrypt(parent::_get($field)), |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of isEncrypted() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
829 | self::ENCRYPTION_PREFIX.config('security.secret')); |
||
830 | } |
||
831 | |||
832 | public function encrypt($field) |
||
833 | { |
||
834 | if (!$this->isEmpty($field)) { |
||
835 | if ($this->isEncrypted($field)) { |
||
836 | return parent::_get($field); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of encrypt() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
837 | } |
||
838 | |||
839 | return $this->doEncrypt(parent::_get($field)); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of encrypt() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
840 | } |
||
841 | } |
||
842 | |||
843 | public function doEncrypt($string) |
||
844 | { |
||
845 | return Ajde_Component_String::encrypt(self::ENCRYPTION_PREFIX.config('security.secret').$string); |
||
846 | } |
||
847 | |||
848 | public function decrypt($field) |
||
849 | { |
||
850 | if (!$this->isEncrypted($field)) { |
||
851 | return parent::_get($field); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of decrypt() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
852 | } |
||
853 | $decrypted = str_replace(self::ENCRYPTION_PREFIX.config('security.secret'), '', |
||
854 | Ajde_Component_String::decrypt(parent::_get($field))); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
_get() instead of decrypt() ). Are you sure this is correct? If so, you might want to change this to $this->_get() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
855 | |||
856 | return $decrypted; |
||
857 | } |
||
858 | |||
859 | // TREE SORT FUNCTIONS |
||
860 | |||
861 | public function sortTree($collectionName, $parentField = 'parent', $levelField = 'level', $sortField = 'sort') |
||
862 | { |
||
863 | $collection = new $collectionName(); |
||
864 | $collection->addFilter(new Ajde_Filter_Where($parentField, Ajde_Filter::FILTER_IS, null)); |
||
865 | $collection->orderBy($sortField); |
||
866 | |||
867 | // Start at root path |
||
868 | $this->_recurseChildren($collection, $collectionName, $parentField, $levelField, $sortField); |
||
869 | } |
||
870 | |||
871 | private function _recurseChildren( |
||
872 | $collection, |
||
873 | $collectionName, |
||
874 | $parentField, |
||
875 | $levelField, |
||
876 | $sortField, |
||
877 | $updatedField = 'updated' |
||
878 | ) { |
||
879 | static $sort; |
||
880 | static $level; |
||
881 | /** @var $item Ajde_Acl_Proxy_Model */ |
||
882 | foreach ($collection as $item) { |
||
883 | $sort++; |
||
884 | $item->set($sortField, $sort); |
||
885 | $item->set($levelField, $level); |
||
886 | $item->set($updatedField, new Ajde_Db_Function($updatedField)); |
||
887 | if ($item instanceof Ajde_Acl_Proxy_Model) { |
||
888 | if ($item->validateAccess('update', false)) { |
||
889 | $item->save(); |
||
890 | } |
||
891 | } else { |
||
892 | $item->save(); |
||
893 | } |
||
894 | // Look for children |
||
895 | $children = new $collectionName(); |
||
896 | $children->addFilter(new Ajde_Filter_Where($parentField, Ajde_Filter::FILTER_EQUALS, $item->getPK())); |
||
897 | $children->orderBy($sortField); |
||
898 | if ($children->count()) { |
||
899 | $level++; |
||
900 | $this->_recurseChildren($children, $collectionName, $parentField, $levelField, $sortField); |
||
901 | } |
||
902 | } |
||
903 | $level--; |
||
904 | } |
||
905 | } |
||
906 |
If you suppress an error, we recommend checking for the error condition explicitly: