diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php index 28a985162c..a92095d1f2 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php @@ -1165,23 +1165,6 @@ public function mapField(array $mapping) } } unset($this->generatorOptions['type']); - } elseif (!isset($mapping['embedded']) && !isset($mapping['reference']) && isset($mapping['type'])) { - switch ($mapping['type']) { - case 'int': - case 'float': - $allowedStrategies = [self::STORAGE_STRATEGY_SET, self::STORAGE_STRATEGY_INCREMENT]; - break; - default: - $allowedStrategies = [self::STORAGE_STRATEGY_SET]; - } - - if (isset($mapping['strategy'])) { - if (! in_array($mapping['strategy'], $allowedStrategies)) { - throw MappingException::invalidStorageStrategy($this->name, $mapping['fieldName'], $mapping['type'], $mapping['strategy']); - } - } else { - $mapping['strategy'] = self::STORAGE_STRATEGY_SET; - } } if ( ! isset($mapping['nullable'])) { @@ -1251,10 +1234,7 @@ public function mapField(array $mapping) } } - if (isset($mapping['reference']) && $mapping['type'] === 'many' && $mapping['isOwningSide'] - && ! empty($mapping['sort']) && ! CollectionHelper::usesSet($mapping['strategy'])) { - throw MappingException::referenceManySortMustNotBeUsedWithNonSetCollectionStrategy($this->name, $mapping['fieldName'], $mapping['strategy']); - } + $this->applyStorageStrategy($mapping); $this->fieldMappings[$mapping['fieldName']] = $mapping; if (isset($mapping['association'])) { @@ -1264,6 +1244,55 @@ public function mapField(array $mapping) return $mapping; } + /** + * Validates the storage strategy of a mapping for consistency + * @param array $mapping + * @throws \Doctrine\ODM\MongoDB\Mapping\MappingException + */ + private function applyStorageStrategy(array &$mapping) + { + if (! isset($mapping['type']) || isset($mapping['id'])) { + return; + } + + switch (true) { + case $mapping['type'] == 'int': + case $mapping['type'] == 'float': + $defaultStrategy = self::STORAGE_STRATEGY_SET; + $allowedStrategies = [self::STORAGE_STRATEGY_SET, self::STORAGE_STRATEGY_INCREMENT]; + break; + + case $mapping['type'] == 'many': + $defaultStrategy = CollectionHelper::DEFAULT_STRATEGY; + $allowedStrategies = [ + self::STORAGE_STRATEGY_PUSH_ALL, + self::STORAGE_STRATEGY_ADD_TO_SET, + self::STORAGE_STRATEGY_SET, + self::STORAGE_STRATEGY_SET_ARRAY, + self::STORAGE_STRATEGY_ATOMIC_SET, + self::STORAGE_STRATEGY_ATOMIC_SET_ARRAY, + ]; + break; + + default: + $defaultStrategy = self::STORAGE_STRATEGY_SET; + $allowedStrategies = [self::STORAGE_STRATEGY_SET]; + } + + if (! isset($mapping['strategy'])) { + $mapping['strategy'] = $defaultStrategy; + } + + if (! in_array($mapping['strategy'], $allowedStrategies)) { + throw MappingException::invalidStorageStrategy($this->name, $mapping['fieldName'], $mapping['type'], $mapping['strategy']); + } + + if (isset($mapping['reference']) && $mapping['type'] === 'many' && $mapping['isOwningSide'] + && ! empty($mapping['sort']) && ! CollectionHelper::usesSet($mapping['strategy'])) { + throw MappingException::referenceManySortMustNotBeUsedWithNonSetCollectionStrategy($this->name, $mapping['fieldName'], $mapping['strategy']); + } + } + /** * Map a MongoGridFSFile. * diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php index e91a444072..6e017fa015 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php @@ -236,12 +236,13 @@ private function addFieldMapping(ClassMetadataInfo $class, $mapping) private function addEmbedMapping(ClassMetadataInfo $class, $embed, $type) { $attributes = $embed->attributes(); + $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'type' => $type, 'embedded' => true, 'targetDocument' => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null, 'name' => (string) $attributes['field'], - 'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : CollectionHelper::DEFAULT_STRATEGY, + 'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : $defaultStrategy, ); if (isset($attributes['fieldName'])) { $mapping['fieldName'] = (string) $attributes['fieldName']; @@ -275,6 +276,7 @@ private function addReferenceMapping(ClassMetadataInfo $class, $reference, $type $cascade = current($cascade) ?: next($cascade); } $attributes = $reference->attributes(); + $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'cascade' => $cascade, 'orphanRemoval' => isset($attributes['orphan-removal']) ? ('true' === (string) $attributes['orphan-removal']) : false, @@ -283,7 +285,7 @@ private function addReferenceMapping(ClassMetadataInfo $class, $reference, $type 'simple' => isset($attributes['simple']) ? ('true' === (string) $attributes['simple']) : false, 'targetDocument' => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null, 'name' => (string) $attributes['field'], - 'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : CollectionHelper::DEFAULT_STRATEGY, + 'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : $defaultStrategy, 'inversedBy' => isset($attributes['inversed-by']) ? (string) $attributes['inversed-by'] : null, 'mappedBy' => isset($attributes['mapped-by']) ? (string) $attributes['mapped-by'] : null, 'repositoryMethod' => isset($attributes['repository-method']) ? (string) $attributes['repository-method'] : null, diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php index 154c817881..8792e854fb 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php @@ -233,12 +233,13 @@ private function addFieldMapping(ClassMetadataInfo $class, $mapping) private function addMappingFromEmbed(ClassMetadataInfo $class, $fieldName, $embed, $type) { + $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'type' => $type, 'embedded' => true, 'targetDocument' => isset($embed['targetDocument']) ? $embed['targetDocument'] : null, 'fieldName' => $fieldName, - 'strategy' => isset($embed['strategy']) ? (string) $embed['strategy'] : CollectionHelper::DEFAULT_STRATEGY, + 'strategy' => isset($embed['strategy']) ? (string) $embed['strategy'] : $defaultStrategy, ); if (isset($embed['name'])) { $mapping['name'] = $embed['name']; @@ -257,6 +258,7 @@ private function addMappingFromEmbed(ClassMetadataInfo $class, $fieldName, $embe private function addMappingFromReference(ClassMetadataInfo $class, $fieldName, $reference, $type) { + $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'cascade' => isset($reference['cascade']) ? $reference['cascade'] : null, 'orphanRemoval' => isset($reference['orphanRemoval']) ? $reference['orphanRemoval'] : false, @@ -265,7 +267,7 @@ private function addMappingFromReference(ClassMetadataInfo $class, $fieldName, $ 'simple' => isset($reference['simple']) ? (boolean) $reference['simple'] : false, 'targetDocument' => isset($reference['targetDocument']) ? $reference['targetDocument'] : null, 'fieldName' => $fieldName, - 'strategy' => isset($reference['strategy']) ? (string) $reference['strategy'] : CollectionHelper::DEFAULT_STRATEGY, + 'strategy' => isset($reference['strategy']) ? (string) $reference['strategy'] : $defaultStrategy, 'inversedBy' => isset($reference['inversedBy']) ? (string) $reference['inversedBy'] : null, 'mappedBy' => isset($reference['mappedBy']) ? (string) $reference['mappedBy'] : null, 'repositoryMethod' => isset($reference['repositoryMethod']) ? (string) $reference['repositoryMethod'] : null, diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php index 763e13a2d6..ae3aac42ed 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php @@ -1043,7 +1043,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $ return array($fieldName, $value); } - if (isset($mapping['strategy']) && CollectionHelper::isHash($mapping['strategy']) + if ($mapping['type'] == 'many' && isset($mapping['strategy']) && CollectionHelper::isHash($mapping['strategy']) && isset($e[2])) { $objectProperty = $e[2]; $objectPropertyPrefix = $e[1] . '.'; diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php index 41593a3712..5766b06997 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php @@ -114,7 +114,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['address']); $this->assertEquals(array( @@ -152,7 +152,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, 'inversedBy' => null, 'mappedBy' => null, 'repositoryMethod' => null, @@ -178,7 +178,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, 'inversedBy' => null, 'mappedBy' => null, 'repositoryMethod' => null,