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; |
||
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; |
||
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; |
||
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([ |
||
0 ignored issues
–
show
|
|||
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([ |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
53% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
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 | //автоопределени формата массива |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
52% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
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 = []; |
||
0 ignored issues
–
show
$entities is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
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; |
||
581 | return $o; |
||
582 | } |
||
583 | |||
584 | public function withDelete(){ |
||
585 | $o = clone $this; |
||
586 | $o->use_delete = true; |
||
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; |
||
597 | return $o; |
||
598 | } |
||
599 | |||
600 | } |
||
601 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.