Map and hydrate relations

@param $entity
@param $name
@param $value
@return Entity
@throws \Doctrine\ORM\Mapping\MappingException
353808
private function hydrateRelation($entity, $name, $value)
    {
        $relationClass = $this->em
            ->getClassMetadata(get_class($entity))
            ->getAssociationMapping($name)["targetEntity"]
        ;

        $relation = $entity->{"get".Inflector::camelize($name)}();
        if(in_array('id', array_keys($value))) {
            $relation = $this->em->getRepository($relationClass)->find($value['id']);
            unset($value['id']);
        } elseif(empty($relation)) {
            $relation = new $relationClass;
        }

        return $this->hydrate($relation, $value);
    }
758771
public function setRelation($name, $value, $data = [])
    {
        // 检测修改器
        $method = 'set' . Db::parseName($name, 1) . 'Attr';

        if (method_exists($this, $method)) {
            $value = $this->$method($value, array_merge($this->data, $data));
        }

        $this->relation[$name] = $value;

        return $this;
    }
776296
public function values($name)
    {
        return $this->map(function (EntityInterface $entity) use ($name) {
            return $entity->getByName($name);
        });
    }
176408
public static function entityManager($name = 'default')
    {
        if (isset(self::$entityManagers[$name])) {
            return self::$entityManagers[$name];
        }
        $databaseConnection = self::connection($name)->getDbalConnection();

        if (Configuration::get('app.env') == 'development') {
            $cache = new ArrayCache();
        } else { // @codeCoverageIgnore
            $cache = new FilesystemCache(Configuration::get('app.cache')); // @codeCoverageIgnore
        }

        $config = new \Doctrine\ORM\Configuration();
        $config->setMetadataCacheImpl($cache);
        $driver = $config->newDefaultAnnotationDriver([APPPATH . 'Entity'], false);

        $config->setMetadataDriverImpl($driver);
        $config->setQueryCacheImpl($cache);

        $proxyDir = APPPATH . 'Proxy';
        $proxyNamespace = 'App\Proxy';

        $config->setProxyDir($proxyDir);
        $config->setProxyNamespace($proxyNamespace);
        Autoloader::register($proxyDir, $proxyNamespace);

        $loggerChain = new LoggerChain();
        if (Configuration::get('app.env') == 'development') {
            $config->setAutoGenerateProxyClasses(true);

            $loggerChain->addLogger(new DoctrineLogBridge(\Logger::getInstance()->getMonologInstance()));
            $loggerChain->addLogger(DebugBarHelper::getInstance()->getDebugStack());
        } else { // @codeCoverageIgnore
            $config->setAutoGenerateProxyClasses(false); // @codeCoverageIgnore
        }
        $em = EntityManager::create($databaseConnection, $config);

        $em->getConnection()->getConfiguration()->setSQLLogger($loggerChain);
        $em->getConfiguration()->setSQLLogger($loggerChain);

        self::$entityManagers[$name] = $em;
        return $em;
    }
1246624
protected function setProperty(&$reflectionClass, $entity, $name, $value)
    {
        $property = $reflectionClass->getProperty($name);
        $property->setAccessible(true);
        $property->setValue($entity, $value);
    }
562329
public function getHydratorForEntity($value)
    {
        $entityMetadata = $this->getMetadataMap()[ClassUtils::getRealClass(get_class($value))];
        $objectManagerClass = $this->getDoctrineHydratorConfig()[$entityMetadata['hydrator']]['object_manager'];

        return new DoctrineHydrator($this->getServiceLocator()->get($objectManagerClass), true);
    }
843736
public function set($name, $value = null)
    {
        $property = $this->getEntityDescription()->getProperty($name);

        if (!$property instanceof AnDomainPropertyAbstract) {
            return parent::set($name, $value);
        }

        //if a value is mixin then get its mixer
        if ($value instanceof AnMixinAbstract) {
            $value = $value->getMixer();
        }

        $modify = false;
        $name = $property->getName();

        $context = $this->getRepository()->getCommandContext();

        $context['property'] = $property;
        $context['value'] = $value;
        $context['entity'] = $this;

        if ($this->getRepository()->getCommandChain()->run('before.setdata', $context) === false) {
            return $this;
        }

        $value = $context->value;

        if ($property->isSerializable()) {
            $modify = true;
            if ($property->isRelationship() && $property->isManyToOne() && $value) {
                if (!is($value, 'AnDomainEntityAbstract', 'AnDomainEntityProxy')) {
                    throw new AnDomainExceptionType('Value of '.$property->getName().' must be a AnDomainEntityAbstract');
                }

                //if a relationship is a belongs to then make sure the parent
                //is always saved before child
                //example if $topic->author = new author
                //then save the new author first before saving topic
                //only set the dependency
                if ($value->getEntityState() == AnDomain::STATE_NEW) {
                    //save the child before saving the parent
                    $this->getRepository()->getSpace()->setSaveOrder($value, $this);
                }
            }
            //if value is not null do a composite type checking
            if (!is_null($value)) {
                if ($property->isAttribute() && !$property->isScalar()) {
                    if (!is($value, $property->getType())) {
                        throw new AnDomainEntityException('Value of '.$property->getName().' must be a '.$property->getType().'. a '.get_class($value).' is given.');
                    }
                }
            }
        } elseif ($property->isRelationship() && $property->isOnetoOne()) {
            $child = $property->getChildProperty();
            $current = $this->get($property->getName());

            //if there's a current value and it's existence depends on
            //the parent entity then remove the current
            if ($current && $child->isRequired()) {
                $current->delete();
            }

            //if a one-to-one relationship then there must be a child key for the property
            //then must set the inverse
            if ($value) {
                $value->set($child->getName(), $this);
            }

            $this->_data[$property->getName()] = $value;
        } elseif ($property->isRelationship() && ($property->isManyToMany() || $property->isOneToMany())) {
            $current = $this->get($name);

            if ($current instanceof AnDomainDecoratorOnetomany) {
                $values = AnConfig::unbox($value);
                //can be an AnObjectArray or AnObjectSet object
                if ($values instanceof AnObject && $values instanceof Iterator) {
                    $current->delete();

                    foreach ($values as $value) {
                        $current->insert($value);
                    }
                }
            }
        }

        //only modify if the current value is differnet than the new value
        $modify = $modify && !is_eql($this->get($name), $value);

        if ($modify) {
            //lets bring them back to their orignal type
            if (!is_null($value) && $property->isAttribute() && $property->isScalar()) {
                settype($value, $property->getType());
            }

            if ($this->getEntityState() != AnDomain::STATE_NEW) {
                //store the original value for future checking
                if (!isset($this->_modified[$name])) {
                    $this->_modified[$name] = array('old' => $this->get($name));
                }

                $this->_modified[$name]['new'] = $value;

                //check if the new value is the same as the old one then remove the
                if (is_eql($this->_modified[$name]['old'], $this->_modified[$name]['new'])) {
                    //if there are no modified then reset the entity
                    unset($this->_modified[$name]);

                    if (count($this->_modified) === 0) {
                        $this->reset();
                    }
                }
            }

            $this->_data[$property->getName()] = $value;
            $this->getRepository()->getSpace()->setEntityState($this, AnDomain::STATE_MODIFIED);

            //only track modifications for the updated entities
            if ($this->getEntityState() !== AnDomain::STATE_MODIFIED) {
                $this->_modified = array();
            }
        }

        return $this;
    }
1270220
public function set($key, $value)
    {
        if (! $value instanceof RelationInterface) {
            throw new InvalidArgumentException(
                "Only RelationInterface objects can be putted in a ".
                "RelationsMap."
            );
        }
        return parent::set($key, $value);
    }
1285819
public static function buildRelationQuery($entity, Relation $relation) {
        $relQuery = "";
        $getid = "getId";
        if ($relation->getCardinality() == Relation::$manyToMany) {
            $m = "get" . $relation->getName();
            $relQuery .= "INSERT INTO " . $relation->getTable() . " (" . $relation->getLocalColumn() . ", " . $relation->getForeignColumn() . ") ";
            $relQuery .= "VALUES (:" . $relation->getLocalColumn() . ", :" . $relation->getForeignColumn() . ");";
        }
        if ($relation->getCardinality() == Relation::$oneToMany) {
            $relMapper = MapperBuilder::buildFromName($this->mapping, $relation->getEntity());
            $m = "get" . $relation->getName();
            foreach ($entity->$m() as $rel) {
                $setid = "set" . $relMapper->getNameForColumn($relation->getForeignColumn());
                $rel->$setid($entity->$getid());
                $relQuery .= $this->buildInsertQuery($rel);
            }
        }


        return $relQuery;
    }
472480
public function set($key, $value)
    {
        if (! $value instanceof EntityMapperInterface) {
            throw new InvalidArgumentException(
                'Trying to add a non EntityMapper to MappersMap.'
            );
        }
        return parent::set($key, $value);
    }
434942
public function validate($name, $value)
    {
        $meta = $this->schema->getPropertyEntryByIdentifier($name);

        if (!$meta) {
            throw new Exception("Meta informação para propriedade {$name} não encontrada no schema", 400);
        }
        $meta = is_array($meta) ? $meta[0] : $meta;

        $meta = $meta->toArray();

        return $this->hydrate($meta, $value);
    }
617401
protected function loadCollaction($name, $entityName, $fields)
    {
        $em = $this->getContainer()->get('doctrine')->getManager();
        $entityRepository = $em->getRepository($entityName);

        $meta = $em->getClassMetadata($entityName);
        $identifier = $meta->getSingleIdentifierFieldName();
        $identifierMethodName = 'get'.ucfirst($identifier);

        $collection = $entityRepository->findAll();

        $result = array();

        foreach ($collection as $item) {
            $element = array();

            foreach ($fields as $fieldName => $attributes) {
                $methodName = 'get'.ucfirst($fieldName);
                $fieldValue = $item->$methodName();

                $value = null;

                if (is_object($fieldValue)) {
                    if (get_class($fieldValue) === 'DateTime') {
                        $value = array('type' => 'DateTime', 'name' => $fieldValue->format('r'));
                    } elseif (array_key_exists('targetEntity', $attributes)) {
                        $targetClassName = $meta->associationMappings[$fieldName]['targetEntity'];
                        $targetEntityProvider = new EntityProvider($targetClassName);

                        $targetMethodName = 'get'.ucfirst($em->getClassMetadata($targetClassName)->identifier[0]);
                        $value = array(
                            'type' => 'reference',
                            'name' => $targetEntityProvider->getName().'_'.$fieldValue->$targetMethodName(),
                        );
                    } else {
                        throw new \Exception('aaa');
                    }
                } else {
                    $value = $fieldValue;
                }

                $element[$fieldName] = $value;
            }

            $result[$name.'_'.$item->$identifierMethodName()] = $element;
        }

        return $result;
    }
1303949
protected function checkRelationExistence($name)
    {
        $getter = 'get' . ucfirst($name);
        $class = get_class($this->owner);

        if (method_exists($this->owner, $getter)) {
            /** @var ActiveQuery $value */
            $value = $this->owner->$getter();

            if (!($value instanceof ActiveQueryInterface)) {
                throw new InvalidConfigException("Value of relation '$getter' not valid");
            }

            $this->models[$name]['multiple'] = $value->multiple;
        } else {
            throw new InvalidConfigException("Relation '$class::$getter' for attribute '$name' does not exists");
        }
    }
756787
public function hydrate(array $data, $entity)
    {
        $this->hydrateEntityProperties($entity, $data);
        
        $repository = $this->getRepository();
        $repository->dispatchEvent(ORMEvents::onEntityLoad, new EntityLifecycleEvent($repository, $entity));
        
        return $entity;
    }
40480
protected function getHasRelationQuery($relation, $entity)
    {
        return Relationship::noConstraints(function () use ($relation, $entity) {
            return $this->entityMap->$relation($entity);
        });
    }
883564
final protected function setAttribute($name, $value)
    {
        if ($value !== null && $this->hasAttributeValueFactory($name)) {
            $this->internalCache[$name] = $this->createAttributeValue($name, $value);

            if ($this->internalCache[$name] instanceof JsonSerializable) {
                $value = $this->internalCache[$name]->jsonSerialize();
            } elseif (is_array($this->internalCache[$name])) {
                $value = array_map(
                    function ($value) {
                        if ($value instanceof JsonSerializable) {
                            $value = $value->jsonSerialize();
                        }

                        return $value;
                    },
                    $this->internalCache[$name]
                );
            } else {
                $value = $this->internalCache[$name];
            }
        }

        $this->data[$name] = $value;

        return $this;
    }
880263
private function update($name, $value = 0)
    {
        if (null === $this->find($name)) {
            throw new InvalidArgumentException(sprintf('Unknown sequence with name %s', $name));
        }

        if (false === Numeric::isPositiveInteger($value, false)) {
            throw new InvalidArgumentException('Initial value of a sequence must be a positive integer');
        }

        $query = 'UPDATE sequence SET value = :value WHERE name = :name';
        $params = array(
            'name'  => $name,
            'value' => $value,
        );

        $this->getEntityManager()
            ->getConnection()
            ->executeUpdate($query, $params)
        ;

        return $value;
    }