예제 #1
0
 protected static function visitEntity(IEntity $entity, IModel $model, $withCascade = true)
 {
     $entityHash = spl_object_hash($entity);
     if (isset(self::$outputQueue[$entityHash])) {
         if (self::$outputQueue[$entityHash] === true) {
             $cycle = [];
             $bt = debug_backtrace();
             foreach ($bt as $item) {
                 if ($item['function'] === 'getCascadeQueue') {
                     break;
                 } elseif ($item['function'] === 'addRelationshipToQueue') {
                     $cycle[] = get_class($item['args'][0]) . '::$' . $item['args'][1]->name;
                 }
             }
             throw new InvalidStateException('Persist cycle detected in ' . implode(' - ', $cycle) . '. Use manual two phase persist.');
         }
         return;
     }
     $repository = $model->getRepositoryForEntity($entity);
     $repository->attach($entity);
     $repository->doFireEvent($entity, 'onBeforePersist');
     if ($withCascade) {
         self::$outputQueue[$entityHash] = true;
         foreach ($entity->getMetadata()->getProperties() as $propertyMeta) {
             if ($propertyMeta->relationship !== null && $propertyMeta->relationship->cascade['persist']) {
                 self::addRelationshipToQueue($entity, $propertyMeta, $model);
             }
         }
         unset(self::$outputQueue[$entityHash]);
         // reenqueue
     }
     self::$outputQueue[$entityHash] = $entity;
 }
예제 #2
0
 public static function getCascadeQueue($entity, IModel $model, &$queue = [])
 {
     $entityHash = spl_object_hash($entity);
     if (isset($queue[$entityHash])) {
         return;
     }
     $repository = $model->getRepositoryForEntity($entity);
     $repository->attach($entity);
     $repository->doFireEvent($entity, 'onBeforePersist');
     list($pre, $post) = static::getLoadedRelationships($entity);
     foreach ($pre as $value) {
         if ($value instanceof IEntity) {
             static::getCascadeQueue($value, $model, $queue);
         } elseif ($value instanceof IRelationshipCollection) {
             foreach ($value->getEntitiesForPersistance() as $subValue) {
                 static::getCascadeQueue($subValue, $model, $queue);
             }
             $queue[spl_object_hash($value)] = $value;
         }
     }
     $queue[$entityHash] = $entity;
     foreach ($post as $value) {
         if ($value instanceof IEntity) {
             static::getCascadeQueue($value, $model, $queue);
         } elseif ($value instanceof IRelationshipCollection) {
             foreach ($value->getEntitiesForPersistance() as $subValue) {
                 static::getCascadeQueue($subValue, $model, $queue);
             }
             $queue[spl_object_hash($value)] = $value;
         }
     }
 }
예제 #3
0
 protected function random(PropertyMetadata $property)
 {
     if (in_array($property->relationshipType, [PropertyMetadata::RELATIONSHIP_MANY_HAS_ONE, PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE, PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED])) {
         $entityClass = $this->model->getRepository($property->relationshipRepository)->getEntityClassNames()[0];
         return $this->create($entityClass);
     }
     $possibilities = [];
     if ($property->enum) {
         $possibilities = $property->enum;
     } else {
         foreach (array_keys($property->types) as $type) {
             switch ($type) {
                 case 'datetime':
                     $possibilities[] = new DateTime($this->randomInt(2010, 2020) . '-' . $this->randomInt(1, 12) . '-' . $this->randomInt(1, 31));
                     break;
                 case 'string':
                     $possibilities[] = $this->randomWords(20, 50);
                     break;
                 case 'int':
                     $possibilities[] = $this->randomInt(0, 100);
                     break;
                 case 'float':
                     $possibilities[] = $this->randomInt(0, 100) + $this->randomInt(0, 100) / 100;
                     break;
                 case 'bool':
                     $possibilities[] = (bool) $this->randomInt(0, 1);
                     break;
             }
         }
     }
     if (!$possibilities) {
         return NULL;
     }
     return $possibilities[array_rand($possibilities)];
 }
예제 #4
0
파일: Form.php 프로젝트: ytnuk/orm
 protected function createComponent($name)
 {
     if ($name instanceof Nextras\Orm\Entity\IEntity) {
         $class = rtrim($name->getMetadata()->getClassName(), 'a..zA..Z') . 'Form\\Container';
         return new $class($name, $this->model->getRepositoryForEntity($name));
     }
     return parent::createComponent($name);
 }
 public function create($entity, array $params = [])
 {
     $entity = new $entity();
     $repository = $this->model->getRepositoryForEntity($entity);
     $repository->attach($entity);
     $this->fill($entity, $params);
     return $entity;
 }
예제 #6
0
 public function persist(IEntity $entity, $recursive = TRUE)
 {
     $this->identityMap->check($entity);
     if (isset($this->isPersisting[spl_object_hash($entity)])) {
         return $entity;
     }
     $this->isPersisting[spl_object_hash($entity)] = TRUE;
     $this->attach($entity);
     $relationships = [];
     if ($recursive) {
         foreach ($entity->toArray(IEntity::TO_ARRAY_LOADED_RELATIONSHIP_AS_IS) as $k => $v) {
             if ($v instanceof IEntity) {
                 $this->model->getRepositoryForEntity($v)->persist($v);
             } elseif ($v instanceof IRelationshipCollection) {
                 $relationships[] = $v;
             }
         }
     }
     if ($entity->isModified()) {
         $id = $this->mapper->persist($entity);
         $entity->fireEvent('onPersist', [$id]);
     }
     foreach ($relationships as $relationship) {
         $relationship->persist($recursive);
     }
     unset($this->isPersisting[spl_object_hash($entity)]);
     return $entity;
 }
예제 #7
0
 private function parseCondition(array $levels, IMapper $mapper)
 {
     /** @var IDbStorageReflection $reflection */
     $reflection = $mapper->getStorageReflection();
     $expression = '';
     $column = array_pop($levels);
     $entityMD = $this->metadataStorage->get($mapper->getRepository()->getEntityClassNames()[0]);
     foreach ($levels as $level) {
         if (!$entityMD->hasProperty($level)) {
             throw new InvalidArgumentException("Undefined property {$entityMD->className}::\${$level}.");
         }
         $propertyMD = $entityMD->getProperty($level);
         if (!$propertyMD->relationshipRepository) {
             throw new InvalidArgumentException("Entity {$entityMD->className}::\${$level} does not contain a relationship.");
         }
         $targetMapper = $this->model->getRepository($propertyMD->relationshipRepository)->getMapper();
         $targetReflection = $targetMapper->getStorageReflection();
         if ($propertyMD->relationshipType === PropertyMetadata::RELATIONSHIP_ONE_HAS_MANY) {
             $table = $targetReflection->getStorageName();
             $joinColumn = $targetReflection->convertEntityToStorageKey($propertyMD->relationshipProperty);
             $expression .= ":{$table}({$joinColumn})";
         } elseif ($propertyMD->relationshipType === PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY) {
             if ($propertyMD->relationshipIsMain) {
                 $expression .= ':' . $reflection->getManyHasManyStorageName($targetMapper);
                 $expression .= '.' . $reflection->getManyHasManyStoragePrimaryKeys($targetMapper)[1];
             } else {
                 $expression .= ':' . $targetReflection->getManyHasManyStorageName($mapper);
                 $expression .= '.' . $targetReflection->getManyHasManyStoragePrimaryKeys($mapper)[0];
             }
         } else {
             $expression .= '.' . $reflection->convertEntityToStorageKey($level);
         }
         $mapper = $targetMapper;
         $reflection = $targetReflection;
         $entityMD = $this->metadataStorage->get($mapper->getRepository()->getEntityClassNames()[0]);
     }
     // check if property exists
     $entityMD->getProperty($column);
     $column = $reflection->convertEntityToStorageKey($column);
     return "{$expression}.{$column}";
 }
예제 #8
0
 protected function createComponentTranslates(Nextras\Orm\Entity\Reflection\PropertyMetadata $metadata) : Nette\Forms\Container
 {
     $translates = $this->addContainer($metadata->name);
     $localeRepository = $this->model->getRepositoryForEntity(Ytnuk\Translation\Locale\Entity::class);
     self::$locales ?: (self::$locales = $localeRepository->findAll()->fetchPairs(current($localeRepository->getEntityMetadata()->getPrimaryKey())));
     $collection = array_combine(array_map(function (Ytnuk\Translation\Translate\Entity $entity) {
         return $entity->getRawValue('locale');
     }, $collection = iterator_to_array($this->entity->getValue($metadata->name))), $collection);
     array_walk(self::$locales, function (Ytnuk\Translation\Locale\Entity $locale) use($translates, $collection) {
         $translate = $collection[$locale->id] ?? new Ytnuk\Translation\Translate\Entity();
         $translates->addComponent($component = $this->form->createComponent($translate), $locale->id);
         if ($component instanceof Nette\Forms\Container) {
             $component->setCurrentGroup($translates->getCurrentGroup());
             $value = $component['value'];
             if ($value instanceof Nette\Forms\Controls\BaseControl) {
                 $value->caption = NULL;
                 $value->setRequired(FALSE);
             }
             unset($component['locale']);
             $component->addHidden('locale', $locale->id)->setOption('entity', $locale);
         }
     });
     $parent = $this->lookup(parent::class, FALSE);
     if ($parent instanceof parent) {
         $translates->getCurrentGroup()->setOption('label', $parent->formatPropertyLabel($parent->getMetadata()->getProperty($this->getName())));
         if (!$parent->getMetadata()->getProperty($this->name)->isNullable && ($containers = iterator_to_array($translates->getComponents(FALSE, Nette\Forms\Container::class)))) {
             foreach ($containers as $key => $container) {
                 $value = $container['value'] ?? NULL;
                 if ($value instanceof Nette\Forms\Controls\BaseControl) {
                     foreach (array_diff_key($containers, array_flip([$key])) as $sibling) {
                         $value = $value->addConditionOn($sibling['value'], ~Nette\Forms\Form::FILLED);
                     }
                     $value->setRequired();
                 }
             }
         }
     }
     return $translates;
 }
예제 #9
0
 /**
  * @param EntityMetadata[]  $metadata
  * @param IModel            $model
  */
 public function validate(array $metadata, IModel $model)
 {
     $pairs = [PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY => PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY, PropertyMetadata::RELATIONSHIP_MANY_HAS_ONE => PropertyMetadata::RELATIONSHIP_ONE_HAS_MANY, PropertyMetadata::RELATIONSHIP_ONE_HAS_MANY => PropertyMetadata::RELATIONSHIP_MANY_HAS_ONE, PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE => PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE, PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED => PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED];
     foreach ($metadata as $entityMeta) {
         foreach ($entityMeta->getProperties() as $propertyMeta) {
             if (!$propertyMeta->relationshipType) {
                 continue;
             }
             $repositoryName = $propertyMeta->relationshipRepository;
             if (!$model->hasRepository($repositoryName)) {
                 throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} points to unknown '{$propertyMeta->relationshipRepository}' repository.");
             }
             $symetricEntityMeta = $metadata[$repositoryName::getEntityClassNames()[0]];
             if (!$symetricEntityMeta->hasProperty($propertyMeta->relationshipProperty)) {
                 throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} has not defined a symetric relationship in {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty}.");
             }
             /** @var PropertyMetadata $symetricPropertyMeta */
             $symetricPropertyMeta = $symetricEntityMeta->getProperty($propertyMeta->relationshipProperty);
             if ($propertyMeta->name !== $symetricPropertyMeta->relationshipProperty) {
                 throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} relationship with {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty} is not transitive.");
             }
             if ($symetricPropertyMeta->relationshipType === NULL) {
                 throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} has not defined a symetric relationship in {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty}.");
             }
             if ($symetricPropertyMeta->relationshipType !== $pairs[$propertyMeta->relationshipType]) {
                 throw new InvalidStateException("{$entityMeta->className}::\${$propertyMeta->name} has not defined a propper reverse relationship type in {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty}.");
             }
             if ($propertyMeta->relationshipType === PropertyMetadata::RELATIONSHIP_MANY_HAS_MANY || $propertyMeta->relationshipType === PropertyMetadata::RELATIONSHIP_ONE_HAS_ONE_DIRECTED) {
                 if ($propertyMeta->relationshipIsMain && $symetricPropertyMeta->relationshipIsMain) {
                     throw new InvalidStateException("Only one side of relationship {$entityMeta->className}::\${$propertyMeta->name} × {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty} could be defined as a primary.");
                 } elseif (!$propertyMeta->relationshipIsMain && !$symetricPropertyMeta->relationshipIsMain) {
                     throw new InvalidStateException("At least one side of relationship {$entityMeta->className}::\${$propertyMeta->name} × {$symetricEntityMeta->className}::\${$propertyMeta->relationshipProperty} has to be defined as a primary.");
                 }
             }
         }
     }
 }
예제 #10
0
파일: Repository.php 프로젝트: Vyki/orm
 /** @inheritdoc */
 public function remove($entity, $recursive = FALSE)
 {
     $entity = $entity instanceof IEntity ? $entity : $this->getById($entity);
     $this->identityMap->check($entity);
     if (isset($this->isProcessing[spl_object_hash($entity)])) {
         return $entity;
     }
     $this->isProcessing[spl_object_hash($entity)] = TRUE;
     $this->fireEvent($entity, 'onBeforeRemove');
     foreach ($entity->getMetadata()->getProperties() as $property) {
         if ($property->relationship !== NULL) {
             if (in_array($property->relationship->type, [PropertyRelationshipMetadata::MANY_HAS_ONE, PropertyRelationshipMetadata::ONE_HAS_ONE, PropertyRelationshipMetadata::ONE_HAS_ONE_DIRECTED])) {
                 $entity->getProperty($property->name)->set(NULL, TRUE);
             } elseif ($property->relationship->type === PropertyRelationshipMetadata::MANY_HAS_MANY) {
                 $entity->getValue($property->name)->set([]);
             } else {
                 $reverseRepository = $this->model->getRepository($property->relationship->repository);
                 $reverseProperty = $reverseRepository->getEntityMetadata()->getProperty($property->relationship->property);
                 if ($reverseProperty->isNullable || !$recursive) {
                     $entity->getValue($property->name)->set([]);
                 } else {
                     foreach ($entity->getValue($property->name) as $reverseEntity) {
                         $reverseRepository->remove($reverseEntity, $recursive);
                     }
                 }
             }
         }
     }
     if ($entity->isPersisted()) {
         $this->mapper->remove($entity);
         $this->identityMap->remove($entity->getPersistedId());
         $this->entitiesToFlush[1][] = $entity;
     }
     $this->detach($entity);
     $this->fireEvent($entity, 'onAfterRemove');
     unset($this->isProcessing[spl_object_hash($entity)]);
     return $entity;
 }
예제 #11
0
파일: Repository.php 프로젝트: nextras/orm
 /** @inheritdoc */
 public function remove($entity, $withCascade = true)
 {
     $entity = $entity instanceof IEntity ? $entity : $this->getById($entity);
     $this->identityMap->check($entity);
     return $this->model->remove($entity, $withCascade);
 }
예제 #12
0
파일: Container.php 프로젝트: ytnuk/orm
 protected function createComponentOneHasMany(Nextras\Orm\Entity\Reflection\PropertyMetadata $metadata, int $forceDefault = 0) : Kdyby\Replicator\Container
 {
     $repository = $this->model->getRepository($metadata->relationship->repository);
     $collection = $this->entity->getValue($metadata->name)->get()->fetchPairs(current($repository->getEntityMetadata()->getPrimaryKey()));
     $replicator = new Kdyby\Replicator\Container(function (Nette\Forms\Container $container) use($metadata, $repository, $collection) {
         $replicator = $container->parent;
         $name = $container->getName();
         unset($container->parent[$name]);
         if (!($entity = $collection[$name] ?? NULL)) {
             $entityClassName = $repository->getEntityMetadata()->getClassName();
             $entity = new $entityClassName();
         }
         $replicator->addComponent($container = $this->form->createComponent($entity), $name);
         if ($container instanceof Nette\Forms\Container) {
             call_user_func([$container->addSubmit('delete', $this->formatPropertyAction($metadata, 'delete')), 'addRemoveOnClick'], function (Kdyby\Replicator\Container $replicator, self $container) {
                 $container->removeEntity(TRUE);
             });
         }
     });
     $add = $replicator->addSubmit('add', $this->formatPropertyAction($metadata, 'add'));
     call_user_func([$add, 'addCreateOnClick']);
     $add->setValidationScope([$replicator]);
     $replicator->setCurrentGroup($this->getForm()->addGroup($this->prefixPropertyGroup($metadata), FALSE)->add($add));
     $this[$metadata->name] = $replicator;
     if ($createDefault = max(count($collection), $forceDefault)) {
         if (!$this->getForm()->isSubmitted()) {
             $count = 0;
             while ($count++ < $createDefault) {
                 $replicator->createOne(key($collection));
                 next($collection);
             }
         } elseif ($forceDefault) {
             while (iterator_count($replicator->getContainers()) < $createDefault) {
                 $replicator->createOne();
             }
         }
     }
     if ($add->isSubmittedBy()) {
         $isValid = TRUE;
         if ($scope = $add->getValidationScope()) {
             $isValid = !array_filter($scope, function (Nette\Forms\Container $container) {
                 return !$container->isValid();
             });
         }
         if ($isValid) {
             $add->setValidationScope(FALSE);
         }
         $add->click();
         $add->onClick = [];
     }
     $containers = [];
     foreach ($replicator->getContainers() as $container) {
         $delete = $container['delete'] ?? NULL;
         if ($delete instanceof Nette\Forms\Controls\SubmitButton && !$delete->isSubmittedBy()) {
             $containers[$container->name] = $container;
         }
     }
     if (count($containers) <= $forceDefault) {
         array_map(function (self $container) {
             unset($container['delete']);
         }, $containers);
     } else {
         $persistedContainers = array_filter($containers, function (self $container) {
             return $container->getEntity()->isPersisted();
         });
         if (count($persistedContainers) <= $forceDefault) {
             array_map(function (self $container) {
                 unset($container['delete']);
             }, $persistedContainers);
         }
     }
     foreach ($containers as $key => $container) {
         if ($container instanceof Nette\ComponentModel\IContainer) {
             foreach ($container->getComponents(FALSE, Nette\Forms\Controls\BaseControl::class) as $control) {
                 if ($control instanceof Nette\Forms\Controls\BaseControl && ($unique = $control->getOption('unique'))) {
                     foreach (array_diff_key($containers, [$key => $container]) as $sibling) {
                         $condition = $control->addCondition(Nette\Forms\Form::FILLED);
                         if (is_string($unique) && isset($sibling[$unique]) && ($uniqueControl = $container[$unique] ?? NULL)) {
                             if ($uniqueControl instanceof Nette\Forms\IControl) {
                                 $condition = $condition->addConditionOn($uniqueControl, Nette\Forms\Form::EQUAL, $sibling[$unique]);
                             }
                         }
                         $condition->addRule(Nette\Forms\Form::NOT_EQUAL, NULL, $sibling[$control->name]);
                     }
                 }
             }
         }
     }
     return $replicator;
 }
예제 #13
0
 private function normalizeAndAddJoins(array $levels, $sourceEntity, QueryBuilder $builder, &$distinctNeeded = false, &$value = null, &$modifier = '%any')
 {
     $column = array_pop($levels);
     $sourceMapper = $this->mapper;
     $sourceAlias = $builder->getFromAlias();
     $sourceReflection = $sourceMapper->getStorageReflection();
     $sourceEntityMeta = $this->metadataStorage->get($sourceEntity ?: $sourceMapper->getRepository()->getEntityClassNames()[0]);
     foreach ($levels as $levelIndex => $level) {
         $property = $sourceEntityMeta->getProperty($level);
         if ($property->relationship === null) {
             throw new InvalidArgumentException("Entity {$sourceEntityMeta->className}::\${$level} does not contain a relationship.");
         }
         $targetMapper = $this->model->getRepository($property->relationship->repository)->getMapper();
         $targetReflection = $targetMapper->getStorageReflection();
         $targetEntityMetadata = $this->metadataStorage->get($property->relationship->entity);
         $relType = $property->relationship->type;
         if ($relType === Relationship::ONE_HAS_MANY || $relType === Relationship::ONE_HAS_ONE && !$property->relationship->isMain) {
             $targetColumn = $targetReflection->convertEntityToStorageKey($property->relationship->property);
             $sourceColumn = $sourceReflection->getStoragePrimaryKey()[0];
             $distinctNeeded = $relType === Relationship::ONE_HAS_MANY;
         } elseif ($relType === Relationship::MANY_HAS_MANY) {
             if ($property->relationship->isMain) {
                 list($joinTable, list($inColumn, $outColumn)) = $sourceMapper->getManyHasManyParameters($property, $targetMapper);
             } else {
                 $sourceProperty = $targetEntityMetadata->getProperty($property->relationship->property);
                 list($joinTable, list($outColumn, $inColumn)) = $targetMapper->getManyHasManyParameters($sourceProperty, $sourceMapper);
             }
             $sourceColumn = $sourceReflection->getStoragePrimaryKey()[0];
             $builder->leftJoin($sourceAlias, $joinTable, self::getAlias($joinTable), "[{$sourceAlias}.{$sourceColumn}] = [{$joinTable}.{$inColumn}]");
             $sourceAlias = $joinTable;
             $sourceColumn = $outColumn;
             $targetColumn = $targetReflection->getStoragePrimaryKey()[0];
             $distinctNeeded = true;
         } else {
             $targetColumn = $targetReflection->getStoragePrimaryKey()[0];
             $sourceColumn = $sourceReflection->convertEntityToStorageKey($level);
         }
         $targetTable = $targetMapper->getTableName();
         $targetAlias = $level . str_repeat('_', $levelIndex);
         $builder->leftJoin($sourceAlias, $targetTable, $targetAlias, "[{$sourceAlias}.{$sourceColumn}] = [{$targetAlias}.{$targetColumn}]");
         $sourceAlias = $targetAlias;
         $sourceMapper = $targetMapper;
         $sourceReflection = $targetReflection;
         $sourceEntityMeta = $targetEntityMetadata;
     }
     $targetProperty = $sourceEntityMeta->getProperty($column);
     if ($targetProperty->isPrimary && $targetProperty->isVirtual) {
         // primary-proxy
         $primaryKey = $sourceEntityMeta->getPrimaryKey();
         if (count($primaryKey) > 1) {
             // composite primary key
             $modifier = '%any';
             list($expression, $value) = $this->processMultiColumn($sourceReflection, $primaryKey, $value, $sourceAlias);
             return $expression;
         } else {
             $column = reset($primaryKey);
         }
     }
     list($expression, $modifier, $value) = $this->processColumn($sourceReflection, $column, $value, $sourceAlias);
     return $expression;
 }
 private function normalizeAndAddJoins(array $levels, $sourceEntity, QueryBuilder $builder, &$distinctNeeded = FALSE, &$value = NULL)
 {
     $column = array_pop($levels);
     $sourceMapper = $this->mapper;
     $sourceAlias = $builder->getFromAlias();
     $sourceReflection = $sourceMapper->getStorageReflection();
     $sourceEntityMeta = $this->metadataStorage->get($sourceEntity ?: $sourceMapper->getRepository()->getEntityClassNames()[0]);
     foreach ($levels as $levelIndex => $level) {
         $property = $sourceEntityMeta->getProperty($level);
         if ($property->relationship === NULL) {
             throw new InvalidArgumentException("Entity {$sourceEntityMeta->className}::\${$level} does not contain a relationship.");
         }
         $targetMapper = $this->model->getRepository($property->relationship->repository)->getMapper();
         $targetReflection = $targetMapper->getStorageReflection();
         $targetEntityMetadata = $this->metadataStorage->get($property->relationship->entity);
         $relType = $property->relationship->type;
         if ($relType === Relationship::ONE_HAS_MANY || $relType === Relationship::ONE_HAS_ONE_DIRECTED && !$property->relationship->isMain) {
             $targetColumn = $targetReflection->convertEntityToStorageKey($property->relationship->property);
             $sourceColumn = $sourceReflection->getStoragePrimaryKey()[0];
             $distinctNeeded = TRUE;
         } elseif ($relType === Relationship::MANY_HAS_MANY) {
             if ($property->relationship->isMain) {
                 list($joinTable, list($inColumn, $outColumn)) = $sourceMapper->getManyHasManyParameters($property, $targetMapper);
             } else {
                 $sourceProperty = $targetEntityMetadata->getProperty($property->relationship->property);
                 list($joinTable, list($outColumn, $inColumn)) = $targetMapper->getManyHasManyParameters($sourceProperty, $sourceMapper);
             }
             $sourceColumn = $sourceReflection->getStoragePrimaryKey()[0];
             $builder->leftJoin($sourceAlias, $joinTable, self::getAlias($joinTable), "[{$sourceAlias}.{$sourceColumn}] = [{$joinTable}.{$inColumn}]");
             $sourceAlias = $joinTable;
             $sourceColumn = $outColumn;
             $targetColumn = $targetReflection->getStoragePrimaryKey()[0];
             $distinctNeeded = TRUE;
         } else {
             $targetColumn = $targetReflection->getStoragePrimaryKey()[0];
             $sourceColumn = $sourceReflection->convertEntityToStorageKey($level);
         }
         $targetTable = $targetMapper->getTableName();
         $targetAlias = $level . str_repeat('_', $levelIndex);
         $builder->leftJoin($sourceAlias, $targetTable, $targetAlias, "[{$sourceAlias}.{$sourceColumn}] = [{$targetAlias}.{$targetColumn}]");
         $sourceAlias = $targetAlias;
         $sourceMapper = $targetMapper;
         $sourceReflection = $targetReflection;
         $sourceEntityMeta = $targetEntityMetadata;
     }
     $sourceEntityMeta->getProperty($column);
     // check if property exists
     if ($column === 'id' && count($sourceEntityMeta->getPrimaryKey()) > 1) {
         $pair = [];
         foreach ($sourceEntityMeta->getPrimaryKey() as $column) {
             $column = $sourceReflection->convertEntityToStorageKey($column);
             $pair[] = "{$sourceAlias}.{$column}";
         }
         if (!isset($value[0][0])) {
             $value = [$value];
         }
         return '(' . implode(', ', $pair) . ')';
     } else {
         $column = $sourceReflection->convertEntityToStorageKey($column);
         return "{$sourceAlias}.{$column}";
     }
 }
예제 #15
0
 /**
  * @param  IEntity $entity
  * @param  PropertyMetadata[] $metadata
  * @parma  IModel $model
  * @param  array $pre
  */
 private static function setNulls($entity, array $metadata, IModel $model, array &$pre)
 {
     foreach ($metadata as $propertyMeta) {
         $type = $propertyMeta->relationship->type;
         $name = $propertyMeta->name;
         $reverseRepository = $model->getRepository($propertyMeta->relationship->repository);
         $reverseProperty = $propertyMeta->relationship->property ? $reverseRepository->getEntityMetadata()->getProperty($propertyMeta->relationship->property) : null;
         if ($type === Relationship::MANY_HAS_MANY) {
             /** @var ManyHasMany $property */
             $property = $entity->getProperty($name);
             $pre[] = $property;
             if ($reverseProperty !== null) {
                 foreach ($property as $reverseEntity) {
                     $pre[] = $reverseEntity->getProperty($reverseProperty->name);
                 }
             }
             $entity->setValue($name, []);
         } elseif ($type === Relationship::MANY_HAS_ONE || $type === Relationship::ONE_HAS_ONE && $propertyMeta->relationship->isMain) {
             /** @var ManyHasOne|OneHasOne $property */
             $property = $entity->getProperty($name);
             if ($reverseProperty !== null && $entity->hasValue($name)) {
                 $pre[] = $entity->getValue($name)->getProperty($reverseProperty->name);
             }
             $property->set(null, true);
         } else {
             // $type === Relationship::ONE_HAS_MANY or
             // $type === Relationship::ONE_HAS_ONE && !$isMain
             if (!$entity->hasValue($name) || $reverseProperty === null) {
                 continue;
             }
             if ($reverseProperty->isNullable) {
                 if ($type === Relationship::ONE_HAS_MANY) {
                     foreach ($entity->getValue($name) as $subValue) {
                         $pre[] = $subValue;
                     }
                     $entity->setValue($name, []);
                 } else {
                     $pre[] = $entity->getValue($name);
                     $entity->getProperty($name)->set(null, true);
                 }
             } else {
                 if ($type === Relationship::ONE_HAS_MANY && $entity->getValue($name)->count() === 0) {
                     continue;
                 }
                 $entityClass = get_class($entity);
                 $reverseEntityClass = $propertyMeta->relationship->entity;
                 $primaryValue = $entity->getValue('id');
                 $primaryValue = is_array($primaryValue) ? '[' . implode(', ', $primaryValue) . ']' : $primaryValue;
                 throw new InvalidStateException("Cannot remove {$entityClass}::\$id={$primaryValue} because {$reverseEntityClass}::\${$reverseProperty->name} cannot be a null.");
             }
         }
     }
 }
 public function __construct(IModel $model, IMapper $mapper)
 {
     $this->model = $model;
     $this->mapper = $mapper;
     $this->metadataStorage = $model->getMetadataStorage();
 }
예제 #17
0
 /**
  * @param  IEntity $entity
  * @param  PropertyMetadata[] $metadata
  * @parma  IModel $model
  * @param  array $pre
  */
 private static function setNulls($entity, array $metadata, IModel $model, array &$pre)
 {
     foreach ($metadata as $propertyMeta) {
         $type = $propertyMeta->relationship->type;
         $name = $propertyMeta->name;
         if ($type === Relationship::MANY_HAS_MANY) {
             $entity->setValue($name, []);
         } elseif ($type === Relationship::MANY_HAS_ONE || $type === Relationship::ONE_HAS_ONE && $propertyMeta->relationship->isMain) {
             $entity->getProperty($name)->set(NULL, TRUE);
         } else {
             // $type === Relationship::ONE_HAS_MANY or
             // $type === Relationship::ONE_HAS_ONE && !$isPrimary
             $reverseRepository = $model->getRepository($propertyMeta->relationship->repository);
             $reverseProperty = $reverseRepository->getEntityMetadata()->getProperty($propertyMeta->relationship->property);
             if ($reverseProperty->isNullable) {
                 if ($entity->hasValue($name)) {
                     if ($type === Relationship::ONE_HAS_MANY) {
                         foreach ($entity->getValue($name) as $subValue) {
                             $pre[] = $subValue;
                         }
                         $entity->getValue($name)->set([]);
                     } else {
                         $pre[] = $entity->getValue($name);
                         $entity->setValue($name, NULL);
                     }
                 }
             } else {
                 $entityClass = get_class($entity);
                 $reverseEntityClass = $propertyMeta->relationship->entity;
                 $primaryValue = $entity->getValue('id');
                 $primaryValue = is_array($primaryValue) ? '[' . implode(', ', $primaryValue) . ']' : $primaryValue;
                 throw new InvalidStateException("Cannot remove {$entityClass}::\$id={$primaryValue} because {$reverseEntityClass}::\${$reverseProperty->name} cannot be a null.");
             }
         }
     }
 }