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 | namespace SimpleORM; |
||
4 | |||
5 | /** |
||
6 | * Description of AbstractDataMapper |
||
7 | * |
||
8 | * @author Dmitriy |
||
9 | */ |
||
10 | abstract class AbstractDataMapper implements RepositoryInterface, MapperInterface |
||
11 | { |
||
12 | |||
13 | use TraitDataMapperEvent; |
||
14 | |||
15 | |||
16 | /** |
||
17 | * адаптер для работы с бд |
||
18 | * @var type |
||
19 | */ |
||
20 | protected $adapter; |
||
21 | |||
22 | /** |
||
23 | * таблица для сущности |
||
24 | * @var type |
||
25 | */ |
||
26 | protected $entityTable; |
||
27 | |||
28 | /** |
||
29 | * первичный ключ |
||
30 | * @var type |
||
31 | */ |
||
32 | protected $key; |
||
33 | |||
34 | /** |
||
35 | * Использование join при выборке |
||
36 | * @var type |
||
37 | */ |
||
38 | protected $use_joins = false; |
||
39 | |||
40 | /** |
||
41 | * Использование мягкое удаление |
||
42 | * @var type |
||
43 | */ |
||
44 | protected $use_delete = false; |
||
45 | |||
46 | /** |
||
47 | * поле для мягкого удаления |
||
48 | * @var type |
||
49 | */ |
||
50 | protected $soft_delete_key; |
||
51 | |||
52 | |||
53 | /** |
||
54 | * поля сущности |
||
55 | * @var type |
||
56 | */ |
||
57 | protected $mapping_fields = []; |
||
58 | |||
59 | /** |
||
60 | * псевдонимы полей сущности |
||
61 | * @var type |
||
62 | */ |
||
63 | protected $mapping_fields_aliases = []; |
||
64 | |||
65 | /** |
||
66 | * связи с другими мапперами |
||
67 | * @var type |
||
68 | */ |
||
69 | protected $relations = []; |
||
70 | |||
71 | /** |
||
72 | * Контейнер |
||
73 | * @var League\Container\Container |
||
74 | */ |
||
75 | protected $DI; |
||
76 | |||
77 | /** |
||
78 | * Возврат данных в массиве |
||
79 | * @var type |
||
80 | */ |
||
81 | protected $result_array = false; |
||
82 | |||
83 | function __construct(\League\Container\Container $DI, QueryBuilderInterface $adapter, $db_name = null) { |
||
84 | |||
85 | $this->DI = $DI; |
||
0 ignored issues
–
show
|
|||
86 | |||
87 | $this->setMappingFields(); |
||
88 | |||
89 | $this->setAdapter($adapter); |
||
90 | |||
91 | $this->setEntityTable($db_name); |
||
92 | |||
93 | if($this->getEntityTable()=='' || $this->getPrimaryKey()==''){ |
||
94 | throw new InvalidEntityPropertyException('Свойства entityTable или key не заданы'); |
||
95 | } |
||
96 | |||
97 | } |
||
98 | |||
99 | abstract protected function setMappingFields(); |
||
100 | |||
101 | public function getAdapter() { |
||
102 | return $this->adapter; |
||
103 | } |
||
104 | |||
105 | public function setAdapter(QueryBuilderInterface $adapter){ |
||
106 | $this->adapter = $adapter; |
||
0 ignored issues
–
show
It seems like
$adapter of type object<SimpleORM\QueryBuilderInterface> is incompatible with the declared type object<SimpleORM\type> of property $adapter .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
107 | } |
||
108 | |||
109 | |||
110 | protected function getEntityTable() { |
||
111 | return $this->entityTable; |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Уставнока таблицы |
||
116 | */ |
||
117 | protected function setEntityTable($db_name) { |
||
118 | $this->entityTable = !empty($db_name)? "$db_name.".$this->table : $this->table; |
||
0 ignored issues
–
show
The property
table does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Получение записи по ключу |
||
123 | * @param type $id |
||
124 | * @return type |
||
125 | */ |
||
126 | public function findById($id) |
||
127 | { |
||
128 | $Criteria = (new Specification())->setWhere($this->key , $id); |
||
129 | |||
130 | return $this->findBySpecification($Criteria); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * Сохранение сущности без спобытий |
||
135 | * @param \SimpleORM\EntityInterface $Entity |
||
136 | */ |
||
137 | public function saveWithoutEvents(EntityInterface $Entity) { |
||
138 | |||
139 | $data = $this->unbuildEntity($Entity); |
||
140 | |||
141 | if(method_exists($this, 'onPrepareData' )) $this->onPrepareData( $Entity , $data ); |
||
142 | |||
143 | $id = $data[$this->getPrimaryKey()]; |
||
144 | unset($data[$this->getPrimaryKey()]); |
||
145 | |||
146 | //insert |
||
147 | if (empty($id)) { |
||
148 | |||
149 | unset($data[$this->setSoftDeleteKey()]); |
||
150 | |||
151 | $this->getAdapter()->insert($this->getEntityTable(),$data); |
||
152 | |||
153 | if (!$id = $this->getAdapter()->insert_id()) { |
||
154 | return false; |
||
155 | } |
||
156 | |||
157 | $Entity->setId($id); |
||
158 | } |
||
159 | //update |
||
160 | else { |
||
161 | |||
162 | if(!$this->getAdapter()->update($this->getEntityTable(), $data, "{$this->getPrimaryKey()} = '{$id}'")){ |
||
163 | return false; |
||
164 | } |
||
165 | |||
166 | } |
||
167 | |||
168 | return true; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Cохранение сущности |
||
173 | * @param EntityInterface $Entity |
||
174 | */ |
||
175 | public function save(EntityInterface $Entity) |
||
176 | { |
||
177 | if(method_exists($this, 'onAfterSave' )) $this->onAfterSave( $Entity ); |
||
178 | |||
179 | if(!$this->saveWithoutEvents($Entity)){ |
||
180 | return false; |
||
181 | } |
||
182 | |||
183 | if(method_exists($this, 'onBeforeSave' )) $this->onBeforeSave( $Entity ); |
||
184 | |||
185 | return true; |
||
186 | } |
||
187 | |||
188 | |||
189 | /** |
||
190 | * получение мапперов в порядке их использования с учетом вложенности |
||
191 | * @return array |
||
192 | */ |
||
193 | protected function createListRelation(){ |
||
194 | $rel_list = []; |
||
195 | |||
196 | $rel_map = $this->getRelations(); |
||
197 | |||
198 | $this->createListRelationReq($rel_map,$rel_list); |
||
199 | |||
200 | return $rel_list; |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Выстроивает порядок использования мапперов в иерархии |
||
205 | * @param array $rel_map |
||
206 | * @param type $rel_list |
||
207 | */ |
||
208 | protected function createListRelationReq(array $rel_map,&$rel_list,$obj_parent_link = null) { |
||
209 | |||
210 | foreach ($rel_map as $rel){ |
||
211 | |||
212 | $obj_link = '#'.$rel['alias'].'()'; |
||
213 | |||
214 | if(count($rel['relations'])>0){ |
||
215 | $this->createListRelationReq($rel['relations'],$rel_list,$obj_parent_link.'get'.$rel['alias'].'()'); |
||
216 | $rel_list [$obj_parent_link.$obj_link]= $rel['name']; |
||
217 | } |
||
218 | else{ |
||
219 | $rel_list [$obj_parent_link.$obj_link] = $rel['name']; |
||
220 | } |
||
221 | } |
||
222 | } |
||
223 | |||
224 | |||
225 | /** |
||
226 | * получить связи |
||
227 | */ |
||
228 | protected function getRelations(){ |
||
229 | $rel_map = []; |
||
230 | foreach ($this->mapping_fields as $field => $cfg){ |
||
231 | if(isset($cfg['relation'])){ |
||
232 | $rels = $this->DI->get($cfg['relation'])->getRelations(); |
||
233 | $rel_map []= [ |
||
234 | 'name' => $cfg['relation'], |
||
235 | 'alias' => $field, |
||
236 | 'relations' => $rels |
||
237 | ]; |
||
238 | } |
||
239 | } |
||
240 | return $rel_map; |
||
241 | } |
||
242 | |||
243 | |||
244 | |||
245 | |||
246 | |||
247 | |||
248 | |||
249 | /** |
||
250 | * Подготавливаем конечный вариант Сущности |
||
251 | * |
||
252 | * @param \Core\Infrastructure\EntityInterface $Entity |
||
253 | * @param array $row |
||
254 | * @return \Core\Infrastructure\EntityInterface |
||
255 | * @throws BadMethodCallException |
||
256 | */ |
||
257 | protected function buildEntity(EntityInterface $Entity, array $row){ |
||
258 | //ed($row); |
||
259 | foreach ($this->mapping_fields as $alias => $cfg ) { |
||
260 | |||
261 | $value = false; |
||
262 | |||
263 | //автоопределени формата массива |
||
264 | $field = $cfg['field']; |
||
265 | |||
266 | $method_set = 'set' . ucfirst($alias); |
||
267 | |||
268 | if(!method_exists($Entity, $method_set )){ |
||
269 | throw new BadMethodCallException("Метод {$method_set} не определен"); |
||
270 | } |
||
271 | |||
272 | //событие на формирование поля |
||
273 | if( isset($cfg['build']) && is_object($cfg['build']) ){ |
||
274 | |||
275 | // ed([ |
||
276 | // get_class($Entity), |
||
277 | // $row |
||
278 | // ]); |
||
279 | |||
280 | |||
281 | $value = call_user_func($cfg['build'], $row); |
||
282 | } |
||
283 | //на связь |
||
284 | elseif(isset($cfg['relation'])){ |
||
285 | |||
286 | $mapper = $this->DI->get($cfg['relation']); |
||
287 | |||
288 | if($this->use_joins===true || empty($row[$field])){ |
||
289 | |||
290 | $value = $mapper->createEntity($row); |
||
291 | |||
292 | // ed([ |
||
293 | // get_class($mapper), |
||
294 | // $row, |
||
295 | // $value |
||
296 | // ]); |
||
297 | |||
298 | } |
||
299 | else{ |
||
300 | $fkey = isset($cfg['on']) ? $cfg['on'] :$mapper->key; |
||
301 | $value = $mapper->findBySpecification((new Specification)->setWhere($fkey, $row[$field])); |
||
302 | } |
||
303 | |||
304 | } |
||
305 | elseif(is_string($field) && isset($row[strtolower($field)])){ |
||
306 | $value = $row[strtolower($field)]; |
||
307 | } |
||
308 | |||
309 | if($value!==false) |
||
310 | $Entity->{$method_set}($value); |
||
311 | |||
312 | } |
||
313 | |||
314 | return $Entity; |
||
315 | } |
||
316 | |||
317 | |||
318 | /** |
||
319 | * из объекта формирует массив |
||
320 | * @param \Core\Infrastructure\EntityInterface $Entity |
||
321 | * @return \Core\Infrastructure\EntityInterface |
||
322 | * @throws BadMethodCallException |
||
323 | */ |
||
324 | protected function unbuildEntity(EntityInterface $Entity){ |
||
325 | |||
326 | $row = []; |
||
327 | |||
328 | foreach ($this->mapping_fields as $alias => $cfg ) { |
||
329 | |||
330 | //автоопределени формата массива |
||
331 | // if(isset($row[$this->key])){ |
||
332 | // $field = $cfg['field']; |
||
333 | // } |
||
334 | // else{ |
||
335 | // $field = $alias; |
||
336 | // } |
||
337 | $field = $cfg['field']; |
||
338 | |||
339 | $method_get = 'get' . ucfirst($alias); |
||
340 | |||
341 | if(!method_exists($Entity, $method_get )){ |
||
342 | throw new BadMethodCallException("Метод {$method_get} не определен"); |
||
343 | } |
||
344 | |||
345 | //-------------------------------------------------------------------- |
||
346 | if( isset($cfg['unbuild']) && is_object($cfg['unbuild']) ){ |
||
347 | $value = call_user_func($cfg['unbuild'], $Entity->{$method_get}() ); |
||
348 | } |
||
349 | elseif(isset($cfg['relation']) && is_object($Entity->{$method_get}()) ){ |
||
350 | |||
351 | if(isset($cfg['on'])) |
||
352 | $fkey = $this->DI->get($cfg['relation'])->getFieldAlias($cfg['on']); |
||
353 | else |
||
354 | $fkey = 'id'; |
||
355 | |||
356 | $value = $Entity->{$method_get}()->{'get'.$fkey}(); |
||
357 | |||
358 | } |
||
359 | else{ |
||
360 | $value = $Entity->{$method_get}(); |
||
361 | } |
||
362 | |||
363 | $row[$field] = $value; |
||
364 | |||
365 | } |
||
366 | |||
367 | return $row; |
||
368 | } |
||
369 | |||
370 | /** |
||
371 | * Установка поля для маппинга |
||
372 | */ |
||
373 | 5 | protected function addMappingField($alias,$field = null){ |
|
374 | |||
375 | 5 | if(is_string($field)){ |
|
376 | 1 | $field = ['field' => $field]; |
|
377 | 1 | } |
|
378 | 4 | elseif( (is_array($field) && !isset($field['field'])) || empty($field)){ |
|
379 | 1 | $field['field'] = $alias; |
|
380 | 1 | } |
|
381 | |||
382 | 5 | $this->mapping_fields[$alias] = $field; |
|
383 | |||
384 | 5 | if(isset($field['primary']) && $field['primary']===true){ |
|
385 | 1 | $this->key = $field['field']; |
|
386 | 1 | } |
|
387 | |||
388 | 5 | if(isset($field['softdelete']) && $field['softdelete']===true){ |
|
389 | 1 | $this->soft_delete_key = $field['field']; |
|
390 | 1 | } |
|
391 | |||
392 | 5 | $this->mapping_fields_aliases[$field['field']] = $alias; |
|
393 | |||
394 | 5 | return $this; |
|
395 | } |
||
396 | |||
397 | |||
398 | |||
399 | /** |
||
400 | * Установка ключа |
||
401 | */ |
||
402 | 1 | public function getPrimaryKey() { |
|
403 | 1 | return $this->key; |
|
404 | } |
||
405 | |||
406 | /** |
||
407 | * Устанвка поля для мягкого удаляения |
||
408 | */ |
||
409 | 1 | protected function setSoftDeleteKey() { |
|
410 | 1 | return $this->soft_delete_key; |
|
411 | } |
||
412 | |||
413 | |||
414 | /** |
||
415 | * получение алиаса поля |
||
416 | * @param type $field |
||
417 | * @return type |
||
418 | */ |
||
419 | 1 | public function getFieldAlias($field){ |
|
420 | 1 | return $this->mapping_fields_aliases[$field]; |
|
421 | } |
||
422 | |||
423 | /** |
||
424 | * получение поля по алиасу |
||
425 | * @param type $alias |
||
426 | * @return type |
||
427 | */ |
||
428 | public function getAliasField($alias) |
||
429 | { |
||
430 | return $this->mapping_fields[$alias]['field']; |
||
431 | } |
||
432 | |||
433 | |||
434 | /** |
||
435 | * |
||
436 | * @param ISpecificationCriteria $specification |
||
437 | * @return type |
||
438 | */ |
||
439 | public function findBySpecification(ISpecificationCriteria $specification){ |
||
440 | |||
441 | //псеводо удаление |
||
442 | $this->setSoftDelete($specification); |
||
443 | |||
444 | $this->setRelations($specification); |
||
445 | |||
446 | $specification->setLimit(1); |
||
447 | |||
448 | //получение записей |
||
449 | $res = $this->getAdapter()->getResultQuery($this->getEntityTable(),$specification); |
||
450 | |||
451 | if (!$row = $res->row_array()) { |
||
452 | return null; |
||
453 | } |
||
454 | |||
455 | if($this->result_array===true){ |
||
456 | return $row; |
||
457 | } |
||
458 | |||
459 | return $this->createEntity($row); |
||
460 | |||
461 | } |
||
462 | |||
463 | /** |
||
464 | * Удаление записи |
||
465 | * @param EntityInterface $Entity |
||
466 | * @return boolean |
||
467 | */ |
||
468 | public function delete(EntityInterface $Entity) |
||
469 | { |
||
470 | $result = false; |
||
471 | |||
472 | $delete_key = $this->setSoftDeleteKey(); |
||
473 | |||
474 | if ( |
||
475 | $delete_key > '' && |
||
476 | $Entity->getId() > 0){ |
||
477 | $result = $this->getAdapter()->update($this->getEntityTable(), [ $delete_key => 1 ], "{$this->getPrimaryKey()} = '{$Entity->getId()}'"); |
||
478 | } |
||
479 | elseif($Entity->getId() > 0){ |
||
480 | |||
481 | if($result = $this->getAdapter()->delete($this->getEntityTable(), $this->getPrimaryKey()." = ".$Entity->getId())){ |
||
482 | if(method_exists($this, 'onBeforeDelete' )){ $result = $this->onBeforeDelete( $Entity );} |
||
483 | } |
||
484 | } |
||
485 | |||
486 | return $result; |
||
487 | } |
||
488 | |||
489 | public function findAllBySpecification(ISpecificationCriteria $specification) |
||
490 | { |
||
491 | |||
492 | $entities = []; |
||
493 | |||
494 | //псеводо удаление |
||
495 | $this->setSoftDelete($specification); |
||
496 | |||
497 | $this->setRelations($specification); |
||
498 | |||
499 | $res = $this->getAdapter()->getResultQuery($this->getEntityTable(),$specification); |
||
500 | |||
501 | if (!$rows = $res->result_array()) { |
||
502 | return null; |
||
503 | } |
||
504 | |||
505 | if($this->result_array===true){ |
||
506 | return $rows; |
||
507 | } |
||
508 | |||
509 | foreach($rows as $k => $row){ |
||
510 | $rows[$k] = $this->createEntity($row); |
||
511 | } |
||
512 | |||
513 | return $rows; |
||
514 | } |
||
515 | |||
516 | public function findAll() |
||
517 | { |
||
518 | return $this->findAllBySpecification(new Specification()); |
||
519 | } |
||
520 | |||
521 | /** |
||
522 | * Выборка удаленных моделей |
||
523 | * @param ISpecificationCriteria $specification |
||
524 | */ |
||
525 | protected function setSoftDelete(ISpecificationCriteria $specification){ |
||
526 | if( |
||
527 | $this->use_delete === false && |
||
528 | $this->setSoftDeleteKey()>'' |
||
529 | && !isset($specification->getWhere()[$this->setSoftDeleteKey()]) |
||
530 | ) |
||
531 | $specification->setWhere($this->setSoftDeleteKey(),0); |
||
532 | } |
||
533 | |||
534 | /** |
||
535 | * Построение join-ов |
||
536 | * |
||
537 | * @todo добавить типы связей |
||
538 | * has_many - один к многим (пост и коммеентарии) |
||
539 | * belongs_to - многие к многим (пользователь имет множество оплат одного заказа) |
||
540 | * has_one - один к одному |
||
541 | */ |
||
542 | protected function setRelations(ISpecificationCriteria $Specification){ |
||
543 | |||
544 | $joins = []; |
||
545 | |||
546 | foreach ($this->mapping_fields as $field => $cfg){ |
||
547 | if(isset($cfg['relation'])){ |
||
548 | |||
549 | $reltype = isset($cfg['reltype']) ? $cfg['reltype'] : 'belongs_to'; |
||
550 | |||
551 | $this->relations[$field] = [ |
||
552 | 'mapper' => $mapper = $this->DI->get($cfg['relation']), |
||
553 | 'reltype' => $reltype |
||
554 | ]; |
||
555 | |||
556 | $table = $mapper->getEntityTable(); |
||
557 | |||
558 | $relation_key = isset($cfg['on'])? $cfg['on'] : $mapper->key; |
||
559 | |||
560 | $joins[$table] = [ |
||
561 | 'alias' => $field, |
||
562 | 'type' => $reltype != 'has_many' ? 'INNER' : 'LEFT OUTER', |
||
563 | 'on' => "`{$this->table}`.{$cfg['field']} = `{$field}`.{$relation_key}" |
||
564 | ]; |
||
565 | |||
566 | } |
||
567 | } |
||
568 | |||
569 | if($this->use_joins===true){ |
||
570 | $Specification->setJoins($joins); |
||
571 | } |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Использование join-ов |
||
576 | */ |
||
577 | public function useJoins() |
||
578 | { |
||
579 | $o = clone $this; |
||
580 | $o->use_joins = true; |
||
0 ignored issues
–
show
It seems like
true of type boolean is incompatible with the declared type object<SimpleORM\type> of property $use_joins .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
581 | return $o; |
||
582 | } |
||
583 | |||
584 | public function withDelete(){ |
||
585 | $o = clone $this; |
||
586 | $o->use_delete = true; |
||
0 ignored issues
–
show
It seems like
true of type boolean is incompatible with the declared type object<SimpleORM\type> of property $use_delete .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
587 | return $o; |
||
588 | } |
||
589 | |||
590 | /** |
||
591 | * Данные только в массиве |
||
592 | * @return \SimpleORM\AbstractDataMapper |
||
593 | */ |
||
594 | public function resultArray(){ |
||
595 | $o = clone $this; |
||
596 | $o->result_array = true; |
||
0 ignored issues
–
show
It seems like
true of type boolean is incompatible with the declared type object<SimpleORM\type> of property $result_array .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
597 | return $o; |
||
598 | } |
||
599 | |||
600 | } |
||
601 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..