1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
model.php
См. документацию.
1<?php
2namespace Bitrix\Report\VisualConstructor\Internal;
3
4use Bitrix\Main\ArgumentException;
5use Bitrix\Main\Entity\Query\Filter\ConditionTree;
6use Bitrix\Main\NotImplementedException;
7use Bitrix\Main\Type\DateTime;
8use Bitrix\Report\VisualConstructor\Config\Common;
9use Bitrix\Report\VisualConstructor\Entity\DashboardRow;
10use Bitrix\Report\VisualConstructor\Helper\Util;
11use Bitrix\Report\VisualConstructor\Internal\Error\IErrorable;
12
17abstract class Model implements IErrorable
18{
20 protected $id;
21 protected $createdAt;
22 protected $updatedAt;
23 protected $errors;
24 private $deletedEntities = array();
25 private $currentDbState = array();
26 //private $lazyAttributes;
27
31 public function __construct()
32 {
33 $this->createdAt = new DateTime();
34 $this->updatedAt = new DateTime();
35 }
36
42 public static function getTableClassName()
43 {
45 }
46
47
53 public static function getMapAttributes()
54 {
55 return array(
56 'ID' => 'id',
57 'CREATED_DATE' => 'createdAt',
58 'UPDATED_DATE' => 'updatedAt'
59 );
60 }
61
92 public static function getMapReferenceAttributes()
93 {
94 return array();
95 }
96
97
101 public function save()
102 {
103
104 $referenceMapAttributes = static::getMapReferenceAttributes();
105
106 foreach ($referenceMapAttributes as $referenceAttributeName => $assoc)
107 {
108 if (!empty($this->{$referenceAttributeName}))
109 {
110 switch ($assoc['type'])
111 {
112 case Common::MANY_TO_ONE:
113 $this->saveManyToOneReference($this->{$referenceAttributeName}, $assoc);
114 break;
115 case Common::ONE_TO_ONE:
116 //TODO:
117 break;
118 }
119 }
120 }
121
122 $ormFields = $this->getConvertedMapAttributesToOrmFields();
123 if (!$ormFields['ID'])
124 {
125 unset($ormFields['ID']);
126 $addResult = $this->add($ormFields);
127 $ownerId = $addResult->getId();
128 $this->setId($ownerId);
129 }
130 else
131 {
132 $ownerId = $ormFields['ID'];
133 $changedAttributes = $this->getChangedOrmAttributes($ormFields);
134 if ($changedAttributes)
135 {
136 $this->update(array('ID' => $ownerId), $changedAttributes);
137 }
138 if (!empty($this->deletedEntities))
139 {
140 $this->deleteReference($this->deletedEntities);
141 }
142 }
143
144
145
146
147 foreach ($referenceMapAttributes as $referenceAttributeName => $assoc)
148 {
149 if (!empty($this->{$referenceAttributeName}))
150 {
151 switch ($assoc['type'])
152 {
153 case Common::ONE_TO_MANY:
154 $this->saveOneToManyReferences($this->{$referenceAttributeName}, $assoc, $ownerId);
155 break;
156 case Common::MANY_TO_MANY:
157 $this->saveManyToManyReferences($this->{$referenceAttributeName}, $assoc, $ownerId);
158 break;
159 }
160 }
161 }
162
163 return $ownerId;
164 }
165
171 private function saveOneToManyReferences($references, $assoc, $ownerEntityId)
172 {
173 foreach ($references as $key => $reference)
174 {
175 if ($reference instanceof $assoc['targetEntity'])
176 {
177 $mapReferenceAttributes = $reference::getMapReferenceAttributes();
178 $reference->{$mapReferenceAttributes[$assoc['mappedBy']]['join']['field'][0]} = $ownerEntityId;
179 $reference->save();
180 }
181
182 }
183 }
184
190 private function saveManyToManyReferences($references, $assoc, $ownerEntityId)
191 {
192 foreach ($references as $key => $reference)
193 {
194 if ($reference instanceof $assoc['targetEntity'])
195 {
196 $isReferenceNew = !(boolean)$reference->getId();
197 $referenceId = $reference->save();
198 if ($isReferenceNew)
199 {
200 $column = array_values($assoc['join']['column']);
201 $column = $column[0];
202 $inverseColumn = array_values($assoc['join']['inverseColumn']);
203 $inverseColumn = $inverseColumn[0];
204 $connectData = array(
205 $column[1] => $ownerEntityId,
206 $inverseColumn[1] => $referenceId,
207 );
209 $ormTableClassName = $assoc['join']['tableClassName'];
210 $ormTableClassName::add($connectData);
211 }
212 }
213 }
214 }
215
220 private function saveManyToOneReference($reference, $assoc)
221 {
222 if ($reference instanceof $assoc['targetEntity'])
223 {
224 $reference = clone $reference;
225 $reference->{$assoc['inversedBy']} = null;
226 $reference->save();
227 $this->{$assoc['join']['field'][0]} = $reference->getId();
228 }
229 }
230
231
232
236 private function getConvertedMapAttributesToOrmFields()
237 {
238 $result = array();
239 $fieldsMap = static::getMapAttributes();
240 foreach ($fieldsMap as $ormFieldName => $objectProperty)
241 {
242 $result[$ormFieldName] = $this->{$objectProperty};
243 }
244 return $result;
245 }
246
247
252 private function add(array $data)
253 {
255 $tableClassName = static::getTableClassName();
256 $entity = $tableClassName::getEntity();
257 $primaryFields = $entity->getPrimaryArray();
258 foreach ($primaryFields as $field)
259 {
260 if (array_key_exists($field, $data) && empty($data[$field]))
261 {
262 unset($data[$field]);
263 }
264 }
265
266 $resultData = $tableClassName::add($data);
267 $this->currentDbState = $resultData->getData();
268 return $resultData;
269 }
270
275 private function getChangedOrmAttributes($newEntityAttributes)
276 {
277
282 $oldEntityAttributes = $this->getCurrentDbState();
283 unset($oldEntityAttributes['CREATED_DATE']);
284 unset($oldEntityAttributes['UPDATED_DATE']);
285 unset($newEntityAttributes['CREATED_DATE']);
286 unset($newEntityAttributes['UPDATED_DATE']);
287 $result = array();
288 foreach ($oldEntityAttributes as $key => $value)
289 {
290 if ($newEntityAttributes[$key] != $value)
291 {
292 $result[$key] = $newEntityAttributes[$key];
293 }
294 }
295
296 return $result;
297 }
298
304 private function update($primary, array $data)
305 {
306 $tableClassName = static::getTableClassName();
307 $data['UPDATED_DATE'] = new DateTime();
308 unset($data['ID']);
309 $resultData = $tableClassName::update($primary, $data);
310
311 foreach ($resultData->getData() as $key => $value)
312 {
313 $this->currentDbState[$key] = $value;
314 }
315 return $resultData;
316 }
317
318
322 public static function getClassName()
323 {
324 return get_called_class();
325 }
326
327
334 public static function load($filter, array $with = array(), $order = array())
335 {
336 $models = static::getModelList(array(
337 'select' => array('*'),
338 'filter' => $filter,
339 'with' => $with,
340 'order' => $order
341 ));
342 return array_shift($models);
343 }
344
350 protected static function getModelList(array $parameters)
351 {
352 $modelList = array();
353 $query = static::getList($parameters);
354 while ($row = $query->fetch())
355 {
356 if (!($modelList[$row['ID']] ?? false))
357 {
358 $model = static::buildFromArray($row);
359 }
360 else
361 {
362 $model = static::buildFromArray($row, $modelList[$row['ID']]);
363 }
364 if ($model->id)
365 {
366 $modelList[$model->id] = $model;
367 }
368 }
369
370 return $modelList;
371 }
372
378 protected static function getList(array $parameters)
379 {
381 $tableClass = static::getTableClassName();
382 return $tableClass::getList(static::prepareGetListParameters($parameters));
383 }
384
392 protected static function buildFromArray(array $attributes, $parentEntity = null)
393 {
395 $model = new static;
396 return $model->setAttributes($attributes, $parentEntity);
397 }
398
406 private function setAttributes(array $attributes, $parentEntity)
407 {
408 foreach ($attributes as $key => $value)
409 {
410 if ($value === null)
411 {
412 unset($attributes[$key]);
413 }
414 }
415 if (!$parentEntity)
416 {
417 $mapAttributes = static::getMapAttributes();
418 foreach ($attributes as $key => $value)
419 {
420 if (!empty($mapAttributes[$key]))
421 {
422 $this->{$mapAttributes[$key]} = $value;
423 $this->currentDbState[$key] = $value;
424 unset($attributes[$key]);
425 }
426 }
427 $parentEntity = $this;
428 }
429
430 if (empty($attributes))
431 {
432 return $parentEntity;
433 }
434
435 $subEntitiesMapAttributes = static::getMapReferenceAttributes();
436 $subEntitiesKeys = array_keys($subEntitiesMapAttributes);
437
438
439 $subEntityAttributes = array();
440 $loadedSubEntitiesKeys = array();
441 foreach ($attributes as $key => $value)
442 {
443 $delimiter = self::ATTRIBUTE_SLICE_DELIMITER;
444 $selectedAttributeParts = explode($delimiter, $key);
445 if (count($selectedAttributeParts) == 2 && in_array($selectedAttributeParts[0], $subEntitiesKeys))
446 {
447 $loadedSubEntitiesKeys[$selectedAttributeParts[0]] = $selectedAttributeParts[0];
448 $subEntityAttributes[$selectedAttributeParts[0]][$selectedAttributeParts[1]] = $value;
449 }
450 elseif (count($selectedAttributeParts) >= 2)
451 {
452 $nestedEntityParentKey = array_shift($selectedAttributeParts);
453 $nestedElementKey = implode(self::ATTRIBUTE_SLICE_DELIMITER, $selectedAttributeParts);
454 $subEntityAttributes[$nestedEntityParentKey][$nestedElementKey] = $value;
455 }
456 }
457
458 foreach ($subEntityAttributes as $key => $validAttributes)
459 {
460 if (!empty($subEntitiesMapAttributes[$key]))
461 {
463 $targetEntityClass = $subEntitiesMapAttributes[$key]['targetEntity'];
464 if ($subEntitiesMapAttributes[$key]['type'] != Common::MANY_TO_ONE)
465 {
466 if (!isset($parentEntity->{$key}[$validAttributes['ID']]))
467 {
468 $subEntity = $targetEntityClass::buildFromArray($validAttributes);
469
470 $nestedEntityReferenceMap = $subEntity::getMapReferenceAttributes();
471
472
476 if ($subEntitiesMapAttributes[$key]['type'] == Common::ONE_TO_MANY)
477 {
478 if (!empty($nestedEntityReferenceMap[$subEntitiesMapAttributes[$key]['mappedBy']]))
479 {
480 $subEntity->{$subEntitiesMapAttributes[$key]['mappedBy']} = $parentEntity;
481 }
482 }
483 $parentEntity->{$key}[$subEntity->id] = $subEntity;
484 }
485 else
486 {
487 $targetEntityClass::buildFromArray($validAttributes, $parentEntity->{$key}[$validAttributes['ID']]);
488 }
489 }
490 else
491 {
492 $subEntity = $targetEntityClass::buildFromArray($validAttributes);
493 $parentEntity->{$key} = $subEntity;
494 }
495
496 }
497 }
498
499
500 return $parentEntity;
501 }
502
508 protected static function prepareGetListParameters(array $parameters)
509 {
510 if (!empty($parameters['with']))
511 {
512 if (!is_array($parameters['with']))
513 {
514 throw new ArgumentException('"with" must be array');
515 }
516 if (!isset($parameters['select']))
517 {
518 $parameters['select'] = array('*');
519 }
520 elseif (!in_array('*', $parameters['select']) && !in_array('ID', $parameters['select']))
521 {
522 $parameters['select'][] = 'ID';
523 }
524 $parameters['select'] = array_merge($parameters['select'], static::buildOrmSelectForReference($parameters['with']));
525 }
526
527 unset($parameters['with']);
528 return $parameters;
529 }
530
536 protected static function buildOrmSelectForReference(array $with)
537 {
538 $select = array();
539 $referenceAttributes = static::getMapReferenceAttributes();
540 foreach ($with as $referenceKey)
541 {
542 $testNesting = explode('.', $referenceKey);
543 $nestedReferenceAttributes = $referenceAttributes;
544 $prefix = '';
545 $fromKeyNamePrefix = '';
546 foreach ($testNesting as $reference)
547 {
548 if (!empty($nestedReferenceAttributes[$reference]))
549 {
550 $prefix = $prefix . $reference . self::ATTRIBUTE_SLICE_DELIMITER;
551 switch ($nestedReferenceAttributes[$reference]['type'])
552 {
553 case Common::ONE_TO_MANY:
555 $targetEntity = $nestedReferenceAttributes[$reference]['targetEntity'];
556 $targetOrmTable = $targetEntity::getTableClassName();
557 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix . '.' : '';
558 $select[$prefix] = $fromKeyNamePrefix.$targetOrmTable::getClassName().':'.mb_strtoupper($nestedReferenceAttributes[$reference]['mappedBy']);
559 $fromKeyNamePrefix .= $targetOrmTable::getClassName().':'.mb_strtoupper($nestedReferenceAttributes[$reference]['mappedBy']);
560 $nestedReferenceAttributes = $targetEntity::getMapReferenceAttributes();
561 break;
562 case Common::MANY_TO_MANY:
563 $fromKeyName = array_keys($nestedReferenceAttributes[$reference]['join']['column']);
564 $fromKeyName = $fromKeyName[0];
565 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix . '.' : '';
566 $toKeyName = array_keys($nestedReferenceAttributes[$reference]['join']['inverseColumn']);
567 $toKeyName = $toKeyName[0];
568 $select[$prefix] = $fromKeyNamePrefix . $nestedReferenceAttributes[$reference]['join']['tableClassName']
569 . ':'
570 . $fromKeyName
571 . '.'
572 . $toKeyName;
573 $targetEntity = $nestedReferenceAttributes[$reference]['targetEntity'];
574 $nestedReferenceAttributes = $targetEntity::getMapReferenceAttributes();
575 break;
576 case Common::MANY_TO_ONE:
577 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix . '.' : '';
578 $select[$prefix] = $fromKeyNamePrefix.mb_strtoupper($reference);
579 $fromKeyNamePrefix .= mb_strtoupper($reference);
580 break;
581
582 }
583 }
584 else
585 {
586 throw new ArgumentException("Reference with name:" . $reference . ' not define in reference map');
587 }
588 }
589 }
590 return $select;
591 }
592
596 public function delete()
597 {
598 $ownerId = $this->getId();
599 $referenceAttributesMap = static::getMapReferenceAttributes();
600
601 foreach ($referenceAttributesMap as $referenceKey => $referenceAttributes)
602 {
603 if (!empty($referenceAttributes['options']['deleteSkip']))
604 {
605 continue;
606 }
607
608 if (!$this->{$referenceKey})
609 {
610 $this->loadAttribute($referenceKey);
611 }
612
613
614 if ($this->{$referenceKey})
615 {
616 switch ($referenceAttributes['type'])
617 {
618 case Common::ONE_TO_MANY:
619 $this->deleteOneToManyReferences($this->{$referenceKey});
620 break;
621 case Common::MANY_TO_MANY:
622 $this->deleteManyToManyReferences($this->{$referenceKey}, $referenceAttributes, $ownerId);
623 break;
624 case Common::MANY_TO_ONE:
625 $this->deleteManyToOneReference($this->{$referenceKey}, $referenceAttributes, $ownerId);
626 break;
627 case Common::ONE_TO_ONE:
628 //TODO
629 break;
630 }
631 }
632
633 }
634 $entityTableClass = static::getTableClassName();
635 $deleteEntity = $entityTableClass::delete($ownerId);
636 if ($deleteEntity->isSuccess())
637 {
638 return true;
639 }
640 else
641 {
642 $this->errors[] = $deleteEntity->getErrors();
643 return null;
644 }
645 }
646
650 private function deleteOneToManyReferences($referenceEntities)
651 {
652 foreach ($referenceEntities as $referenceEntity)
653 {
654 $referenceEntity->delete();
655 }
656 }
657
663 private function deleteManyToManyReferences($referenceEntities, $assoc, $ownerId)
664 {
665 $connectColumn = array_shift($assoc['join']['column']);
666 $connectInverseColumn = array_shift($assoc['join']['inverseColumn']);
667 foreach ($referenceEntities as $referenceEntity)
668 {
669 $connectPrimaryKey = array();
671 $connectTableClass = $assoc['join']['tableClassName'];
672 $connectPrimaryKey[$connectColumn[1]] = $ownerId;
673 $connectPrimaryKey[$connectInverseColumn[1]] = $referenceEntity->getId();;
674 $connectTableClass::delete($connectPrimaryKey);
675 $referenceEntity->delete();
676 }
677 }
678
685 private function deleteManyToOneReference(&$referenceEntity, $assoc, $ownerId)
686 {
687 if ($referenceEntity instanceof $assoc['targetEntity'])
688 {
689 unset($referenceEntity->{$assoc['inversedBy']}[$ownerId]);
690 }
691 }
692
696 public function getId()
697 {
698 return $this->id;
699 }
700
705 public function setId($id)
706 {
707 $this->id = $id;
708 }
709
713 public function getCreatedAt()
714 {
715 return $this->createdAt;
716 }
717
723 {
724 $this->createdAt = $createdAt;
725 }
726
730 public function getUpdatedAt()
731 {
732 return $this->updatedAt;
733 }
734
740 {
741 $this->updatedAt = $updatedAt;
742 }
743
748 public static function loadById($id)
749 {
750 $entity = static::load(array('ID' => $id));
751 return $entity;
752 }
753
758 public function loadAttribute($attributeName)
759 {
760 if (property_exists($this, $attributeName) && $this->{$attributeName} == null)
761 {
762 $entity = static::load(array('ID' => $this->getId()), array($attributeName));
763 $this->{$attributeName} = $entity->{$attributeName};
764 }
765 }
766
767
775 public function __call($name , array $arguments)
776 {
777 $isDeleteReferenceCall = preg_match_all('/^delete(\w+)/', $name, $deleteCallNameParts);
778 if ($isDeleteReferenceCall)
779 {
780 $referenceName = $deleteCallNameParts[1][0];
781 $referenceName = mb_strtolower($referenceName);
782 $referenceMapAttributes = $this::getMapReferenceAttributes();
783 if (!empty($referenceMapAttributes[$referenceName]))
784 {
786 $entities = !empty($arguments[0]) ? $arguments[0] : array();
787 if (!is_array($entities))
788 {
789 $entities = array(
790 $entities
791 );
792 }
793
794 foreach ($entities as $entity)
795 {
796 $this->deletedEntities[$referenceName][$entity->getId()] = $entity;
797 unset($this->{$referenceName}[$entity->getId()]);
798 }
799 }
800 }
801
802 $isAddReferenceCall = preg_match_all('/^add(\w+)/', $name, $addCallNameParts);
803 if ($isAddReferenceCall)
804 {
805 $referenceName = $addCallNameParts[1][0];
806 $referenceName = mb_strtolower($referenceName);
807 $referenceMapAttributes = $this::getMapReferenceAttributes();
808 if (!empty($referenceMapAttributes[$referenceName]))
809 {
811 $entities = !empty($arguments[0]) ? $arguments[0] : array();
812 if (!is_array($entities))
813 {
814 $entities = array(
815 $entities
816 );
817 }
818
819 foreach ($entities as $entity)
820 {
821 $this->{$referenceName}[] = $entity;
822 }
823 }
824 }
825
826 }
827
831 private function deleteReference($deletedReferenceEntities)
832 {
833 foreach ($deletedReferenceEntities as $referenceName => $referenceEntities)
834 {
835 $map = $this::getMapReferenceAttributes();
836 $map = $map[$referenceName];
837 switch ($map['type'])
838 {
839 case Common::ONE_TO_MANY:
840 foreach ($referenceEntities as $referenceEntity)
841 {
842 $referenceEntity->delete();
843 }
844 break;
845 case Common::MANY_TO_MANY:
846 $connectColumn = array_shift($map['join']['column']);
847 $connectInverseColumn = array_shift($map['join']['inverseColumn']);
848
849 foreach ($referenceEntities as $referenceEntity)
850 {
851 $connectPrimaryKey = array();
853 $connectTableClass = $map['join']['tableClassName'];
854 $connectPrimaryKey[$connectColumn[1]] = $this->getId();
855 $connectPrimaryKey[$connectInverseColumn[1]] = $referenceEntity->getId();
856 $connectTableClass::delete($connectPrimaryKey);
857 }
858 break;
859 case Common::ONE_TO_ONE:
860 //TODO
861 break;
862 case Common::MANY_TO_ONE:
863 //TODO
864 break;
865 }
866 }
867
868
869 }
870
874 public function getErrors()
875 {
876 return $this->errors;
877 }
878
882 public function getCurrentDbState()
883 {
884 return $this->currentDbState;
885 }
886
887
888 public static function factoryWithHorizontalCells($cellCount = 1)
889 {
890 $row = new DashboardRow();
891 $row->setGId(Util::generateUserUniqueId());
892 $map = [
893 'type' => 'cell-container',
894 'orientation' => 'horizontal',
895 'elements' => []
896 ];
897 for ($i = 0; $i < $cellCount; $i++)
898 {
899 $cellId = 'cell_' . randString(4);
900 $map['elements'][] = [
901 'type' => 'cell',
902 'id' => $cellId
903 ];
904 }
905 $row->setLayoutMap($map);
906
907 return $row;
908 }
909
910}
loadAttribute($attributeName)
Определения model.php:758
static getMapReferenceAttributes()
Определения model.php:92
static prepareGetListParameters(array $parameters)
Определения model.php:508
static getModelList(array $parameters)
Определения model.php:350
setUpdatedAt(DateTime $updatedAt)
Определения model.php:739
static factoryWithHorizontalCells($cellCount=1)
Определения model.php:888
setCreatedAt(DateTime $createdAt)
Определения model.php:722
static load($filter, array $with=array(), $order=array())
Определения model.php:334
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$entity
$errors
Определения iblock_catalog_edit.php:74
$select
Определения iblock_catalog_list.php:194
$filter
Определения iblock_catalog_list.php:54
randString($pass_len=10, $pass_chars=false)
Определения tools.php:2154
$name
Определения menu_edit.php:35
$map
Определения config.php:5
$value
Определения Param.php:39
$order
Определения payment.php:8
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936