Once populated, ClassMetadata instances are usually cached in a serialized form.
IMPORTANT NOTE:
The fields of this class are only public for 2 reasons:
1) To allow fast READ access.
2) To drastically reduce the size of a serialized instance (private/protected members
get the whole class name, namespace inclusive, prepended to every property in
the serialized representation).
/** * Convert thrift class spec to doctrine ClassMetadataInfo * * @param $className * @return ClassMetadataInfo * @throws \Doctrine\ODM\MongoDB\Mapping\MappingException * @throws \Exception */ public function read($className) { $cmi = new ClassMetadataInfo($className); $types = array(TType::BOOL => 'bool', TType::I32 => 'integer', TType::I64 => 'integer', TType::DOUBLE => 'float', TType::UTF7 => 'string', TType::UTF8 => 'string', TType::LST => 'many', TType::STRUCT => 'one', TType::MAP => 'hash'); $spec = $this->loadSpec($className); foreach ($spec as $id => $fieldSpec) { if (!isset($types[$fieldSpec['type']])) { throw new \Exception('Unknown thrift -> doctrine type conversion'); } $type = $types[$fieldSpec['type']]; if ($fieldSpec['type'] == TType::LST) { // list if ($fieldSpec['etype'] == TType::STRUCT) { // list of structs $mapping = array('fieldName' => $fieldSpec['var'], 'name' => $id . '_' . $fieldSpec['var'], 'embedded' => true, 'type' => $type, 'targetDocument' => substr($fieldSpec['elem']['class'], 1)); } else { // list of simple types $mapping = array('fieldName' => $fieldSpec['var'], 'name' => $id . '_' . $fieldSpec['var'], 'type' => 'hash'); } } elseif ($fieldSpec['type'] == TType::STRUCT) { // single struct $mapping = array('fieldName' => $fieldSpec['var'], 'name' => $id . '_' . $fieldSpec['var'], 'embedded' => true, 'type' => $type, 'targetDocument' => substr($fieldSpec['class'], 1)); } else { // simple field $mapping = array('fieldName' => $fieldSpec['var'], 'name' => $id . '_' . $fieldSpec['var'], 'type' => $type); } $cmi->mapField($mapping); } return $cmi; }
/** * @param ColumnInfoInterface $columnInfo * @param ODMMongoDBClassMetadataInfo $metadata * * @return array */ private function getODMTransformerInfo(ColumnInfoInterface $columnInfo, ODMMongoDBClassMetadataInfo $metadata) { $fieldName = $columnInfo->getPropertyPath(); if (in_array($metadata->getTypeOfField($fieldName), ['entity', 'entities'])) { $mapping = $metadata->getFieldMapping($fieldName); $target = $mapping['targetEntity']; if (!$this->doctrine->getRepository($target) instanceof ReferableEntityRepositoryInterface) { return; } return array($this->transformer, array('class' => $target, 'multiple' => 'entities' === $metadata->getTypeOfField($fieldName))); } if (in_array($metadata->getTypeOfField($fieldName), ['one', 'many'])) { $mapping = $metadata->getFieldMapping($fieldName); $target = $mapping['targetDocument']; // TODO Remove this hack switch ($target) { case 'Pim\\Bundle\\CatalogBundle\\Model\\ProductPrice': case 'Pim\\Bundle\\CatalogBundle\\Model\\Metric': return; } if (!$this->doctrine->getRepository($target) instanceof ReferableEntityRepositoryInterface) { return; } return array($this->transformer, array('class' => $mapping['targetDocument'], 'multiple' => 'many' === $metadata->getTypeOfField($fieldName))); } }
/** * Returns an array of fields. Fields can be both column fields and * association fields. * * @param \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo $metadata * * @return array */ private function getFieldsFromMetadata(ClassMetadataInfo $metadata) { $fields = (array) $metadata->getFieldNames(); // Remove the primary key field if it's not managed manually if ($metadata->isIdGeneratorAuto()) { $fields = array_diff($fields, array($metadata->identifier)); } return $fields; }
public function testOwningSideAndInverseSide() { $cm = new ClassMetadataInfo('Documents\\User'); $cm->mapManyReference(array('fieldName' => 'articles', 'inversedBy' => 'user')); $this->assertTrue($cm->fieldMappings['articles']['isOwningSide']); $cm = new ClassMetadataInfo('Documents\\Article'); $cm->mapOneReference(array('fieldName' => 'user', 'mappedBy' => 'articles')); $this->assertTrue($cm->fieldMappings['user']['isInverseSide']); }
protected function setUp() { parent::setUp(); $this->filesystem = new Filesystem(); $this->documentName = ucfirst($this->getName()); $this->tmpDir = sys_get_temp_dir() . '/ismaambrosi'; $this->metadata = new ClassMetadataInfo($this->documentName); $this->metadata->mapField(array('name' => 'id', 'id' => true, 'strategy' => 'auto')); $this->metadata->mapField(array('fieldName' => 'name', 'type' => 'string')); $this->metadata->mapField(array('fieldName' => 'description', 'type' => 'string')); }
function it_configures_the_mappings_of_a_model_that_overrides_an_original_model($configuration, ClassMetadataInfo $metadataInfo, MappingDriver $mappingDriver) { $originalQux1 = __NAMESPACE__ . '\\OriginalQux1'; $originalQux2 = __NAMESPACE__ . '\\OriginalQux2'; $overrideQux1 = __NAMESPACE__ . '\\OverrideQux1'; $overrideQux2 = __NAMESPACE__ . '\\OverrideQux2'; $mappingDriver->getAllClassNames()->willReturn([$originalQux1]); $configuration->getMetadataDriverImpl()->willReturn($mappingDriver); $metadataInfo->getName()->willReturn($overrideQux1); $mappingDriver->loadMetadataForClass($originalQux1, Argument::any())->shouldBeCalled(); $overrides = [['original' => $originalQux1, 'override' => $overrideQux1], ['original' => $originalQux2, 'override' => $overrideQux2]]; $this->configure($metadataInfo, $overrides, $configuration); }
/** * Set the association mappings of a metadata. * * @param ClassMetadataInfo $metadata * @param Configuration $configuration */ protected function setAssociationMappings(ClassMetadataInfo $metadata, Configuration $configuration) { $supportedClasses = $configuration->getMetadataDriverImpl()->getAllClassNames(); foreach (class_parents($metadata->getName()) as $parent) { if (in_array($parent, $supportedClasses)) { $parentMetadata = new MongoClassMetadata($parent); $configuration->getMetadataDriverImpl()->loadMetadataForClass($parent, $parentMetadata); foreach ($parentMetadata->associationMappings as $key => $value) { if ($this->hasRelation($value['association'])) { $metadata->associationMappings[$key] = $value; } } } } }
/** * @param ClassMetadataInfo $metadata * @param $configuration */ private function setAssociationMappings(ClassMetadataInfo $metadata, $configuration) { foreach (class_parents($metadata->getName()) as $parent) { $parentMetadata = new ClassMetadata($parent); if (in_array($parent, $configuration->getMetadataDriverImpl()->getAllClassNames())) { $configuration->getMetadataDriverImpl()->loadMetadataForClass($parent, $parentMetadata); if ($parentMetadata->isMappedSuperclass) { foreach ($parentMetadata->associationMappings as $key => $value) { if ($this->hasRelation($value['association'])) { $metadata->associationMappings[$key] = $value; } } } } } }
/** * Map a field. * * @param array $mapping The mapping information. * @return void */ public function mapField(array $mapping) { $mapping = parent::mapField($mapping); $reflProp = $this->reflClass->getProperty($mapping['fieldName']); $reflProp->setAccessible(true); $this->reflFields[$mapping['fieldName']] = $reflProp; }
public function generateBookDocumentFixture() { $metadata = new ClassMetadataInfo($this->namespace . '\\DocumentGeneratorBook'); $metadata->namespace = $this->namespace; $metadata->customRepositoryClassName = $this->namespace . '\\DocumentGeneratorBookRepository'; $metadata->collection = 'book'; $metadata->mapField(array('fieldName' => 'name', 'type' => 'string')); $metadata->mapField(array('fieldName' => 'status', 'type' => 'string')); $metadata->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true)); $metadata->mapOneReference(array('fieldName' => 'author', 'targetDocument' => 'Doctrine\\ODM\\MongoDB\\Tests\\Tools\\DocumentGeneratorAuthor')); $metadata->mapManyReference(array('fieldName' => 'comments', 'targetDocument' => 'Doctrine\\ODM\\MongoDB\\Tests\\Tools\\DocumentGeneratorComment')); $metadata->addLifecycleCallback('loading', 'postLoad'); $metadata->addLifecycleCallback('willBeRemoved', 'preRemove'); $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); $this->generator->writeDocumentClass($metadata, $this->tmpDir); return $metadata; }
/** * @param \Symfony\Component\HttpKernel\Bundle\BundleInterface $bundle * @param string $document * @param array $fields * @param Boolean $withRepository * @throws \RuntimeException */ public function generate(BundleInterface $bundle, $document, array $fields, $withRepository) { $config = $this->documentManager->getConfiguration(); $config->addDocumentNamespace($bundle->getName(), $bundle->getNamespace() . '\\Document'); $documentClass = $config->getDocumentNamespace($bundle->getName()) . '\\' . $document; $documentPath = $bundle->getPath() . '/Document/' . str_replace('\\', '/', $document) . '.php'; if (file_exists($documentPath)) { throw new \RuntimeException(sprintf('Document "%s" already exists.', $documentClass)); } $class = new ClassMetadataInfo($documentClass); if ($withRepository) { $class->setCustomRepositoryClass($documentClass . 'Repository'); } $class->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true)); $class->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); foreach ($fields as $field) { $class->mapField($field); } $documentGenerator = $this->getDocumentGenerator(); $documentCode = $documentGenerator->generateDocumentClass($class); $this->filesystem->mkdir(dirname($documentPath)); file_put_contents($documentPath, rtrim($documentCode) . PHP_EOL, LOCK_EX); if ($withRepository) { $path = $bundle->getPath() . str_repeat('/..', substr_count(get_class($bundle), '\\')); $this->getRepositoryGenerator()->writeDocumentRepositoryClass($class->customRepositoryClassName, $path); } }
/** * @param ClassMetadataInfo $metadata * @param $configuration */ private function setAssociationMappings(ClassMetadataInfo $metadata, $configuration) { foreach (class_parents($metadata->getName()) as $parent) { if (false === in_array($parent, $configuration->getMetadataDriverImpl()->getAllClassNames())) { continue; } $parentMetadata = new ClassMetadata($parent, $configuration->getNamingStrategy()); // Wakeup Reflection $parentMetadata->wakeupReflection($this->getReflectionService()); // Load Metadata $configuration->getMetadataDriverImpl()->loadMetadataForClass($parent, $parentMetadata); if (false === $this->isResource($parentMetadata)) { continue; } if ($parentMetadata->isMappedSuperclass) { foreach ($parentMetadata->associationMappings as $key => $value) { if ($this->hasRelation($value['association'])) { $metadata->associationMappings[$key] = $value; } } } } }
/** * @param ClassMetadataInfo $class * @param ODM\ShardKey $shardKey * * @throws MappingException */ private function setShardKey(ClassMetadataInfo $class, ODM\ShardKey $shardKey) { $options = array(); $allowed = array('unique', 'numInitialChunks'); foreach ($allowed as $name) { if (isset($shardKey->{$name})) { $options[$name] = $shardKey->{$name}; } } $class->setShardKey($shardKey->keys, $options); }
/** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadataInfo $class) { $element = $this->getElement($className); if ( ! $element) { return; } $element['type'] = isset($element['type']) ? $element['type'] : 'document'; if (isset($element['db'])) { $class->setDatabase($element['db']); } if (isset($element['collection'])) { $class->setCollection($element['collection']); } if ($element['type'] == 'document') { if (isset($element['repositoryClass'])) { $class->setCustomRepositoryClass($element['repositoryClass']); } } elseif ($element['type'] === 'mappedSuperclass') { $class->isMappedSuperclass = true; } elseif ($element['type'] === 'embeddedDocument') { $class->isEmbeddedDocument = true; } if (isset($element['indexes'])) { foreach($element['indexes'] as $index) { $class->addIndex($index['keys'], isset($index['options']) ? $index['options'] : array()); } } if (isset($element['inheritanceType'])) { $class->setInheritanceType(constant('Doctrine\ODM\MongoDB\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType']))); } if (isset($element['discriminatorField'])) { $discrField = $element['discriminatorField']; $class->setDiscriminatorField(array( 'name' => $discrField['name'], 'fieldName' => $discrField['fieldName'] )); } if (isset($element['discriminatorMap'])) { $class->setDiscriminatorMap($element['discriminatorMap']); } if (isset($element['changeTrackingPolicy'])) { $class->setChangeTrackingPolicy(constant('Doctrine\ODM\MongoDB\Mapping\ClassMetadata::CHANGETRACKING_' . strtoupper($element['changeTrackingPolicy']))); } if (isset($element['fields'])) { foreach ($element['fields'] as $fieldName => $mapping) { if (is_string($mapping)) { $type = $mapping; $mapping = array(); $mapping['type'] = $type; } if ( ! isset($mapping['fieldName'])) { $mapping['fieldName'] = $fieldName; } if (isset($mapping['type']) && $mapping['type'] === 'collection') { $mapping['strategy'] = isset($mapping['strategy']) ? $mapping['strategy'] : 'pushAll'; } $this->addFieldMapping($class, $mapping); } } if (isset($element['embedOne'])) { foreach ($element['embedOne'] as $fieldName => $embed) { $this->addMappingFromEmbed($class, $fieldName, $embed, 'one'); } } if (isset($element['embedMany'])) { foreach ($element['embedMany'] as $fieldName => $embed) { $this->addMappingFromEmbed($class, $fieldName, $embed, 'many'); } } if (isset($element['referenceOne'])) { foreach ($element['referenceOne'] as $fieldName => $reference) { $this->addMappingFromReference($class, $fieldName, $reference, 'one'); } } if (isset($element['referenceMany'])) { foreach ($element['referenceMany'] as $fieldName => $reference) { $this->addMappingFromReference($class, $fieldName, $reference, 'many'); } } if (isset($element['lifecycleCallbacks'])) { foreach ($element['lifecycleCallbacks'] as $type => $methods) { foreach ($methods as $method) { $class->addLifecycleCallback($method, constant('Doctrine\ODM\MongoDB\Events::' . $type)); } } } }
private function addFieldMapping(ClassMetadataInfo $class, $mapping) { if (isset($mapping['name'])) { $name = $mapping['name']; } elseif (isset($mapping['fieldName'])) { $name = $mapping['fieldName']; } else { throw new \InvalidArgumentException('Cannot infer a MongoDB name from the mapping'); } $class->mapField($mapping); if (!(isset($mapping['index']) || isset($mapping['unique']) || isset($mapping['sparse']))) { return; } // Multiple index specifications in one field mapping is ambiguous if ((isset($mapping['index']) && is_array($mapping['index'])) + (isset($mapping['unique']) && is_array($mapping['unique'])) + (isset($mapping['sparse']) && is_array($mapping['sparse'])) > 1) { throw new \InvalidArgumentException('Multiple index specifications found among index, unique, and/or sparse fields'); } // Index this field if either "index", "unique", or "sparse" are set $keys = array($name => 'asc'); /* The "order" option is only used in the index specification and should * not be passed along as an index option. */ if (isset($mapping['index']['order'])) { $keys[$name] = $mapping['index']['order']; unset($mapping['index']['order']); } elseif (isset($mapping['unique']['order'])) { $keys[$name] = $mapping['unique']['order']; unset($mapping['unique']['order']); } elseif (isset($mapping['sparse']['order'])) { $keys[$name] = $mapping['sparse']['order']; unset($mapping['sparse']['order']); } /* Initialize $options from any array value among index, unique, and * sparse. Any boolean values for unique or sparse should be merged into * the options afterwards to ensure consistent parsing. */ $options = array(); $unique = null; $sparse = null; if (isset($mapping['index']) && is_array($mapping['index'])) { $options = $mapping['index']; } if (isset($mapping['unique'])) { if (is_array($mapping['unique'])) { $options = $mapping['unique'] + array('unique' => true); } else { $unique = (bool) $mapping['unique']; } } if (isset($mapping['sparse'])) { if (is_array($mapping['sparse'])) { $options = $mapping['sparse'] + array('sparse' => true); } else { $sparse = (bool) $mapping['sparse']; } } if (isset($unique)) { $options['unique'] = $unique; } if (isset($sparse)) { $options['sparse'] = $sparse; } $class->addIndex($keys, $options); }
private function addIndex(ClassMetadataInfo $class, \SimpleXmlElement $xmlIndex) { $attributes = $xmlIndex->attributes(); $keys = array(); foreach ($xmlIndex->{'key'} as $key) { $keys[(string) $key['name']] = isset($key['order']) ? (string) $key['order'] : 'asc'; } $options = array(); if (isset($attributes['background'])) { $options['background'] = 'true' === (string) $attributes['background']; } if (isset($attributes['drop-dups'])) { $options['dropDups'] = 'true' === (string) $attributes['drop-dups']; } if (isset($attributes['name'])) { $options['name'] = (string) $attributes['name']; } if (isset($attributes['safe'])) { $options['safe'] = 'true' === (string) $attributes['safe']; } if (isset($attributes['sparse'])) { $options['sparse'] = 'true' === (string) $attributes['sparse']; } if (isset($attributes['unique'])) { $options['unique'] = 'true' === (string) $attributes['unique']; } if (isset($xmlIndex->{'option'})) { foreach ($xmlIndex->{'option'} as $option) { $value = (string) $option['value']; if ($value === 'true') { $value = true; } elseif ($value === 'false') { $value = false; } elseif (is_numeric($value)) { $value = preg_match('/^[-]?\\d+$/', $value) ? (int) $value : (double) $value; } $options[(string) $option['name']] = $value; } } $class->addIndex($keys, $options); }
/** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadataInfo $class) { $reflClass = $class->getReflectionClass(); $classAnnotations = $this->reader->getClassAnnotations($reflClass); if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Document'])) { $documentAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Document']; } elseif (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\MappedSuperclass'])) { $documentAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\MappedSuperclass']; $class->isMappedSuperclass = true; } elseif (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\EmbeddedDocument'])) { $documentAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\EmbeddedDocument']; $class->isEmbeddedDocument = true; } else { throw MongoDBException::classIsNotAValidDocument($className); } if (isset($documentAnnot->db)) { $class->setDatabase($documentAnnot->db); } if (isset($documentAnnot->collection)) { $class->setCollection($documentAnnot->collection); } if (isset($documentAnnot->repositoryClass)) { $class->setCustomRepositoryClass($documentAnnot->repositoryClass); } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Indexes'])) { $indexes = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Indexes']->value; $indexes = is_array($indexes) ? $indexes : array($indexes); foreach ($indexes as $index) { $this->addIndex($class, $index); } } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Index'])) { $index = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Index']; $this->addIndex($class, $index); } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\UniqueIndex'])) { $index = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\UniqueIndex']; $this->addIndex($class, $index); } if (isset($documentAnnot->indexes)) { foreach ($documentAnnot->indexes as $index) { $this->addIndex($class, $index); } } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\InheritanceType'])) { $inheritanceTypeAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\InheritanceType']; $class->setInheritanceType(constant('Doctrine\\ODM\\MongoDB\\Mapping\\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value)); } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\DiscriminatorField'])) { $discrFieldAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\DiscriminatorField']; $class->setDiscriminatorField(array('fieldName' => $discrFieldAnnot->fieldName)); } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\DiscriminatorMap'])) { $discrMapAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\DiscriminatorMap']; $class->setDiscriminatorMap($discrMapAnnot->value); } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\DiscriminatorValue'])) { $discrValueAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\DiscriminatorValue']; $class->setDiscriminatorValue($discrValueAnnot->value); } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\ChangeTrackingPolicy'])) { $changeTrackingAnnot = $classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\ChangeTrackingPolicy']; $class->setChangeTrackingPolicy(constant('Doctrine\\ODM\\MongoDB\\Mapping\\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value)); } $methods = $reflClass->getMethods(); foreach ($reflClass->getProperties() as $property) { if ($class->isMappedSuperclass && !$property->isPrivate() || $class->isInheritedField($property->name)) { continue; } $mapping = array(); $mapping['fieldName'] = $property->getName(); if ($alsoLoad = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\AlsoLoad')) { $mapping['alsoLoadFields'] = (array) $alsoLoad->value; } if ($notSaved = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\NotSaved')) { $mapping['notSaved'] = true; } if ($versionAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Version')) { $mapping['version'] = true; } if ($versionAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Lock')) { $mapping['lock'] = true; } $indexes = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Indexes'); $indexes = $indexes ? $indexes : array(); if ($index = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\Index')) { $indexes[] = $index; } if ($index = $this->reader->getPropertyAnnotation($property, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\UniqueIndex')) { $indexes[] = $index; } foreach ($this->reader->getPropertyAnnotations($property) as $fieldAnnot) { if ($fieldAnnot instanceof \Doctrine\ODM\MongoDB\Mapping\Annotations\AbstractField) { $mapping = array_merge($mapping, (array) $fieldAnnot); $class->mapField($mapping); } } if ($indexes) { foreach ($indexes as $index) { $name = isset($mapping['name']) ? $mapping['name'] : $mapping['fieldName']; $keys = array(); $keys[$name] = 'asc'; if (isset($index->order)) { $keys[$name] = $index->order; } $this->addIndex($class, $index, $keys); } } } foreach ($methods as $method) { if ($method->isPublic()) { if ($alsoLoad = $this->reader->getMethodAnnotation($method, 'Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\AlsoLoad')) { $fields = (array) $alsoLoad->value; foreach ($fields as $value) { $class->alsoLoadMethods[$value] = $method->getName(); } } } } if (isset($classAnnotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\HasLifecycleCallbacks'])) { foreach ($methods as $method) { if ($method->isPublic()) { $annotations = $this->reader->getMethodAnnotations($method); if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PrePersist'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::prePersist); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PostPersist'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::postPersist); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PreUpdate'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::preUpdate); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PostUpdate'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::postUpdate); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PreRemove'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::preRemove); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PostRemove'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::postRemove); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PreLoad'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::preLoad); } if (isset($annotations['Doctrine\\ODM\\MongoDB\\Mapping\\Annotations\\PostLoad'])) { $class->addLifecycleCallback($method->getName(), \Doctrine\ODM\MongoDB\Events::postLoad); } } } } }
private function setShardKey(ClassMetadataInfo $class, \SimpleXmlElement $xmlShardkey) { $attributes = $xmlShardkey->attributes(); $keys = array(); $options = array(); foreach ($xmlShardkey->{'key'} as $key) { $keys[(string) $key['name']] = isset($key['order']) ? (string) $key['order'] : 'asc'; } if (isset($attributes['unique'])) { $options['unique'] = 'true' === (string) $attributes['unique']; } if (isset($attributes['numInitialChunks'])) { $options['numInitialChunks'] = (int) $attributes['numInitialChunks']; } if (isset($xmlShardkey->{'option'})) { foreach ($xmlShardkey->{'option'} as $option) { $value = (string) $option['value']; if ($value === 'true') { $value = true; } elseif ($value === 'false') { $value = false; } elseif (is_numeric($value)) { $value = preg_match('/^[-]?\\d+$/', $value) ? (int) $value : (double) $value; } $options[(string) $option['name']] = $value; } } $class->setShardKey($keys, $options); }
/** * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException * @expectedExceptionMessage Cascade on Doctrine\ODM\MongoDB\Tests\Mapping\EmbedWithCascadeTest::address is not allowed. */ public function testEmbedWithCascadeThrowsMappingException() { $class = new ClassMetadataInfo(__NAMESPACE__ . '\\EmbedWithCascadeTest'); $class->mapOneEmbedded(array('fieldName' => 'address', 'targetDocument' => 'Documents\\Address', 'cascade' => 'all')); }
private function addFieldMapping(ClassMetadataInfo $class, $mapping) { $keys = null; $name = isset($mapping['name']) ? $mapping['name'] : $mapping['fieldName']; if (isset($mapping['index'])) { $keys = array($name => isset($mapping['index']['order']) ? $mapping['index']['order'] : 'asc'); } if (isset($mapping['unique'])) { $keys = array($name => isset($mapping['unique']['order']) ? $mapping['unique']['order'] : 'asc'); } if ($keys !== null) { $options = array(); if (isset($mapping['index'])) { $options = $mapping['index']; } elseif (isset($mapping['unique'])) { $options = $mapping['unique']; $options['unique'] = true; } $class->addIndex($keys, $options); } $class->mapField($mapping); }
private function addIndex(ClassMetadataInfo $class, SimpleXmlElement $xmlIndex) { $attributes = $xmlIndex->attributes(); $options = array(); if (isset($attributes['name'])) { $options['name'] = (string) $attributes['name']; } if (isset($attributes['drop-dups'])) { $options['dropDups'] = ((string) $attributes['dropDups'] == 'false') ? false : true; } if (isset($attributes['background'])) { $options['background'] = ((string) $attributes['background'] == 'false') ? false : true; } if (isset($attributes['safe'])) { $options['safe'] = ((string) $attributes['safe'] == 'false') ? false : true; } if (isset($attributes['unique'])) { $options['unique'] = ((string) $attributes['unique'] == 'false') ? false : true; } $index = array( 'keys' => array(), 'options' => $options ); foreach ($xmlIndex->{'key'} as $key) { $index['keys'][(string) $key['name']] = isset($key['order']) ? (string) $key['order'] : 'asc'; } if (isset($xmlIndex->{'option'})) { foreach ($xmlIndex->{'option'} as $option) { $value = (string) $option['value']; $value = $value === 'true' ? true : $value; $value = $value === 'false' ? false : $value; $index['options'][(string) $option['name']] = $value; } } $class->addIndex($index['keys'], $index['options']); }
/** * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException * @expectedExceptionMessage atomicSet collection strategy can be used only in top level document, used in stdClass::many */ public function testAtomicCollectionUpdateUsageInEmbeddedDocument() { $cm = new ClassMetadataInfo('stdClass'); $cm->isEmbeddedDocument = true; $cm->mapField(array('fieldName' => 'many', 'reference' => true, 'type' => 'many', 'strategy' => 'atomicSet')); }
private function completeIdGeneratorMapping(ClassMetadataInfo $class) { $idGenOptions = $class->generatorOptions; switch ($class->generatorType) { case ClassMetadata::GENERATOR_TYPE_AUTO: $class->setIdGenerator(new \Doctrine\ODM\MongoDB\Id\AutoGenerator($class)); break; case ClassMetadata::GENERATOR_TYPE_INCREMENT: $incrementGenerator = new \Doctrine\ODM\MongoDB\Id\IncrementGenerator($class); if (isset($idGenOptions['key'])) { $incrementGenerator->setKey($idGenOptions['key']); } if (isset($idGenOptions['collection'])) { $incrementGenerator->setCollection($idGenOptions['collection']); } $class->setIdGenerator($incrementGenerator); break; case ClassMetadata::GENERATOR_TYPE_UUID: $uuidGenerator = new \Doctrine\ODM\MongoDB\Id\UuidGenerator($class); $uuidGenerator->setSalt(isset($idGenOptions['salt']) ? $idGenOptions['salt'] : php_uname('n')); $class->setIdGenerator($uuidGenerator); break; case ClassMetadata::GENERATOR_TYPE_ALNUM: $alnumGenerator = new \Doctrine\ODM\MongoDB\Id\AlnumGenerator($class); if (isset($idGenOptions['pad'])) { $alnumGenerator->setPad($idGenOptions['pad']); } if (isset($idGenOptions['chars'])) { $alnumGenerator->setChars($idGenOptions['chars']); } elseif (isset($idGenOptions['awkwardSafe'])) { $alnumGenerator->setAwkwardSafeMode($idGenOptions['awkwardSafe']); } $class->setIdGenerator($alnumGenerator); break; case ClassMetadata::GENERATOR_TYPE_NONE: break; default: throw new MappingException("Unknown generator type: " . $class->generatorType); } }
/** * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException * @expectedExceptionMessage You must not change identifier field's type: stdClass::id */ public function testIdFieldsTypeMustNotBeOverrriden() { $cm = new ClassMetadataInfo('stdClass'); $cm->setIdentifier('id'); $cm->mapField(array('fieldName' => 'id', 'type' => 'string')); }
/** * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException * @expectedExceptionMessage Target document must be specified for simple reference: stdClass::assoc */ public function testSimpleReferenceRequiresTargetDocument() { $cm = new ClassMetadataInfo('stdClass'); $cm->mapField(array('fieldName' => 'assoc', 'reference' => true, 'type' => 'one', 'simple' => true)); }
/** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadataInfo $class) { $reflClass = $class->getReflectionClass(); $documentAnnots = array(); foreach ($this->reader->getClassAnnotations($reflClass) as $annot) { foreach (self::$documentAnnotationClasses as $i => $annotClass) { if ($annot instanceof $annotClass) { $documentAnnots[$i] = $annot; goto next_annotation; } } // non-document class annotations if ($annot instanceof ODM\AbstractIndex) { $this->addIndex($class, $annot); } if ($annot instanceof ODM\Indexes) { foreach (is_array($annot->value) ? $annot->value : array($annot->value) as $index) { $this->addIndex($class, $index); } } elseif ($annot instanceof ODM\InheritanceType) { $class->setInheritanceType(constant('Doctrine\\ODM\\MongoDB\\Mapping\\ClassMetadata::INHERITANCE_TYPE_' . $annot->value)); } elseif ($annot instanceof ODM\DiscriminatorField) { $class->setDiscriminatorField(array('fieldName' => $annot->fieldName)); } elseif ($annot instanceof ODM\DiscriminatorMap) { $class->setDiscriminatorMap($annot->value); } elseif ($annot instanceof ODM\DiscriminatorValue) { $class->setDiscriminatorValue($annot->value); } elseif ($annot instanceof ODM\ChangeTrackingPolicy) { $class->setChangeTrackingPolicy(constant('Doctrine\\ODM\\MongoDB\\Mapping\\ClassMetadata::CHANGETRACKING_' . $annot->value)); } next_annotation: } if (!$documentAnnots) { throw MongoDBException::classIsNotAValidDocument($className); } // find the winning document annotation ksort($documentAnnots); $documentAnnot = reset($documentAnnots); if ($documentAnnot instanceof ODM\MappedSuperclass) { $class->isMappedSuperclass = true; } elseif ($documentAnnot instanceof ODM\EmbeddedDocument) { $class->isEmbeddedDocument = true; } if (isset($documentAnnot->db)) { $class->setDatabase($documentAnnot->db); } if (isset($documentAnnot->collection)) { $class->setCollection($documentAnnot->collection); } if (isset($documentAnnot->repositoryClass)) { $class->setCustomRepositoryClass($documentAnnot->repositoryClass); } if (isset($documentAnnot->indexes)) { foreach ($documentAnnot->indexes as $index) { $this->addIndex($class, $index); } } foreach ($reflClass->getProperties() as $property) { if ($class->isMappedSuperclass && !$property->isPrivate() || $class->isInheritedField($property->name)) { continue; } $indexes = array(); $mapping = array('fieldName' => $property->getName()); $fieldAnnot = null; foreach ($this->reader->getPropertyAnnotations($property) as $annot) { if ($annot instanceof ODM\AbstractField) { $fieldAnnot = $annot; } if ($annot instanceof ODM\AbstractIndex) { $indexes[] = $annot; } if ($annot instanceof ODM\Indexes) { foreach (is_array($annot->value) ? $annot->value : array($annot->value) as $index) { $indexes[] = $index; } } elseif ($annot instanceof ODM\AlsoLoad) { $mapping['alsoLoadFields'] = (array) $annot->value; } elseif ($annot instanceof ODM\Version) { $mapping['version'] = true; } elseif ($annot instanceof ODM\Lock) { $mapping['lock'] = true; } } if ($fieldAnnot) { $mapping = array_replace($mapping, (array) $fieldAnnot); $class->mapField($mapping); } if ($indexes) { foreach ($indexes as $index) { $name = isset($mapping['name']) ? $mapping['name'] : $mapping['fieldName']; $keys = array($name => $index->order ?: 'asc'); $this->addIndex($class, $index, $keys); } } } foreach ($reflClass->getMethods() as $method) { if ($method->isPublic()) { foreach ($this->reader->getMethodAnnotations($method) as $annot) { if ($annot instanceof ODM\AlsoLoad) { foreach (is_array($annot->value) ? $annot->value : array($annot->value) as $field) { $class->alsoLoadMethods[$field] = $method->getName(); } } elseif ($annot instanceof ODM\PrePersist) { $class->addLifecycleCallback($method->getName(), Events::prePersist); } elseif ($annot instanceof ODM\PostPersist) { $class->addLifecycleCallback($method->getName(), Events::postPersist); } elseif ($annot instanceof ODM\PreUpdate) { $class->addLifecycleCallback($method->getName(), Events::preUpdate); } elseif ($annot instanceof ODM\PostUpdate) { $class->addLifecycleCallback($method->getName(), Events::postUpdate); } elseif ($annot instanceof ODM\PreRemove) { $class->addLifecycleCallback($method->getName(), Events::preRemove); } elseif ($annot instanceof ODM\PostRemove) { $class->addLifecycleCallback($method->getName(), Events::postRemove); } elseif ($annot instanceof ODM\PreLoad) { $class->addLifecycleCallback($method->getName(), Events::preLoad); } elseif ($annot instanceof ODM\PostLoad) { $class->addLifecycleCallback($method->getName(), Events::postLoad); } } } } }
private function addFieldMapping(ClassMetadataInfo $class, $mapping) { $keys = null; if (isset($mapping['name'])) { $name = $mapping['name']; } elseif (isset($mapping['fieldName'])) { $name = $mapping['fieldName']; } else { throw new \InvalidArgumentException('Cannot infer a MongoDB name from the mapping'); } if (isset($mapping['index'])) { $keys = array($name => isset($mapping['index']['order']) ? $mapping['index']['order'] : 'asc'); } if (isset($mapping['unique'])) { $keys = array($name => isset($mapping['unique']['order']) ? $mapping['unique']['order'] : 'asc'); } if ($keys !== null) { $options = array(); if (isset($mapping['index'])) { $options = $mapping['index']; } elseif (isset($mapping['unique'])) { $options = $mapping['unique']; $options['unique'] = true; } elseif (isset($mapping['sparse'])) { $options = $mapping['sparse']; $options['sparse'] = true; } $class->addIndex($keys, $options); } $class->mapField($mapping); }
private function completeIdGeneratorMapping(ClassMetadataInfo $class) { $idGenOptions = $class->generatorOptions; switch ($class->generatorType) { case ClassMetadata::GENERATOR_TYPE_AUTO: $class->setIdGenerator(new \Doctrine\ODM\MongoDB\Id\AutoGenerator()); break; case ClassMetadata::GENERATOR_TYPE_INCREMENT: $incrementGenerator = new \Doctrine\ODM\MongoDB\Id\IncrementGenerator(); if (isset($idGenOptions['key'])) { $incrementGenerator->setKey($idGenOptions['key']); } if (isset($idGenOptions['collection'])) { $incrementGenerator->setCollection($idGenOptions['collection']); } $class->setIdGenerator($incrementGenerator); break; case ClassMetadata::GENERATOR_TYPE_UUID: $uuidGenerator = new \Doctrine\ODM\MongoDB\Id\UuidGenerator(); isset($idGenOptions['salt']) && $uuidGenerator->setSalt($idGenOptions['salt']); $class->setIdGenerator($uuidGenerator); break; case ClassMetadata::GENERATOR_TYPE_ALNUM: $alnumGenerator = new \Doctrine\ODM\MongoDB\Id\AlnumGenerator(); if (isset($idGenOptions['pad'])) { $alnumGenerator->setPad($idGenOptions['pad']); } if (isset($idGenOptions['chars'])) { $alnumGenerator->setChars($idGenOptions['chars']); } elseif (isset($idGenOptions['awkwardSafe'])) { $alnumGenerator->setAwkwardSafeMode($idGenOptions['awkwardSafe']); } $class->setIdGenerator($alnumGenerator); break; case ClassMetadata::GENERATOR_TYPE_CUSTOM: if (empty($idGenOptions['class'])) { throw MappingException::missingIdGeneratorClass($class->name); } $customGenerator = new $idGenOptions['class'](); unset($idGenOptions['class']); if (!$customGenerator instanceof \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator) { throw MappingException::classIsNotAValidGenerator(get_class($customGenerator)); } $methods = get_class_methods($customGenerator); foreach ($idGenOptions as $name => $value) { $method = 'set' . ucfirst($name); if (!in_array($method, $methods)) { throw MappingException::missingGeneratorSetter(get_class($customGenerator), $name); } $customGenerator->{$method}($value); } $class->setIdGenerator($customGenerator); break; case ClassMetadata::GENERATOR_TYPE_NONE: break; default: throw new MappingException("Unknown generator type: " . $class->generatorType); } }
private function addIndex(ClassMetadataInfo $class, $index, array $keys = array()) { $keys = array_merge($keys, $index->keys); $options = array(); $allowed = array('name', 'dropDups', 'background', 'safe', 'unique', 'sparse', 'expireAfterSeconds'); foreach ($allowed as $name) { if (isset($index->{$name})) { $options[$name] = $index->{$name}; } } $options = array_merge($options, $index->options); $class->addIndex($keys, $options); }
/** * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException * @expectedExceptionMessage ReferenceMany's sort can not be used with addToSet and pushAll strategies, pushAll used in stdClass::ref */ public function testReferenceManySortMustNotBeUsedWithNonSetCollectionStrategy() { $cm = new ClassMetadataInfo('stdClass'); $cm->mapField(array('fieldName' => 'ref', 'reference' => true, 'strategy' => 'pushAll', 'type' => 'many', 'sort' => array('foo' => 1))); }