24 private $deletedEntities =
array();
25 private $currentDbState =
array();
57 'CREATED_DATE' =>
'createdAt',
58 'UPDATED_DATE' =>
'updatedAt'
104 $referenceMapAttributes = static::getMapReferenceAttributes();
106 foreach ($referenceMapAttributes as $referenceAttributeName => $assoc)
108 if (!empty($this->{$referenceAttributeName}))
110 switch ($assoc[
'type'])
112 case Common::MANY_TO_ONE:
113 $this->saveManyToOneReference($this->{$referenceAttributeName}, $assoc);
115 case Common::ONE_TO_ONE:
122 $ormFields = $this->getConvertedMapAttributesToOrmFields();
123 if (!$ormFields[
'ID'])
125 unset($ormFields[
'ID']);
126 $addResult = $this->add($ormFields);
127 $ownerId = $addResult->getId();
128 $this->
setId($ownerId);
132 $ownerId = $ormFields[
'ID'];
133 $changedAttributes = $this->getChangedOrmAttributes($ormFields);
134 if ($changedAttributes)
136 $this->update(
array(
'ID' => $ownerId), $changedAttributes);
138 if (!empty($this->deletedEntities))
140 $this->deleteReference($this->deletedEntities);
147 foreach ($referenceMapAttributes as $referenceAttributeName => $assoc)
149 if (!empty($this->{$referenceAttributeName}))
151 switch ($assoc[
'type'])
153 case Common::ONE_TO_MANY:
154 $this->saveOneToManyReferences($this->{$referenceAttributeName}, $assoc, $ownerId);
156 case Common::MANY_TO_MANY:
157 $this->saveManyToManyReferences($this->{$referenceAttributeName}, $assoc, $ownerId);
171 private function saveOneToManyReferences($references, $assoc, $ownerEntityId)
173 foreach ($references as
$key => $reference)
175 if ($reference instanceof $assoc[
'targetEntity'])
177 $mapReferenceAttributes = $reference::getMapReferenceAttributes();
178 $reference->{$mapReferenceAttributes[$assoc[
'mappedBy']][
'join'][
'field'][0]} = $ownerEntityId;
190 private function saveManyToManyReferences($references, $assoc, $ownerEntityId)
192 foreach ($references as
$key => $reference)
194 if ($reference instanceof $assoc[
'targetEntity'])
196 $isReferenceNew = !(boolean)$reference->getId();
197 $referenceId = $reference->save();
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,
209 $ormTableClassName = $assoc[
'join'][
'tableClassName'];
210 $ormTableClassName::add($connectData);
220 private function saveManyToOneReference($reference, $assoc)
222 if ($reference instanceof $assoc[
'targetEntity'])
224 $reference = clone $reference;
225 $reference->{$assoc[
'inversedBy']} =
null;
227 $this->{$assoc[
'join'][
'field'][0]} = $reference->getId();
236 private function getConvertedMapAttributesToOrmFields()
239 $fieldsMap = static::getMapAttributes();
240 foreach ($fieldsMap as $ormFieldName => $objectProperty)
242 $result[$ormFieldName] = $this->{$objectProperty};
255 $tableClassName = static::getTableClassName();
256 $entity = $tableClassName::getEntity();
257 $primaryFields =
$entity->getPrimaryArray();
258 foreach ($primaryFields as $field)
260 if (array_key_exists($field,
$data) && empty(
$data[$field]))
262 unset(
$data[$field]);
266 $resultData = $tableClassName::add(
$data);
267 $this->currentDbState = $resultData->getData();
275 private function getChangedOrmAttributes($newEntityAttributes)
282 $oldEntityAttributes = $this->getCurrentDbState();
283 unset($oldEntityAttributes[
'CREATED_DATE']);
284 unset($oldEntityAttributes[
'UPDATED_DATE']);
285 unset($newEntityAttributes[
'CREATED_DATE']);
286 unset($newEntityAttributes[
'UPDATED_DATE']);
288 foreach ($oldEntityAttributes as
$key => $value)
290 if ($newEntityAttributes[
$key] != $value)
304 private function update($primary,
array $data)
306 $tableClassName = static::getTableClassName();
307 $data[
'UPDATED_DATE'] =
new DateTime();
309 $resultData = $tableClassName::update($primary,
$data);
311 foreach ($resultData->getData() as
$key => $value)
324 return get_called_class();
336 $models = static::getModelList(
array(
337 'select' =>
array(
'*'),
342 return array_shift($models);
352 $modelList =
array();
353 $query = static::getList($parameters);
354 while ($row =
$query->fetch())
356 if (!($modelList[$row[
'ID']] ??
false))
358 $model = static::buildFromArray($row);
362 $model = static::buildFromArray($row, $modelList[$row[
'ID']]);
366 $modelList[$model->id] = $model;
378 protected static function getList(
array $parameters)
381 $tableClass = static::getTableClassName();
382 return $tableClass::getList(static::prepareGetListParameters($parameters));
392 protected static function buildFromArray(
array $attributes, $parentEntity =
null)
396 return $model->setAttributes($attributes, $parentEntity);
406 private function setAttributes(
array $attributes, $parentEntity)
408 foreach ($attributes as
$key => $value)
412 unset($attributes[
$key]);
417 $mapAttributes = static::getMapAttributes();
418 foreach ($attributes as
$key => $value)
420 if (!empty($mapAttributes[
$key]))
424 unset($attributes[
$key]);
427 $parentEntity = $this;
430 if (empty($attributes))
432 return $parentEntity;
435 $subEntitiesMapAttributes = static::getMapReferenceAttributes();
436 $subEntitiesKeys = array_keys($subEntitiesMapAttributes);
439 $subEntityAttributes =
array();
440 $loadedSubEntitiesKeys =
array();
441 foreach ($attributes as
$key => $value)
443 $delimiter = self::ATTRIBUTE_SLICE_DELIMITER;
444 $selectedAttributeParts = explode($delimiter,
$key);
445 if (
count($selectedAttributeParts) == 2 && in_array($selectedAttributeParts[0], $subEntitiesKeys))
447 $loadedSubEntitiesKeys[$selectedAttributeParts[0]] = $selectedAttributeParts[0];
448 $subEntityAttributes[$selectedAttributeParts[0]][$selectedAttributeParts[1]] =
$value;
452 $nestedEntityParentKey = array_shift($selectedAttributeParts);
453 $nestedElementKey = implode(self::ATTRIBUTE_SLICE_DELIMITER, $selectedAttributeParts);
454 $subEntityAttributes[$nestedEntityParentKey][$nestedElementKey] =
$value;
458 foreach ($subEntityAttributes as
$key => $validAttributes)
460 if (!empty($subEntitiesMapAttributes[
$key]))
463 $targetEntityClass = $subEntitiesMapAttributes[
$key][
'targetEntity'];
464 if ($subEntitiesMapAttributes[
$key][
'type'] != Common::MANY_TO_ONE)
466 if (!isset($parentEntity->{
$key}[$validAttributes[
'ID']]))
468 $subEntity = $targetEntityClass::buildFromArray($validAttributes);
470 $nestedEntityReferenceMap = $subEntity::getMapReferenceAttributes();
476 if ($subEntitiesMapAttributes[
$key][
'type'] == Common::ONE_TO_MANY)
478 if (!empty($nestedEntityReferenceMap[$subEntitiesMapAttributes[
$key][
'mappedBy']]))
480 $subEntity->{$subEntitiesMapAttributes[
$key][
'mappedBy']} = $parentEntity;
483 $parentEntity->{
$key}[$subEntity->id] = $subEntity;
487 $targetEntityClass::buildFromArray($validAttributes, $parentEntity->{
$key}[$validAttributes[
'ID']]);
492 $subEntity = $targetEntityClass::buildFromArray($validAttributes);
493 $parentEntity->{
$key} = $subEntity;
500 return $parentEntity;
510 if (!empty($parameters[
'with']))
512 if (!is_array($parameters[
'with']))
516 if (!isset($parameters[
'select']))
518 $parameters[
'select'] =
array(
'*');
520 elseif (!in_array(
'*', $parameters[
'select']) && !in_array(
'ID', $parameters[
'select']))
522 $parameters[
'select'][] =
'ID';
524 $parameters[
'select'] = array_merge($parameters[
'select'], static::buildOrmSelectForReference($parameters[
'with']));
527 unset($parameters[
'with']);
536 protected static function buildOrmSelectForReference(
array $with)
539 $referenceAttributes = static::getMapReferenceAttributes();
540 foreach ($with as $referenceKey)
542 $testNesting = explode(
'.', $referenceKey);
543 $nestedReferenceAttributes = $referenceAttributes;
545 $fromKeyNamePrefix =
'';
546 foreach ($testNesting as $reference)
548 if (!empty($nestedReferenceAttributes[$reference]))
550 $prefix = $prefix . $reference . self::ATTRIBUTE_SLICE_DELIMITER;
551 switch ($nestedReferenceAttributes[$reference][
'type'])
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();
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']
573 $targetEntity = $nestedReferenceAttributes[$reference][
'targetEntity'];
574 $nestedReferenceAttributes = $targetEntity::getMapReferenceAttributes();
576 case Common::MANY_TO_ONE:
577 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix .
'.' :
'';
578 $select[$prefix] = $fromKeyNamePrefix.mb_strtoupper($reference);
579 $fromKeyNamePrefix .= mb_strtoupper($reference);
586 throw new ArgumentException(
"Reference with name:" . $reference .
' not define in reference map');
596 public function delete()
598 $ownerId = $this->
getId();
599 $referenceAttributesMap = static::getMapReferenceAttributes();
601 foreach ($referenceAttributesMap as $referenceKey => $referenceAttributes)
603 if (!empty($referenceAttributes[
'options'][
'deleteSkip']))
608 if (!$this->{$referenceKey})
614 if ($this->{$referenceKey})
616 switch ($referenceAttributes[
'type'])
618 case Common::ONE_TO_MANY:
619 $this->deleteOneToManyReferences($this->{$referenceKey});
621 case Common::MANY_TO_MANY:
622 $this->deleteManyToManyReferences($this->{$referenceKey}, $referenceAttributes, $ownerId);
624 case Common::MANY_TO_ONE:
625 $this->deleteManyToOneReference($this->{$referenceKey}, $referenceAttributes, $ownerId);
627 case Common::ONE_TO_ONE:
634 $entityTableClass = static::getTableClassName();
635 $deleteEntity = $entityTableClass::delete($ownerId);
636 if ($deleteEntity->isSuccess())
642 $this->errors[] = $deleteEntity->getErrors();
650 private function deleteOneToManyReferences($referenceEntities)
652 foreach ($referenceEntities as $referenceEntity)
654 $referenceEntity->delete();
663 private function deleteManyToManyReferences($referenceEntities, $assoc, $ownerId)
665 $connectColumn = array_shift($assoc[
'join'][
'column']);
666 $connectInverseColumn = array_shift($assoc[
'join'][
'inverseColumn']);
667 foreach ($referenceEntities as $referenceEntity)
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();
685 private function deleteManyToOneReference(&$referenceEntity, $assoc, $ownerId)
687 if ($referenceEntity instanceof $assoc[
'targetEntity'])
689 unset($referenceEntity->{$assoc[
'inversedBy']}[$ownerId]);
715 return $this->createdAt;
732 return $this->updatedAt;
760 if (property_exists($this, $attributeName) && $this->{$attributeName} ==
null)
763 $this->{$attributeName} =
$entity->{$attributeName};
775 public function __call(
$name ,
array $arguments)
777 $isDeleteReferenceCall = preg_match_all(
'/^delete(\w+)/',
$name, $deleteCallNameParts);
778 if ($isDeleteReferenceCall)
780 $referenceName = $deleteCallNameParts[1][0];
781 $referenceName = mb_strtolower($referenceName);
782 $referenceMapAttributes = $this::getMapReferenceAttributes();
783 if (!empty($referenceMapAttributes[$referenceName]))
786 $entities = !empty($arguments[0]) ? $arguments[0] :
array();
787 if (!is_array($entities))
796 $this->deletedEntities[$referenceName][
$entity->getId()] =
$entity;
797 unset($this->{$referenceName}[
$entity->getId()]);
802 $isAddReferenceCall = preg_match_all(
'/^add(\w+)/',
$name, $addCallNameParts);
803 if ($isAddReferenceCall)
805 $referenceName = $addCallNameParts[1][0];
806 $referenceName = mb_strtolower($referenceName);
807 $referenceMapAttributes = $this::getMapReferenceAttributes();
808 if (!empty($referenceMapAttributes[$referenceName]))
811 $entities = !empty($arguments[0]) ? $arguments[0] :
array();
812 if (!is_array($entities))
821 $this->{$referenceName}[] =
$entity;
831 private function deleteReference($deletedReferenceEntities)
833 foreach ($deletedReferenceEntities as $referenceName => $referenceEntities)
835 $map = $this::getMapReferenceAttributes();
837 switch (
$map[
'type'])
839 case Common::ONE_TO_MANY:
840 foreach ($referenceEntities as $referenceEntity)
842 $referenceEntity->delete();
845 case Common::MANY_TO_MANY:
846 $connectColumn = array_shift(
$map[
'join'][
'column']);
847 $connectInverseColumn = array_shift(
$map[
'join'][
'inverseColumn']);
849 foreach ($referenceEntities as $referenceEntity)
851 $connectPrimaryKey =
array();
853 $connectTableClass =
$map[
'join'][
'tableClassName'];
854 $connectPrimaryKey[$connectColumn[1]] = $this->
getId();
855 $connectPrimaryKey[$connectInverseColumn[1]] = $referenceEntity->getId();
856 $connectTableClass::delete($connectPrimaryKey);
859 case Common::ONE_TO_ONE:
862 case Common::MANY_TO_ONE:
884 return $this->currentDbState;
891 $row->setGId(Util::generateUserUniqueId());
893 'type' =>
'cell-container',
894 'orientation' =>
'horizontal',
897 for (
$i = 0;
$i < $cellCount;
$i++)
900 $map[
'elements'][] = [
905 $row->setLayoutMap(
$map);