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 $addResult = $this->add($ormFields);
126 $ownerId = $addResult->getId();
127 $this->
setId($ownerId);
131 $ownerId = $ormFields[
'ID'];
132 $changedAttributes = $this->getChangedOrmAttributes($ormFields);
133 if ($changedAttributes)
135 $this->update(array(
'ID' => $ownerId), $changedAttributes);
137 if (!empty($this->deletedEntities))
139 $this->deleteReference($this->deletedEntities);
146 foreach ($referenceMapAttributes as $referenceAttributeName => $assoc)
148 if (!empty($this->{$referenceAttributeName}))
150 switch ($assoc[
'type'])
152 case Common::ONE_TO_MANY:
153 $this->saveOneToManyReferences($this->{$referenceAttributeName}, $assoc, $ownerId);
155 case Common::MANY_TO_MANY:
156 $this->saveManyToManyReferences($this->{$referenceAttributeName}, $assoc, $ownerId);
170 private function saveOneToManyReferences($references, $assoc, $ownerEntityId)
172 foreach ($references as $key => $reference)
174 if ($reference instanceof $assoc[
'targetEntity'])
176 $mapReferenceAttributes = $reference::getMapReferenceAttributes();
177 $reference->{$mapReferenceAttributes[$assoc[
'mappedBy']][
'join'][
'field'][0]} = $ownerEntityId;
189 private function saveManyToManyReferences($references, $assoc, $ownerEntityId)
191 foreach ($references as $key => $reference)
193 if ($reference instanceof $assoc[
'targetEntity'])
195 $isReferenceNew = !(boolean)$reference->getId();
196 $referenceId = $reference->save();
199 $column = array_values($assoc[
'join'][
'column']);
200 $column = $column[0];
201 $inverseColumn = array_values($assoc[
'join'][
'inverseColumn']);
202 $inverseColumn = $inverseColumn[0];
203 $connectData = array(
204 $column[1] => $ownerEntityId,
205 $inverseColumn[1] => $referenceId,
208 $ormTableClassName = $assoc[
'join'][
'tableClassName'];
209 $ormTableClassName::add($connectData);
219 private function saveManyToOneReference($reference, $assoc)
221 if ($reference instanceof $assoc[
'targetEntity'])
223 $reference = clone $reference;
224 $reference->{$assoc[
'inversedBy']} =
null;
226 $this->{$assoc[
'join'][
'field'][0]} = $reference->getId();
235 private function getConvertedMapAttributesToOrmFields()
238 $fieldsMap = static::getMapAttributes();
239 foreach ($fieldsMap as $ormFieldName => $objectProperty)
241 $result[$ormFieldName] = $this->{$objectProperty};
251 private function add(array $data)
253 $tableClassName = static::getTableClassName();
254 $resultData = $tableClassName::add($data);
255 $this->currentDbState = $resultData->getData();
263 private function getChangedOrmAttributes($newEntityAttributes)
270 $oldEntityAttributes = $this->getCurrentDbState();
271 unset($oldEntityAttributes[
'CREATED_DATE']);
272 unset($oldEntityAttributes[
'UPDATED_DATE']);
273 unset($newEntityAttributes[
'CREATED_DATE']);
274 unset($newEntityAttributes[
'UPDATED_DATE']);
276 foreach ($oldEntityAttributes as $key => $value)
278 if ($newEntityAttributes[$key] != $value)
280 $result[$key] = $newEntityAttributes[$key];
292 private function update($primary, array $data)
294 $tableClassName = static::getTableClassName();
295 $data[
'UPDATED_DATE'] =
new DateTime();
297 $resultData = $tableClassName::update($primary, $data);
299 foreach ($resultData->getData() as $key => $value)
301 $this->currentDbState[$key] = $value;
312 return get_called_class();
322 public static function load($filter, array $with = array(), $order = array())
324 $models = static::getModelList(array(
325 'select' => array(
'*'),
330 return array_shift($models);
340 $modelList = array();
341 $query = static::getList($parameters);
342 while ($row = $query->fetch())
344 if (!$modelList[$row[
'ID']])
346 $model = static::buildFromArray($row);
350 $model = static::buildFromArray($row, $modelList[$row[
'ID']]);
354 $modelList[$model->id] = $model;
366 protected static function getList(array $parameters)
369 $tableClass = static::getTableClassName();
370 return $tableClass::getList(static::prepareGetListParameters($parameters));
380 protected static function buildFromArray(array $attributes, $parentEntity =
null)
384 return $model->setAttributes($attributes, $parentEntity);
394 private function setAttributes(array $attributes, $parentEntity)
396 foreach ($attributes as $key => $value)
400 unset($attributes[$key]);
405 $mapAttributes = static::getMapAttributes();
406 foreach ($attributes as $key => $value)
408 if (!empty($mapAttributes[$key]))
410 $this->{$mapAttributes[$key]} = $value;
411 $this->currentDbState[$key] = $value;
412 unset($attributes[$key]);
415 $parentEntity = $this;
418 if (empty($attributes))
420 return $parentEntity;
423 $subEntitiesMapAttributes = static::getMapReferenceAttributes();
424 $subEntitiesKeys = array_keys($subEntitiesMapAttributes);
427 $subEntityAttributes = array();
428 $loadedSubEntitiesKeys = array();
429 foreach ($attributes as $key => $value)
431 $delimiter = self::ATTRIBUTE_SLICE_DELIMITER;
432 $selectedAttributeParts = explode($delimiter, $key);
433 if (count($selectedAttributeParts) == 2 && in_array($selectedAttributeParts[0], $subEntitiesKeys))
435 $loadedSubEntitiesKeys[$selectedAttributeParts[0]] = $selectedAttributeParts[0];
436 $subEntityAttributes[$selectedAttributeParts[0]][$selectedAttributeParts[1]] = $value;
438 elseif (count($selectedAttributeParts) >= 2)
440 $nestedEntityParentKey = array_shift($selectedAttributeParts);
441 $nestedElementKey = implode(self::ATTRIBUTE_SLICE_DELIMITER, $selectedAttributeParts);
442 $subEntityAttributes[$nestedEntityParentKey][$nestedElementKey] = $value;
446 foreach ($subEntityAttributes as $key => $validAttributes)
448 if (!empty($subEntitiesMapAttributes[$key]))
451 $targetEntityClass = $subEntitiesMapAttributes[$key][
'targetEntity'];
452 if ($subEntitiesMapAttributes[$key][
'type'] != Common::MANY_TO_ONE)
454 if (!isset($parentEntity->{$key}[$validAttributes[
'ID']]))
456 $subEntity = $targetEntityClass::buildFromArray($validAttributes);
458 $nestedEntityReferenceMap = $subEntity::getMapReferenceAttributes();
464 if ($subEntitiesMapAttributes[$key][
'type'] == Common::ONE_TO_MANY)
466 if (!empty($nestedEntityReferenceMap[$subEntitiesMapAttributes[$key][
'mappedBy']]))
468 $subEntity->{$subEntitiesMapAttributes[$key][
'mappedBy']} = $parentEntity;
471 $parentEntity->{$key}[$subEntity->id] = $subEntity;
475 $targetEntityClass::buildFromArray($validAttributes, $parentEntity->{$key}[$validAttributes[
'ID']]);
480 $subEntity = $targetEntityClass::buildFromArray($validAttributes);
481 $parentEntity->{$key} = $subEntity;
488 return $parentEntity;
498 if (!empty($parameters[
'with']))
500 if (!is_array($parameters[
'with']))
504 if (!isset($parameters[
'select']))
506 $parameters[
'select'] = array(
'*');
508 elseif (!in_array(
'*', $parameters[
'select']) && !in_array(
'ID', $parameters[
'select']))
510 $parameters[
'select'][] =
'ID';
512 $parameters[
'select'] = array_merge($parameters[
'select'], static::buildOrmSelectForReference($parameters[
'with']));
515 unset($parameters[
'with']);
524 protected static function buildOrmSelectForReference(array $with)
527 $referenceAttributes = static::getMapReferenceAttributes();
528 foreach ($with as $referenceKey)
530 $testNesting = explode(
'.', $referenceKey);
531 $nestedReferenceAttributes = $referenceAttributes;
533 $fromKeyNamePrefix =
'';
534 foreach ($testNesting as $reference)
536 if (!empty($nestedReferenceAttributes[$reference]))
538 $prefix = $prefix . $reference . self::ATTRIBUTE_SLICE_DELIMITER;
539 switch ($nestedReferenceAttributes[$reference][
'type'])
541 case Common::ONE_TO_MANY:
543 $targetEntity = $nestedReferenceAttributes[$reference][
'targetEntity'];
544 $targetOrmTable = $targetEntity::getTableClassName();
545 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix .
'.' :
'';
546 $select[$prefix] = $fromKeyNamePrefix.$targetOrmTable::getClassName().
':'.mb_strtoupper($nestedReferenceAttributes[$reference][
'mappedBy']);
547 $fromKeyNamePrefix .= $targetOrmTable::getClassName().
':'.mb_strtoupper($nestedReferenceAttributes[$reference][
'mappedBy']);
548 $nestedReferenceAttributes = $targetEntity::getMapReferenceAttributes();
550 case Common::MANY_TO_MANY:
551 $fromKeyName = array_keys($nestedReferenceAttributes[$reference][
'join'][
'column']);
552 $fromKeyName = $fromKeyName[0];
553 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix .
'.' :
'';
554 $toKeyName = array_keys($nestedReferenceAttributes[$reference][
'join'][
'inverseColumn']);
555 $toKeyName = $toKeyName[0];
556 $select[$prefix] = $fromKeyNamePrefix . $nestedReferenceAttributes[$reference][
'join'][
'tableClassName']
561 $targetEntity = $nestedReferenceAttributes[$reference][
'targetEntity'];
562 $nestedReferenceAttributes = $targetEntity::getMapReferenceAttributes();
564 case Common::MANY_TO_ONE:
565 $fromKeyNamePrefix = !empty($fromKeyNamePrefix) ? $fromKeyNamePrefix .
'.' :
'';
566 $select[$prefix] = $fromKeyNamePrefix.mb_strtoupper($reference);
567 $fromKeyNamePrefix .= mb_strtoupper($reference);
574 throw new ArgumentException(
"Reference with name:" . $reference .
' not define in reference map');
584 public function delete()
586 $ownerId = $this->getId();
587 $referenceAttributesMap = static::getMapReferenceAttributes();
589 foreach ($referenceAttributesMap as $referenceKey => $referenceAttributes)
591 if (!empty($referenceAttributes[
'options'][
'deleteSkip']))
596 if (!$this->{$referenceKey})
598 $this->loadAttribute($referenceKey);
602 if ($this->{$referenceKey})
604 switch ($referenceAttributes[
'type'])
606 case Common::ONE_TO_MANY:
607 $this->deleteOneToManyReferences($this->{$referenceKey});
609 case Common::MANY_TO_MANY:
610 $this->deleteManyToManyReferences($this->{$referenceKey}, $referenceAttributes, $ownerId);
612 case Common::MANY_TO_ONE:
613 $this->deleteManyToOneReference($this->{$referenceKey}, $referenceAttributes, $ownerId);
615 case Common::ONE_TO_ONE:
622 $entityTableClass = static::getTableClassName();
623 $deleteEntity = $entityTableClass::delete($ownerId);
624 if ($deleteEntity->isSuccess())
630 $this->errors[] = $deleteEntity->getErrors();
638 private function deleteOneToManyReferences($referenceEntities)
640 foreach ($referenceEntities as $referenceEntity)
642 $referenceEntity->delete();
651 private function deleteManyToManyReferences($referenceEntities, $assoc, $ownerId)
653 $connectColumn = array_shift($assoc[
'join'][
'column']);
654 $connectInverseColumn = array_shift($assoc[
'join'][
'inverseColumn']);
655 foreach ($referenceEntities as $referenceEntity)
657 $connectPrimaryKey = array();
659 $connectTableClass = $assoc[
'join'][
'tableClassName'];
660 $connectPrimaryKey[$connectColumn[1]] = $ownerId;
661 $connectPrimaryKey[$connectInverseColumn[1]] = $referenceEntity->getId();;
662 $connectTableClass::delete($connectPrimaryKey);
663 $referenceEntity->delete();
673 private function deleteManyToOneReference(&$referenceEntity, $assoc, $ownerId)
675 if ($referenceEntity instanceof $assoc[
'targetEntity'])
677 unset($referenceEntity->{$assoc[
'inversedBy']}[$ownerId]);
703 return $this->createdAt;
712 $this->createdAt = $createdAt;
720 return $this->updatedAt;
729 $this->updatedAt = $updatedAt;
738 $entity = static::load(array(
'ID' => $id));
748 if (property_exists($this, $attributeName) && $this->{$attributeName} ==
null)
750 $entity = static::load(array(
'ID' => $this->getId()), array($attributeName));
751 $this->{$attributeName} = $entity->{$attributeName};
763 public function __call($name , array $arguments)
765 $isDeleteReferenceCall = preg_match_all(
'/^delete(\w+)/', $name, $deleteCallNameParts);
766 if ($isDeleteReferenceCall)
768 $referenceName = $deleteCallNameParts[1][0];
769 $referenceName = mb_strtolower($referenceName);
770 $referenceMapAttributes = $this::getMapReferenceAttributes();
771 if (!empty($referenceMapAttributes[$referenceName]))
774 $entities = !empty($arguments[0]) ? $arguments[0] : array();
775 if (!is_array($entities))
782 foreach ($entities as $entity)
784 $this->deletedEntities[$referenceName][$entity->getId()] = $entity;
785 unset($this->{$referenceName}[$entity->getId()]);
790 $isAddReferenceCall = preg_match_all(
'/^add(\w+)/', $name, $addCallNameParts);
791 if ($isAddReferenceCall)
793 $referenceName = $addCallNameParts[1][0];
794 $referenceName = mb_strtolower($referenceName);
795 $referenceMapAttributes = $this::getMapReferenceAttributes();
796 if (!empty($referenceMapAttributes[$referenceName]))
799 $entities = !empty($arguments[0]) ? $arguments[0] : array();
800 if (!is_array($entities))
807 foreach ($entities as $entity)
809 $this->{$referenceName}[] = $entity;
819 private function deleteReference($deletedReferenceEntities)
821 foreach ($deletedReferenceEntities as $referenceName => $referenceEntities)
823 $map = $this::getMapReferenceAttributes();
824 $map = $map[$referenceName];
825 switch ($map[
'type'])
827 case Common::ONE_TO_MANY:
828 foreach ($referenceEntities as $referenceEntity)
830 $referenceEntity->delete();
833 case Common::MANY_TO_MANY:
834 $connectColumn = array_shift($map[
'join'][
'column']);
835 $connectInverseColumn = array_shift($map[
'join'][
'inverseColumn']);
837 foreach ($referenceEntities as $referenceEntity)
839 $connectPrimaryKey = array();
841 $connectTableClass = $map[
'join'][
'tableClassName'];
842 $connectPrimaryKey[$connectColumn[1]] = $this->getId();
843 $connectPrimaryKey[$connectInverseColumn[1]] = $referenceEntity->getId();
844 $connectTableClass::delete($connectPrimaryKey);
847 case Common::ONE_TO_ONE:
850 case Common::MANY_TO_ONE:
864 return $this->errors;
872 return $this->currentDbState;
879 $row->setGId(Util::generateUserUniqueId());
881 'type' =>
'cell-container',
882 'orientation' =>
'horizontal',
885 for ($i = 0; $i < $cellCount; $i++)
887 $cellId =
'cell_' . randString(4);
888 $map[
'elements'][] = [
893 $row->setLayoutMap($map);