/** * @param Request $request * @param FilterInterface $filter * @param Criteria $criteria * @param ClassMetadata $embedClassMeta * * @return null */ protected function applyFilter(Request $request, FilterInterface $filter, Criteria $criteria, ClassMetadata $embedClassMeta) { $properties = $filter->getRequestProperties($request); if ($filter instanceof OrderFilter && !empty($properties)) { $criteria->orderBy($properties); return null; } if ($filter instanceof SearchFilter) { foreach ($properties as $name => $propertie) { if (in_array($name, $embedClassMeta->getIdentifier())) { continue; } $expCriterial = Criteria::expr(); if ($embedClassMeta->hasAssociation($name)) { $associationTargetClass = $embedClassMeta->getAssociationTargetClass($name); $propertyResource = $this->resourceResolver->getResourceForEntity($associationTargetClass); $propertyObj = $this->dataProviderChain->getItem($propertyResource, (int) $propertie['value'], true); if ($propertyObj && $propertyResource instanceof ResourceInterface) { $whereCriteria = $expCriterial->in($name, [$propertyObj]); $criteria->where($whereCriteria); } } else { if ($embedClassMeta->hasField($name)) { $fieldMapping = $embedClassMeta->getFieldMapping($name); $type = isset($fieldMapping['type']) ? $fieldMapping['type'] : null; $value = isset($this->mappingFilterVar[$type]) ? filter_var($propertie['value'], $this->mappingFilterVar[$type]) : $propertie['value']; $whereCriteria = isset($propertie['precision']) && $propertie['precision'] === 'exact' ? $expCriterial->eq($name, $value) : $expCriterial->contains($name, $propertie['value']); $criteria->where($whereCriteria); } } } } }
/** * @param QueryBuilder $qb * @param Criteria $criteria */ protected function buildWhereClause(Builder $qb, Criteria $criteria) { foreach ($criteria as $key => $value) { if ($this->metadata->hasField($key) || $this->metadata->hasAssociation($key)) { $qb->field($key)->equals($value); } } }
/** * @param QueryBuilder $qb * @param Criteria $criteria */ protected function buildWhereClause(QueryBuilder $qb, Criteria $criteria) { $values = array(); foreach ($criteria as $key => $value) { if ($this->metadata->hasField($key) || $this->metadata->hasAssociation($key)) { $qb->andWhere('e.' . $key . ' = :' . $key); $values[$key] = $value; } } $qb->setParameters($values); }
/** * {@inheritDoc} */ public function mapHierarchy(ClassMetadata $meta) { if ($meta->isMappedSuperclass || !$meta->isRootEntity()) { return; } $rc = $meta->getReflectionClass(); if ($rc->hasProperty('parent') && !$meta->hasAssociation('parent')) { $meta->mapManyToOne(['targetEntity' => $meta->getName(), 'fieldName' => 'parent', 'inversedBy' => 'children', 'cascade' => ['persist']]); } if ($rc->hasProperty('children') && !$meta->hasAssociation('children')) { $meta->mapOneToMany(['targetEntity' => $meta->getName(), 'fieldName' => 'children', 'mappedBy' => 'parent', 'cascade' => ['persist', 'remove'], 'fetch' => 'EXTRA_LAZY']); } }
/** * Hydrate $object with the provided $data. * * @param array $data * @param object $object * @throws \Exception * @return object */ public function hydrate(array $data, $object) { $this->metadata = $this->objectManager->getClassMetadata(get_class($object)); foreach ($data as $field => &$value) { if ($this->metadata->hasAssociation($field)) { $target = $this->metadata->getAssociationTargetClass($field); if ($this->metadata->isSingleValuedAssociation($field)) { $value = $this->toOne($value, $target); } elseif ($this->metadata->isCollectionValuedAssociation($field)) { $value = $this->toMany($value, $target); } } } return $this->hydrator->hydrate($data, $object); }
protected function setPropertyType(DoctrineClassMetadata $doctrineMetadata, PropertyMetadata $propertyMetadata) { /** @var \Doctrine\ODM\PHPCR\Mapping\ClassMetadata $doctrineMetadata */ $propertyName = $propertyMetadata->name; if ($doctrineMetadata->hasField($propertyName) && ($fieldType = $this->normalizeFieldType($doctrineMetadata->getTypeOfField($propertyName)))) { $field = $doctrineMetadata->getFieldMapping($propertyName); if (!empty($field['multivalue'])) { $fieldType = 'array'; } $propertyMetadata->setType($fieldType); } elseif ($doctrineMetadata->hasAssociation($propertyName)) { try { $targetEntity = $doctrineMetadata->getAssociationTargetClass($propertyName); } catch (\Exception $e) { return; } if (null === $this->tryLoadingDoctrineMetadata($targetEntity)) { return; } if (!$doctrineMetadata->isSingleValuedAssociation($propertyName)) { $targetEntity = "ArrayCollection<{$targetEntity}>"; } $propertyMetadata->setType($targetEntity); } }
/** * Hydrate $object with the provided $data. * * @param array $data * @param object $object * @throws \Exception * @return object */ public function hydrate(array $data, $object) { $this->metadata = $this->objectManager->getClassMetadata(get_class($object)); $object = $this->tryConvertArrayToObject($data, $object); foreach ($data as $field => &$value) { $value = $this->hydrateValue($field, $value); if ($value === null) { continue; } // @todo DateTime (and other types) conversion should be handled by doctrine itself in future if (in_array($this->metadata->getTypeOfField($field), array('datetime', 'time', 'date'))) { if (is_int($value)) { $dt = new DateTime(); $dt->setTimestamp($value); $value = $dt; } elseif (is_string($value)) { $value = new DateTime($value); } } if ($this->metadata->hasAssociation($field)) { $target = $this->metadata->getAssociationTargetClass($field); if ($this->metadata->isSingleValuedAssociation($field)) { $value = $this->toOne($value, $target); } elseif ($this->metadata->isCollectionValuedAssociation($field)) { $value = $this->toMany($value, $target); // Automatically merge collections using helper utility $propertyRefl = $this->metadata->getReflectionClass()->getProperty($field); $propertyRefl->setAccessible(true); $previousValue = $propertyRefl->getValue($object); $value = CollectionUtils::intersectUnion($previousValue, $value); } } } return $this->hydrator->hydrate($data, $object); }
/** * {@inheritdoc} */ public function getTransformerInfo(ColumnInfoInterface $columnInfo, ClassMetadata $metadata) { if (!$columnInfo->getLocale() && !count($columnInfo->getSuffixes()) || !$metadata->hasAssociation('translations')) { return; } return array($this->transformer, array()); }
/** * {@inheritdoc} */ public function getTransformerInfo(ColumnInfoInterface $columnInfo, ClassMetadata $metadata) { $mapping = $this->getMapping(); if (!$metadata->hasAssociation('translations') || !isset($mapping[$columnInfo->getName()])) { return null; } return array($this->transformer, array('propertyPath' => $mapping[$columnInfo->getName()])); }
/** * {@inheritDoc} */ public function mapTranslation(ClassMetadata $meta, $translatableClassName) { $rc = $meta->getReflectionClass(); if (!$rc->hasProperty('object') || $meta->hasAssociation('object') || !$rc->isSubclassOf($this->personalTranslation)) { return; } $namingStrategy = $this->getObjectManager()->getConfiguration()->getNamingStrategy(); $meta->mapManyToOne(['targetEntity' => $translatableClassName, 'fieldName' => 'object', 'inversedBy' => 'translations', 'isOwningSide' => true, 'joinColumns' => [['name' => $namingStrategy->joinColumnName('object'), 'referencedColumnName' => $namingStrategy->referenceColumnName(), 'onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE']]]); }
public function testLoadClassMetadata() { $this->loadClassMetadataEvent->getClassMetadata()->willReturn($this->classMetadata->reveal()); $this->classMetadata->getReflectionClass()->willReturn($this->refl->reveal()); $this->refl->implementsInterface('Sulu\\Component\\Persistence\\Model\\UserBlameInterface')->willReturn(true); $this->classMetadata->hasAssociation('creator')->shouldBeCalled(); $this->classMetadata->hasAssociation('changer')->shouldBeCalled(); $this->classMetadata->mapManyToOne(Argument::any())->shouldBeCalled(); $this->subscriber->loadClassMetadata($this->loadClassMetadataEvent->reveal()); }
/** * {@inheritDoc} * @throws InvalidArgumentException If a strategy added to a collection does not extend AbstractCollectionStrategy */ public function addStrategy($name, StrategyInterface $strategy) { if ($this->metadata->hasAssociation($name)) { if (!$strategy instanceof Strategy\AbstractCollectionStrategy) { throw new InvalidArgumentException(sprintf('Strategies used for collections valued associations must inherit from ' . 'Strategy\\AbstractCollectionStrategy, %s given', get_class($strategy))); } $strategy->setCollectionName($name)->setClassMetadata($this->metadata); } return parent::addStrategy($name, $strategy); }
/** * {@inheritDoc} */ protected function validateExtendedMetadata(ClassMetadata $baseClassMetadata, ClassMetadataInterface $extendedClassMetadata) { if ($extendedClassMetadata->hasTranslatableProperties()) { if (!isset($extendedClassMetadata->localeProperty)) { throw new Exception\MappingException('Entity \'' . $baseClassMetadata->name . '\' has translatable properties so it must have property marked with @Translatable\\Language annotation'); } $translatableProperties = $extendedClassMetadata->getTranslatableProperties(); foreach ($translatableProperties as $translation => $properties) { if (!$baseClassMetadata->hasAssociation($translation) || !$baseClassMetadata->isCollectionValuedAssociation($translation)) { throw new Exception\MappingException('Field \'' . $translation . '\' in entity \'' . $baseClassMetadata->name . '\' has to be a OneToMany association'); } } } if (isset($extendedClassMetadata->localeProperty)) { if ($extendedClassMetadata->hasTranslatableProperties() && ($baseClassMetadata->hasField($extendedClassMetadata->localeProperty) || $baseClassMetadata->hasAssociation($extendedClassMetadata->localeProperty))) { throw new Exception\MappingException('Entity \'' . $baseClassMetadata->name . '\' seems to be a translatable entity so its \'' . $extendedClassMetadata->localeProperty . '\' field must not be persistent'); } else { if (!$extendedClassMetadata->hasTranslatableProperties() && !$baseClassMetadata->hasField($extendedClassMetadata->localeProperty) && !$baseClassMetadata->hasAssociation($extendedClassMetadata->localeProperty)) { throw new Exception\MappingException('Entity \'' . $baseClassMetadata->name . '\' seems to be a translation entity so its \'' . $extendedClassMetadata->localeProperty . '\' field must be persistent'); } } } }
public function __construct(ObjectManager $om, ClassMetadata $classMetadata) { $ids = $classMetadata->getIdentifierFieldNames(); $idType = $classMetadata->getTypeOfField(current($ids)); $this->om = $om; $this->classMetadata = $classMetadata; $this->singleId = 1 === count($ids); $this->intId = $this->singleId && in_array($idType, array('integer', 'smallint', 'bigint')); $this->idField = current($ids); // single field association are resolved, since the schema column could be an int if ($this->singleId && $classMetadata->hasAssociation($this->idField)) { $this->associationIdReader = new self($om, $om->getClassMetadata($classMetadata->getAssociationTargetClass($this->idField))); $this->singleId = $this->associationIdReader->isSingleId(); $this->intId = $this->associationIdReader->isIntId(); } }
/** * Adds an object to a collection. * * @param string $field * @param array $args * * @return void * * @throws \BadMethodCallException * @throws \InvalidArgumentException */ private function add($field, $args) { $this->initializeDoctrine(); if ($this->cm->hasAssociation($field) && $this->cm->isCollectionValuedAssociation($field)) { $targetClass = $this->cm->getAssociationTargetClass($field); if (!$args[0] instanceof $targetClass) { throw new \InvalidArgumentException("Expected persistent object of type '" . $targetClass . "'"); } if (!$this->{$field} instanceof Collection) { $this->{$field} = new ArrayCollection($this->{$field} ?: []); } $this->{$field}->add($args[0]); $this->completeOwningSide($field, $targetClass, $args[0]); } else { throw new \BadMethodCallException("There is no method add" . $field . "() on " . $this->cm->getName()); } }
/** * {@inheritdoc} */ public function readMetadata(ClassMetadata $doctrineMeta, array &$meta) { if (!isset($meta['user'])) { $meta['user'] = []; } foreach ($doctrineMeta->getReflectionClass()->getProperties() as $property) { $annotation = $this->reader->getPropertyAnnotation($property, User::ANNOTATION); if (!$annotation instanceof User) { continue; } if (!empty($meta['user'])) { if ($meta['user']['property'] === $property->getName()) { continue; } throw $this->createPropertyAnnotationInvalidException(User::ANNOTATION, $doctrineMeta->getName(), $property->getName(), sprintf('property "%s" is already annotated with this annotation', $meta['user']['property'])); } if (!$doctrineMeta->hasAssociation($property->getName())) { throw $this->createPropertyAnnotationInvalidException(User::ANNOTATION, $doctrineMeta->getName(), $property->getName(), 'property must be mapped association'); } $meta['user'] = ['property' => $property->getName(), 'roles' => $annotation->roles]; } }
protected function setPropertyType(DoctrineClassMetadata $doctrineMetadata, PropertyMetadata $propertyMetadata) { $propertyName = $propertyMetadata->name; if ($doctrineMetadata->hasField($propertyName) && ($fieldType = $this->normalizeFieldType($doctrineMetadata->getTypeOfField($propertyName)))) { $propertyMetadata->setType($fieldType); } elseif ($doctrineMetadata->hasAssociation($propertyName)) { $targetEntity = $doctrineMetadata->getAssociationTargetClass($propertyName); if (null === ($targetMetadata = $this->tryLoadingDoctrineMetadata($targetEntity))) { return; } // For inheritance schemes, we cannot add any type as we would only add the super-type of the hierarchy. // On serialization, this would lead to only the supertype being serialized, and properties of subtypes // being ignored. if ($targetMetadata instanceof DoctrineClassMetadata && !$targetMetadata->isInheritanceTypeNone()) { return; } if (!$doctrineMetadata->isSingleValuedAssociation($propertyName)) { $targetEntity = "ArrayCollection<{$targetEntity}>"; } $propertyMetadata->setType($targetEntity); } }
protected function unserializeField($data, ClassMetadata $metadata, $document, $field, $mode) { if ($metadata->hasAssociation($field) && $metadata->isSingleValuedAssociation($field)) { $value = $this->unserializeSingleModel($data, $metadata, $document, $field, $mode); } elseif ($metadata->hasAssociation($field)) { $value = $this->unserializeCollection($data, $metadata, $document, $field, $mode); } else { $value = $this->unserializeSingleValue($data, $metadata, $field); } if (isset($value)) { $metadata->setFieldValue($document, $field, $value); } elseif ($mode == self::UNSERIALIZE_UPDATE) { $metadata->setFieldValue($document, $field, null); } }
protected function serializeField(ClassMetadata $metadata, $value, $field) { if ($metadata->hasAssociation($field) && $metadata->isSingleValuedAssociation($field)) { return $this->serializeSingleModel($metadata, $value, $field); } elseif ($metadata->hasAssociation($field)) { return $this->serializeCollection($metadata, $value, $field); } else { return $this->serializeSingleValue($metadata, $value, $field); } }
/** * @param ClassMetadata $metadata * @param $name * @return bool */ protected function checkForExcludeElementFromMetadata(ClassMetadata $metadata, $name) { $params = array('metadata' => $metadata, 'name' => $name); $result = false; if ($metadata->hasField($name)) { $result = $this->getEventManager()->trigger(static::EVENT_EXCLUDE_FIELD, $this, $params); } elseif ($metadata->hasAssociation($name)) { $result = $this->getEventManager()->trigger(static::EVENT_EXCLUDE_ASSOCIATION, $this, $params); } if ($result) { $result = (bool) $result->last(); } return $result; }
/** * Return "false" if can't find config for field, "null" if field type is unknown for given field * or array with config data for given field * * @param ClassMetadata $metadata * @param $field * @return array|bool */ protected function guessAttributeParametersScalarField(ClassMetadata $metadata, $field) { if ($metadata->hasField($field)) { $doctrineType = $metadata->getTypeOfField($field); if (!isset($this->doctrineTypeMapping[$doctrineType])) { return null; } return $this->formatResult($this->getLabel($metadata->getName(), $field), $this->doctrineTypeMapping[$doctrineType]['type'], $this->doctrineTypeMapping[$doctrineType]['options']); } elseif ($this->entityConfigProvider->hasConfig($metadata->getName(), $field)) { $entityConfig = $this->entityConfigProvider->getConfig($metadata->getName(), $field); $fieldType = $entityConfig->getId()->getFieldType(); if (!$metadata->hasAssociation($field)) { return $this->formatResult($entityConfig->get('label'), $this->doctrineTypeMapping[$fieldType]['type'], $this->doctrineTypeMapping[$fieldType]['options']); } } return false; }
/** * Generates a closure capable of finalizing a cloned proxy * * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata * @param \Doctrine\ODM\MongoDB\Persisters\DocumentPersister $documentPersister * @param \ReflectionProperty $reflectionId * * @return \Closure * * @throws \Doctrine\ODM\MongoDB\DocumentNotFoundException */ private function createCloner(BaseClassMetadata $classMetadata, DocumentPersister $documentPersister, ReflectionProperty $reflectionId) { return function (BaseProxy $proxy) use($documentPersister, $classMetadata, $reflectionId) { if ($proxy->__isInitialized()) { return; } $proxy->__setInitialized(true); $proxy->__setInitializer(null); $id = $reflectionId->getValue($proxy); $original = $documentPersister->load(array('_id' => $id)); if (null === $original) { throw DocumentNotFoundException::documentNotFound(get_class($proxy), $id); } foreach ($classMetadata->getReflectionClass()->getProperties() as $reflectionProperty) { $propertyName = $reflectionProperty->getName(); if ($classMetadata->hasField($propertyName) || $classMetadata->hasAssociation($propertyName)) { $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($proxy, $reflectionProperty->getValue($original)); } } }; }
/** * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata * @param string $field * @return bool */ private function isFieldSearchable(ClassMetadata $classMetadata, $field) { return $classMetadata->hasField($field) || $classMetadata->hasAssociation($field) && $classMetadata->isSingleValuedAssociation($field); }
/** * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $baseClassMetadata * @param \FSi\DoctrineExtensions\Translatable\Mapping\ClassMetadata $translatableClassMetadata * @throws \FSi\DoctrineExtensions\Translatable\Exception\MappingException */ private function validateTranslationLocaleProperty(ClassMetadata $baseClassMetadata, TranslatableClassMetadata $translatableClassMetadata) { if (!$baseClassMetadata->hasField($translatableClassMetadata->localeProperty) && !$baseClassMetadata->hasAssociation($translatableClassMetadata->localeProperty)) { throw new Exception\MappingException(sprintf("Entity '%s' seems to be a translation entity so its '%s' field must be persistent", $baseClassMetadata->getName(), $translatableClassMetadata->localeProperty)); } }
/** * @param DoctrineSqlFilter $sqlFilter * @param ClassMetadata $targetEntity * @param string $targetTableAlias * @return string * @throws InvalidQueryRewritingConstraintException * @throws \Exception */ public function getSql(DoctrineSqlFilter $sqlFilter, ClassMetadata $targetEntity, $targetTableAlias) { $targetEntityPropertyName = strpos($this->path, '.') ? substr($this->path, 0, strpos($this->path, '.')) : $this->path; $quoteStrategy = $this->entityManager->getConfiguration()->getQuoteStrategy(); if ($targetEntity->hasAssociation($targetEntityPropertyName) === FALSE) { return $this->getSqlForSimpleProperty($sqlFilter, $quoteStrategy, $targetEntity, $targetTableAlias, $targetEntityPropertyName); } elseif (strstr($this->path, '.') === FALSE && $targetEntity->isSingleValuedAssociation($targetEntityPropertyName) === TRUE && $targetEntity->isAssociationInverseSide($targetEntityPropertyName) === FALSE) { return $this->getSqlForManyToOneAndOneToOneRelationsWithoutPropertyPath($sqlFilter, $quoteStrategy, $targetEntity, $targetTableAlias, $targetEntityPropertyName); } elseif ($targetEntity->isSingleValuedAssociation($targetEntityPropertyName) === TRUE && $targetEntity->isAssociationInverseSide($targetEntityPropertyName) === FALSE) { return $this->getSqlForManyToOneAndOneToOneRelationsWithPropertyPath($sqlFilter, $quoteStrategy, $targetEntity, $targetTableAlias, $targetEntityPropertyName); } elseif ($targetEntity->isSingleValuedAssociation($targetEntityPropertyName) === TRUE && $targetEntity->isAssociationInverseSide($targetEntityPropertyName) === TRUE) { throw new InvalidQueryRewritingConstraintException('Single valued properties from the inverse side are not supported in a content security constraint path! Got: "' . $this->path . ' ' . $this->operator . ' ' . $this->operandDefinition . '"', 1416397754); } elseif ($targetEntity->isCollectionValuedAssociation($targetEntityPropertyName) === TRUE) { throw new InvalidQueryRewritingConstraintException('Multivalued properties are not supported in a content security constraint path! Got: "' . $this->path . ' ' . $this->operator . ' ' . $this->operandDefinition . '"', 1416397655); } throw new InvalidQueryRewritingConstraintException('The configured operator of the entity constraint is not valid/supported. Got: ' . $this->operator, 1270483540); }
/** * Generates the list of public properties to be lazy loaded, with their default values. * * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class * * @return mixed[] */ private function getLazyLoadedPublicProperties(ClassMetadata $class) { $defaultProperties = $class->getReflectionClass()->getDefaultProperties(); $properties = array(); foreach ($class->getReflectionClass()->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { $name = $property->getName(); if (($class->hasField($name) || $class->hasAssociation($name)) && !$class->isIdentifier($name)) { $properties[$name] = $defaultProperties[$name]; } } return $properties; }
/** * Get identifier information for a class. * * @param ClassMetadata $classMetadata The entity metadata * * @return array Return an array with idAsIndex, idAsValue and identifier */ private function getIdentifierInfoForClass(ClassMetadata $classMetadata) { $identifier = null; $idAsIndex = false; $idAsValue = false; $identifiers = $classMetadata->getIdentifierFieldNames(); if (1 === count($identifiers)) { $identifier = $identifiers[0]; if (!$classMetadata->hasAssociation($identifier)) { $idAsValue = true; if (in_array($classMetadata->getTypeOfField($identifier), array('integer', 'smallint', 'bigint'))) { $idAsIndex = true; } } } return array($idAsIndex, $idAsValue, $identifier); }