From b796f507555625c7b1ace9fb1b1e6d08dc9cd25d Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Tue, 8 Jan 2019 07:52:58 +0100 Subject: [PATCH] Deprecate and alias ClassMetadataInfo (#1733) --- UPGRADE-1.3.md | 7 + .../MongoDB/Aggregation/Stage/GraphLookup.php | 7 +- .../ODM/MongoDB/Aggregation/Stage/Lookup.php | 13 +- lib/Doctrine/ODM/MongoDB/DocumentManager.php | 16 +- .../Mapping/Annotations/ReferenceMany.php | 4 +- .../Mapping/Annotations/ReferenceOne.php | 4 +- .../ODM/MongoDB/Mapping/ClassMetadata.php | 2223 +++++++++++++++- .../MongoDB/Mapping/ClassMetadataFactory.php | 2 +- .../ODM/MongoDB/Mapping/ClassMetadataInfo.php | 2230 +---------------- .../Mapping/Driver/AnnotationDriver.php | 11 +- .../ODM/MongoDB/Mapping/Driver/XmlDriver.php | 19 +- .../ODM/MongoDB/Mapping/Driver/YamlDriver.php | 17 +- .../Persisters/CollectionPersister.php | 18 +- .../MongoDB/Persisters/DocumentPersister.php | 25 +- .../MongoDB/Persisters/PersistenceBuilder.php | 9 +- .../ODM/MongoDB/Proxy/ProxyFactory.php | 5 +- lib/Doctrine/ODM/MongoDB/Query/Builder.php | 6 +- lib/Doctrine/ODM/MongoDB/Query/Expr.php | 21 +- .../ODM/MongoDB/Query/ReferencePrimer.php | 9 +- lib/Doctrine/ODM/MongoDB/SchemaManager.php | 5 +- .../GeneratePersistentCollectionsCommand.php | 1 - .../DisconnectedClassMetadataFactory.php | 4 +- .../ODM/MongoDB/Tools/DocumentGenerator.php | 136 +- lib/Doctrine/ODM/MongoDB/UnitOfWork.php | 2 +- .../ODM/MongoDB/Utility/CollectionHelper.php | 18 +- .../ODM/MongoDB/Tests/DocumentManagerTest.php | 42 +- .../Functional/CustomCollectionsTest.php | 4 +- .../Functional/NestedCollectionsTest.php | 14 +- .../Tests/Functional/ReferencePrimerTest.php | 3 +- .../Tests/Functional/Ticket/GH1275Test.php | 14 +- .../Tests/Mapping/ClassMetadataInfoTest.php | 533 ---- .../Tests/Mapping/ClassMetadataTest.php | 552 +++- .../Mapping/Driver/AbstractDriverTest.php | 37 +- .../Tests/Mapping/Driver/XmlDriverTest.php | 7 +- .../Tests/Mapping/XmlMappingDriverTest.php | 11 +- .../ODM/MongoDB/Tests/Query/ExprTest.php | 8 +- .../Tests/Tools/DocumentGeneratorTest.php | 30 +- tests/Documents/Article.php | 2 + tests/Documents/User.php | 2 + 39 files changed, 3043 insertions(+), 3028 deletions(-) delete mode 100644 tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataInfoTest.php diff --git a/UPGRADE-1.3.md b/UPGRADE-1.3.md index 3f0c34a0fb..d05ad6d1a5 100644 --- a/UPGRADE-1.3.md +++ b/UPGRADE-1.3.md @@ -35,3 +35,10 @@ class User private $groups; } ``` + +### `ClassMetadataInfo` class deprecated + +The `Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo` class has been deprecated +in favor of `Doctrine\ODM\MongoDB\Mapping\ClassMetadata` and will be dropped in +2.0. + diff --git a/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/GraphLookup.php b/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/GraphLookup.php index 445441c132..2521576b76 100644 --- a/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/GraphLookup.php +++ b/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/GraphLookup.php @@ -24,7 +24,6 @@ use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Mapping\MappingException; use Doctrine\ODM\MongoDB\Types\Type; @@ -198,9 +197,9 @@ private function getReferencedFieldName($fieldName, array $mapping) } switch ($mapping['storeAs']) { - case ClassMetadataInfo::REFERENCE_STORE_AS_ID: - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: - return ClassMetadataInfo::getReferenceFieldName($mapping['storeAs'], $mapping['name']); + case ClassMetadata::REFERENCE_STORE_AS_ID: + case ClassMetadata::REFERENCE_STORE_AS_REF: + return ClassMetadata::getReferenceFieldName($mapping['storeAs'], $mapping['name']); break; default: diff --git a/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Lookup.php b/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Lookup.php index 367f61ad43..8ba50e2cdf 100644 --- a/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Lookup.php +++ b/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Lookup.php @@ -24,7 +24,6 @@ use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Mapping\MappingException; /** @@ -111,9 +110,9 @@ private function fromReference($fieldName) if ($referenceMapping['isOwningSide']) { switch ($referenceMapping['storeAs']) { - case ClassMetadataInfo::REFERENCE_STORE_AS_ID: - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: - $referencedFieldName = ClassMetadataInfo::getReferenceFieldName($referenceMapping['storeAs'], $referenceMapping['name']); + case ClassMetadata::REFERENCE_STORE_AS_ID: + case ClassMetadata::REFERENCE_STORE_AS_REF: + $referencedFieldName = ClassMetadata::getReferenceFieldName($referenceMapping['storeAs'], $referenceMapping['name']); break; default: @@ -130,9 +129,9 @@ private function fromReference($fieldName) $mappedByMapping = $this->targetClass->getFieldMapping($referenceMapping['mappedBy']); switch ($mappedByMapping['storeAs']) { - case ClassMetadataInfo::REFERENCE_STORE_AS_ID: - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: - $referencedFieldName = ClassMetadataInfo::getReferenceFieldName($mappedByMapping['storeAs'], $mappedByMapping['name']); + case ClassMetadata::REFERENCE_STORE_AS_ID: + case ClassMetadata::REFERENCE_STORE_AS_REF: + $referencedFieldName = ClassMetadata::getReferenceFieldName($mappedByMapping['storeAs'], $mappedByMapping['name']); break; default: diff --git a/lib/Doctrine/ODM/MongoDB/DocumentManager.php b/lib/Doctrine/ODM/MongoDB/DocumentManager.php index 86240887e2..31798a1b74 100644 --- a/lib/Doctrine/ODM/MongoDB/DocumentManager.php +++ b/lib/Doctrine/ODM/MongoDB/DocumentManager.php @@ -23,7 +23,7 @@ use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\MongoDB\Connection; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Mapping\MappingException; use Doctrine\ODM\MongoDB\Hydrator\HydratorFactory; use Doctrine\ODM\MongoDB\Proxy\ProxyFactory; @@ -556,7 +556,7 @@ public function flush($document = null, array $options = array()) */ public function getReference($documentName, $identifier) { - /* @var $class \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo */ + /* @var $class \Doctrine\ODM\MongoDB\Mapping\ClassMetadata */ $class = $this->metadataFactory->getMetadataFor(ltrim($documentName, '\\')); // Check identity map first, if its already in there just return it. @@ -697,8 +697,8 @@ public function createReference($document, array $referenceMapping) $storeAs = isset($referenceMapping['storeAs']) ? $referenceMapping['storeAs'] : null; switch ($storeAs) { - case ClassMetadataInfo::REFERENCE_STORE_AS_ID: - if ($class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION) { + case ClassMetadata::REFERENCE_STORE_AS_ID: + if ($class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION) { throw MappingException::simpleReferenceMustNotTargetDiscriminatedDocument($referenceMapping['targetDocument']); } @@ -706,18 +706,18 @@ public function createReference($document, array $referenceMapping) break; - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: + case ClassMetadata::REFERENCE_STORE_AS_REF: $reference = ['id' => $class->getDatabaseIdentifierValue($id)]; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF: $reference = [ '$ref' => $class->getCollection(), '$id' => $class->getDatabaseIdentifierValue($id), ]; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB: $reference = [ '$ref' => $class->getCollection(), '$id' => $class->getDatabaseIdentifierValue($id), @@ -779,7 +779,7 @@ public function createDBRef($document, array $referenceMapping = null) @trigger_error('The ' . __METHOD__ . ' method has been deprecated and will be removed in ODM 2.0. Use createReference() instead.', E_USER_DEPRECATED); if (!isset($referenceMapping['storeAs'])) { - $referenceMapping['storeAs'] = ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF; + $referenceMapping['storeAs'] = ClassMetadata::REFERENCE_STORE_AS_DB_REF; } return $this->createReference($document, $referenceMapping); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceMany.php b/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceMany.php index 442f5b9d7a..85e450ca84 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceMany.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceMany.php @@ -19,7 +19,7 @@ namespace Doctrine\ODM\MongoDB\Mapping\Annotations; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Utility\CollectionHelper; /** @@ -32,7 +32,7 @@ final class ReferenceMany extends AbstractField public $type = 'many'; public $reference = true; public $simple = false; // @deprecated - public $storeAs = ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB; + public $storeAs = ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB; public $targetDocument; public $discriminatorField; public $discriminatorMap; diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceOne.php b/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceOne.php index b7cc956197..e8172742fd 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceOne.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/ReferenceOne.php @@ -19,7 +19,7 @@ namespace Doctrine\ODM\MongoDB\Mapping\Annotations; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; /** * Specifies a one-to-one relationship to a different document @@ -31,7 +31,7 @@ final class ReferenceOne extends AbstractField public $type = 'one'; public $reference = true; public $simple = false; // @deprecated - public $storeAs = ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB; + public $storeAs = ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB; public $targetDocument; public $discriminatorField; public $discriminatorMap; diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php index 87a2b1b906..fd83503d2a 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php @@ -19,7 +19,14 @@ namespace Doctrine\ODM\MongoDB\Mapping; +use Doctrine\Common\Persistence\Mapping\ClassMetadata as BaseClassMetadata; use Doctrine\Instantiator\Instantiator; +use Doctrine\ODM\MongoDB\LockException; +use Doctrine\ODM\MongoDB\Proxy\Proxy; +use Doctrine\ODM\MongoDB\Types\Type; +use Doctrine\ODM\MongoDB\Utility\CollectionHelper; +use InvalidArgumentException; +use function class_exists; /** * A ClassMetadata instance holds all the object-document mapping metadata @@ -37,48 +44,2217 @@ * * @since 1.0 */ -class ClassMetadata extends ClassMetadataInfo +class ClassMetadata implements BaseClassMetadata { + /* The Id generator types. */ + /** + * AUTO means Doctrine will automatically create a new \MongoId instance for us. + */ + const GENERATOR_TYPE_AUTO = 1; + + /** + * INCREMENT means a separate collection is used for maintaining and incrementing id generation. + * Offers full portability. + */ + const GENERATOR_TYPE_INCREMENT = 2; + + /** + * UUID means Doctrine will generate a uuid for us. + */ + const GENERATOR_TYPE_UUID = 3; + + /** + * ALNUM means Doctrine will generate Alpha-numeric string identifiers, using the INCREMENT + * generator to ensure identifier uniqueness + */ + const GENERATOR_TYPE_ALNUM = 4; + + /** + * CUSTOM means Doctrine expect a class parameter. It will then try to initiate that class + * and pass other options to the generator. It will throw an Exception if the class + * does not exist or if an option was passed for that there is not setter in the new + * generator class. + * + * The class will have to be a subtype of AbstractIdGenerator. + */ + const GENERATOR_TYPE_CUSTOM = 5; + + /** + * NONE means Doctrine will not generate any id for us and you are responsible for manually + * assigning an id. + */ + const GENERATOR_TYPE_NONE = 6; + + /** + * Default discriminator field name. + * + * This is used for associations value for associations where a that do not define a "targetDocument" or + * "discriminatorField" option in their mapping. + */ + const DEFAULT_DISCRIMINATOR_FIELD = '_doctrine_class_name'; + + const REFERENCE_ONE = 1; + const REFERENCE_MANY = 2; + const EMBED_ONE = 3; + const EMBED_MANY = 4; + const MANY = 'many'; + const ONE = 'one'; + + /** + * The types of storeAs references + */ + const REFERENCE_STORE_AS_ID = 'id'; + const REFERENCE_STORE_AS_DB_REF = 'dbRef'; + const REFERENCE_STORE_AS_DB_REF_WITH_DB = 'dbRefWithDb'; + const REFERENCE_STORE_AS_REF = 'ref'; + + /* The inheritance mapping types */ + /** + * NONE means the class does not participate in an inheritance hierarchy + * and therefore does not need an inheritance mapping type. + */ + const INHERITANCE_TYPE_NONE = 1; + + /** + * SINGLE_COLLECTION means the class will be persisted according to the rules of + * Single Collection Inheritance. + */ + const INHERITANCE_TYPE_SINGLE_COLLECTION = 2; + + /** + * COLLECTION_PER_CLASS means the class will be persisted according to the rules + * of Concrete Collection Inheritance. + */ + const INHERITANCE_TYPE_COLLECTION_PER_CLASS = 3; + + /** + * DEFERRED_IMPLICIT means that changes of entities are calculated at commit-time + * by doing a property-by-property comparison with the original data. This will + * be done for all entities that are in MANAGED state at commit-time. + * + * This is the default change tracking policy. + */ + const CHANGETRACKING_DEFERRED_IMPLICIT = 1; + + /** + * DEFERRED_EXPLICIT means that changes of entities are calculated at commit-time + * by doing a property-by-property comparison with the original data. This will + * be done only for entities that were explicitly saved (through persist() or a cascade). + */ + const CHANGETRACKING_DEFERRED_EXPLICIT = 2; + + /** + * NOTIFY means that Doctrine relies on the entities sending out notifications + * when their properties change. Such entity classes must implement + * the NotifyPropertyChanged interface. + */ + const CHANGETRACKING_NOTIFY = 3; + + /** + * SET means that fields will be written to the database using a $set operator + */ + const STORAGE_STRATEGY_SET = 'set'; + + /** + * INCREMENT means that fields will be written to the database by calculating + * the difference and using the $inc operator + */ + const STORAGE_STRATEGY_INCREMENT = 'increment'; + + const STORAGE_STRATEGY_PUSH_ALL = 'pushAll'; + const STORAGE_STRATEGY_ADD_TO_SET = 'addToSet'; + const STORAGE_STRATEGY_ATOMIC_SET = 'atomicSet'; + const STORAGE_STRATEGY_ATOMIC_SET_ARRAY = 'atomicSetArray'; + const STORAGE_STRATEGY_SET_ARRAY = 'setArray'; + + /** + * READ-ONLY: The name of the mongo database the document is mapped to. + */ + public $db; + + /** + * READ-ONLY: The name of the mongo collection the document is mapped to. + */ + public $collection; + + /** + * READ-ONLY: If the collection should be a fixed size. + */ + public $collectionCapped; + + /** + * READ-ONLY: If the collection is fixed size, its size in bytes. + */ + public $collectionSize; + + /** + * READ-ONLY: If the collection is fixed size, the maximum number of elements to store in the collection. + */ + public $collectionMax; + + /** + * READ-ONLY Describes how MongoDB clients route read operations to the members of a replica set. + */ + public $readPreference; + + /** + * READ-ONLY Associated with readPreference Allows to specify criteria so that your application can target read + * operations to specific members, based on custom parameters. + */ + public $readPreferenceTags; + + /** + * READ-ONLY: Describes the level of acknowledgement requested from MongoDB for write operations. + */ + public $writeConcern; + + /** + * READ-ONLY: The field name of the document identifier. + */ + public $identifier; + + /** + * READ-ONLY: The field that stores a file reference and indicates the + * document is a file and should be stored on the MongoGridFS. + */ + public $file; + + /** + * READ-ONLY: The field that stores the calculated distance when performing geo spatial + * queries. + */ + public $distance; + + /** + * READ-ONLY: Whether or not reads for this class are okay to read from a slave. + * + * @deprecated in version 1.2 and will be removed in 2.0. + */ + public $slaveOkay; + + /** + * READ-ONLY: The array of indexes for the document collection. + */ + public $indexes = array(); + + /** + * READ-ONLY: Keys and options describing shard key. Only for sharded collections. + */ + public $shardKey; + + /** + * READ-ONLY: Whether or not queries on this document should require indexes. + * + * @deprecated property was deprecated in 1.2 and will be removed in 2.0 + */ + public $requireIndexes = false; + + /** + * READ-ONLY: The name of the document class. + */ + public $name; + + /** + * READ-ONLY: The namespace the document class is contained in. + * + * @var string + * @deprecated Will be removed in 2.0. Use fully qualified class names instead + */ + public $namespace; + + /** + * READ-ONLY: The name of the document class that is at the root of the mapped document inheritance + * hierarchy. If the document is not part of a mapped inheritance hierarchy this is the same + * as {@link $documentName}. + * + * @var string + */ + public $rootDocumentName; + + /** + * The name of the custom repository class used for the document class. + * (Optional). + * + * @var string + */ + public $customRepositoryClassName; + + /** + * READ-ONLY: The names of the parent classes (ancestors). + * + * @var array + */ + public $parentClasses = array(); + + /** + * READ-ONLY: The names of all subclasses (descendants). + * + * @var array + */ + public $subClasses = array(); + /** * The ReflectionProperty instances of the mapped class. * - * @var \ReflectionProperty[] + * @var \ReflectionProperty[] + */ + public $reflFields = array(); + + /** + * READ-ONLY: The inheritance mapping type used by the class. + * + * @var integer + */ + public $inheritanceType = self::INHERITANCE_TYPE_NONE; + + /** + * READ-ONLY: The Id generator type used by the class. + * + * @var string + */ + public $generatorType = self::GENERATOR_TYPE_AUTO; + + /** + * READ-ONLY: The Id generator options. + * + * @var array + */ + public $generatorOptions = array(); + + /** + * READ-ONLY: The ID generator used for generating IDs for this class. + * + * @var \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator + */ + public $idGenerator; + + /** + * READ-ONLY: The field mappings of the class. + * Keys are field names and values are mapping definitions. + * + * The mapping definition array has the following values: + * + * - fieldName (string) + * The name of the field in the Document. + * + * - id (boolean, optional) + * Marks the field as the primary key of the document. Multiple fields of an + * document can have the id attribute, forming a composite key. + * + * @var array + */ + public $fieldMappings = array(); + + /** + * READ-ONLY: The association mappings of the class. + * Keys are field names and values are mapping definitions. + * + * @var array + */ + public $associationMappings = array(); + + /** + * READ-ONLY: Array of fields to also load with a given method. + * + * @var array + */ + public $alsoLoadMethods = array(); + + /** + * READ-ONLY: The registered lifecycle callbacks for documents of this class. + * + * @var array + */ + public $lifecycleCallbacks = array(); + + /** + * READ-ONLY: The discriminator value of this class. + * + * This does only apply to the JOINED and SINGLE_COLLECTION inheritance mapping strategies + * where a discriminator field is used. + * + * @var mixed + * @see discriminatorField + */ + public $discriminatorValue; + + /** + * READ-ONLY: The discriminator map of all mapped classes in the hierarchy. + * + * This does only apply to the SINGLE_COLLECTION inheritance mapping strategy + * where a discriminator field is used. + * + * @var mixed + * @see discriminatorField + */ + public $discriminatorMap = array(); + + /** + * READ-ONLY: The definition of the discriminator field used in SINGLE_COLLECTION + * inheritance mapping. + * + * @var string + */ + public $discriminatorField; + + /** + * READ-ONLY: The default value for discriminatorField in case it's not set in the document + * + * @var string + * @see discriminatorField + */ + public $defaultDiscriminatorValue; + + /** + * READ-ONLY: Whether this class describes the mapping of a mapped superclass. + * + * @var boolean + */ + public $isMappedSuperclass = false; + + /** + * READ-ONLY: Whether this class describes the mapping of a embedded document. + * + * @var boolean + */ + public $isEmbeddedDocument = false; + + /** + * READ-ONLY: Whether this class describes the mapping of an aggregation result document. + * + * @var boolean + */ + public $isQueryResultDocument = false; + + /** + * READ-ONLY: The policy used for change-tracking on entities of this class. + * + * @var integer + */ + public $changeTrackingPolicy = self::CHANGETRACKING_DEFERRED_IMPLICIT; + + /** + * READ-ONLY: A flag for whether or not instances of this class are to be versioned + * with optimistic locking. + * + * @var boolean $isVersioned + */ + public $isVersioned; + + /** + * READ-ONLY: The name of the field which is used for versioning in optimistic locking (if any). + * + * @var mixed $versionField + */ + public $versionField; + + /** + * READ-ONLY: A flag for whether or not instances of this class are to allow pessimistic + * locking. + * + * @var boolean $isLockable + */ + public $isLockable; + + /** + * READ-ONLY: The name of the field which is used for locking a document. + * + * @var mixed $lockField + */ + public $lockField; + + /** + * The ReflectionClass instance of the mapped class. + * + * @var \ReflectionClass + */ + public $reflClass; + + /** + * READ_ONLY: A flag for whether or not this document is read-only. + * + * @var bool + */ + public $isReadOnly; + + /** + * @var \Doctrine\Instantiator\InstantiatorInterface|null + */ + private $instantiator; + + /** + * Initializes a new ClassMetadata instance that will hold the object-document mapping + * metadata of the class with the given name. + * + * @param string $documentName The name of the document class the new instance is used for. + */ + public function __construct($documentName) + { + $this->name = $documentName; + $this->rootDocumentName = $documentName; + $this->reflClass = new \ReflectionClass($documentName); + $this->namespace = $this->reflClass->getNamespaceName(); + $this->setCollection($this->reflClass->getShortName()); + $this->instantiator = new Instantiator(); + } + + /** + * Helper method to get reference id of ref* type references + * @param mixed $reference + * @param string $storeAs + * @return mixed + * @internal + */ + public static function getReferenceId($reference, $storeAs) + { + return $storeAs === static::REFERENCE_STORE_AS_ID ? $reference : $reference[static::getReferencePrefix($storeAs) . 'id']; + } + + /** + * Returns the reference prefix used for a reference + * @param string $storeAs + * @return string + */ + private static function getReferencePrefix($storeAs) + { + if (!in_array($storeAs, [static::REFERENCE_STORE_AS_REF, static::REFERENCE_STORE_AS_DB_REF, static::REFERENCE_STORE_AS_DB_REF_WITH_DB])) { + throw new \LogicException('Can only get a reference prefix for DBRef and reference arrays'); + } + + return $storeAs === static::REFERENCE_STORE_AS_REF ? '' : '$'; + } + + /** + * Returns a fully qualified field name for a given reference + * @param string $storeAs + * @param string $pathPrefix The field path prefix + * @return string + * @internal + */ + public static function getReferenceFieldName($storeAs, $pathPrefix = '') + { + if ($storeAs === static::REFERENCE_STORE_AS_ID) { + return $pathPrefix; + } + + return ($pathPrefix ? $pathPrefix . '.' : '') . static::getReferencePrefix($storeAs) . 'id'; + } + + /** + * {@inheritDoc} + */ + public function getReflectionClass() + { + if ( ! $this->reflClass) { + $this->reflClass = new \ReflectionClass($this->name); + } + + return $this->reflClass; + } + + /** + * {@inheritDoc} + */ + public function isIdentifier($fieldName) + { + return $this->identifier === $fieldName; + } + + /** + * INTERNAL: + * Sets the mapped identifier field of this class. + * + * @param string $identifier + */ + public function setIdentifier($identifier) + { + $this->identifier = $identifier; + } + + /** + * {@inheritDoc} + * + * Since MongoDB only allows exactly one identifier field + * this will always return an array with only one value + */ + public function getIdentifier() + { + return array($this->identifier); + } + + /** + * {@inheritDoc} + * + * Since MongoDB only allows exactly one identifier field + * this will always return an array with only one value + */ + public function getIdentifierFieldNames() + { + return array($this->identifier); + } + + /** + * {@inheritDoc} + */ + public function hasField($fieldName) + { + return isset($this->fieldMappings[$fieldName]); + } + + /** + * Sets the inheritance type used by the class and it's subclasses. + * + * @param integer $type + */ + public function setInheritanceType($type) + { + $this->inheritanceType = $type; + } + + /** + * Checks whether a mapped field is inherited from an entity superclass. + * + * @param string $fieldName + * + * @return boolean TRUE if the field is inherited, FALSE otherwise. + */ + public function isInheritedField($fieldName) + { + return isset($this->fieldMappings[$fieldName]['inherited']); + } + + /** + * Registers a custom repository class for the document class. + * + * @param string $repositoryClassName The class name of the custom repository. + */ + public function setCustomRepositoryClass($repositoryClassName) + { + if ($this->isEmbeddedDocument || $this->isQueryResultDocument) { + return; + } + + if ($repositoryClassName && strpos($repositoryClassName, '\\') === false && strlen($this->namespace)) { + @trigger_error(sprintf('Class "%s" relies on same-namespace resolution for its repository class. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $this->name), E_USER_DEPRECATED); + + $repositoryClassName = $this->namespace . '\\' . $repositoryClassName; + } + + $this->customRepositoryClassName = $repositoryClassName; + } + + /** + * Dispatches the lifecycle event of the given document by invoking all + * registered callbacks. + * + * @param string $event Lifecycle event + * @param object $document Document on which the event occurred + * @param array $arguments Arguments to pass to all callbacks + * @throws \InvalidArgumentException if document class is not this class or + * a Proxy of this class + */ + public function invokeLifecycleCallbacks($event, $document, array $arguments = null) + { + if ( ! $document instanceof $this->name) { + throw new \InvalidArgumentException(sprintf('Expected document class "%s"; found: "%s"', $this->name, get_class($document))); + } + + if (empty($this->lifecycleCallbacks[$event])) { + return; + } + + foreach ($this->lifecycleCallbacks[$event] as $callback) { + if ($arguments !== null) { + call_user_func_array(array($document, $callback), $arguments); + } else { + $document->$callback(); + } + } + } + + /** + * Checks whether the class has callbacks registered for a lifecycle event. + * + * @param string $event Lifecycle event + * + * @return boolean + */ + public function hasLifecycleCallbacks($event) + { + return ! empty($this->lifecycleCallbacks[$event]); + } + + /** + * Gets the registered lifecycle callbacks for an event. + * + * @param string $event + * @return array + */ + public function getLifecycleCallbacks($event) + { + return isset($this->lifecycleCallbacks[$event]) ? $this->lifecycleCallbacks[$event] : array(); + } + + /** + * Adds a lifecycle callback for documents of this class. + * + * If the callback is already registered, this is a NOOP. + * + * @param string $callback + * @param string $event + */ + public function addLifecycleCallback($callback, $event) + { + if (isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) { + return; + } + + $this->lifecycleCallbacks[$event][] = $callback; + } + + /** + * Sets the lifecycle callbacks for documents of this class. + * + * Any previously registered callbacks are overwritten. + * + * @param array $callbacks + */ + public function setLifecycleCallbacks(array $callbacks) + { + $this->lifecycleCallbacks = $callbacks; + } + + /** + * Registers a method for loading document data before field hydration. + * + * Note: A method may be registered multiple times for different fields. + * it will be invoked only once for the first field found. + * + * @param string $method Method name + * @param array|string $fields Database field name(s) + */ + public function registerAlsoLoadMethod($method, $fields) + { + $this->alsoLoadMethods[$method] = is_array($fields) ? $fields : array($fields); + } + + /** + * Sets the AlsoLoad methods for documents of this class. + * + * Any previously registered methods are overwritten. + * + * @param array $methods + */ + public function setAlsoLoadMethods(array $methods) + { + $this->alsoLoadMethods = $methods; + } + + /** + * Sets the discriminator field. + * + * The field name is the the unmapped database field. Discriminator values + * are only used to discern the hydration class and are not mapped to class + * properties. + * + * @param string $discriminatorField + * + * @throws MappingException If the discriminator field conflicts with the + * "name" attribute of a mapped field. + */ + public function setDiscriminatorField($discriminatorField) + { + if ($discriminatorField === null) { + $this->discriminatorField = null; + + return; + } + + // Handle array argument with name/fieldName keys for BC + if (is_array($discriminatorField)) { + if (isset($discriminatorField['name'])) { + $discriminatorField = $discriminatorField['name']; + } elseif (isset($discriminatorField['fieldName'])) { + $discriminatorField = $discriminatorField['fieldName']; + } + } + + foreach ($this->fieldMappings as $fieldMapping) { + if ($discriminatorField == $fieldMapping['name']) { + throw MappingException::discriminatorFieldConflict($this->name, $discriminatorField); + } + } + + $this->discriminatorField = $discriminatorField; + } + + /** + * Sets the discriminator values used by this class. + * Used for JOINED and SINGLE_TABLE inheritance mapping strategies. + * + * @param array $map + * + * @throws MappingException + */ + public function setDiscriminatorMap(array $map) + { + foreach ($map as $value => $className) { + if (strpos($className, '\\') === false && strlen($this->namespace)) { + @trigger_error(sprintf('Class "%s" relies on same-namespace resolution in its discriminator map for value "%s". This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $this->name, $value), E_USER_DEPRECATED); + + $className = $this->namespace . '\\' . $className; + } + $this->discriminatorMap[$value] = $className; + if ($this->name == $className) { + $this->discriminatorValue = $value; + } else { + if ( ! class_exists($className)) { + throw MappingException::invalidClassInDiscriminatorMap($className, $this->name); + } + if (is_subclass_of($className, $this->name)) { + $this->subClasses[] = $className; + } + } + } + } + + /** + * Sets the default discriminator value to be used for this class + * Used for JOINED and SINGLE_TABLE inheritance mapping strategies if the document has no discriminator value + * + * @param string $defaultDiscriminatorValue + * + * @throws MappingException + */ + public function setDefaultDiscriminatorValue($defaultDiscriminatorValue) + { + if ($defaultDiscriminatorValue === null) { + $this->defaultDiscriminatorValue = null; + + return; + } + + if (!array_key_exists($defaultDiscriminatorValue, $this->discriminatorMap)) { + throw MappingException::invalidDiscriminatorValue($defaultDiscriminatorValue, $this->name); + } + + $this->defaultDiscriminatorValue = $defaultDiscriminatorValue; + } + + /** + * Sets the discriminator value for this class. + * Used for JOINED/SINGLE_TABLE inheritance and multiple document types in a single + * collection. + * + * @param string $value + */ + public function setDiscriminatorValue($value) + { + $this->discriminatorMap[$value] = $this->name; + $this->discriminatorValue = $value; + } + + /** + * Sets the slaveOkay option applied to collections for this class. + * + * @param boolean|null $slaveOkay + * + * @deprecated in version 1.2 and will be removed in 2.0. + * + * @throws MappingException + */ + public function setSlaveOkay($slaveOkay) + { + if ($slaveOkay) { + @trigger_error( + sprintf('%s was deprecated in version 1.2 and will be removed in 2.0.', __METHOD__), + E_USER_DEPRECATED + ); + } + + if ($this->readPreference) { + throw MappingException::canNotCombineReadPreferenceAndSlaveOkay($this->getName()); + } + $this->slaveOkay = $slaveOkay === null ? null : (boolean) $slaveOkay; + } + + /** + * Add a index for this Document. + * + * @param array $keys Array of keys for the index. + * @param array $options Array of options for the index. + */ + public function addIndex($keys, array $options = array()) + { + $this->indexes[] = array( + 'keys' => array_map(function($value) { + if ($value == 1 || $value == -1) { + return (int) $value; + } + if (is_string($value)) { + $lower = strtolower($value); + if ($lower === 'asc') { + return 1; + } elseif ($lower === 'desc') { + return -1; + } + } + return $value; + }, $keys), + 'options' => $options + ); + } + + /** + * Set whether or not queries on this document should require indexes. + * + * @param bool $requireIndexes + * + * @deprecated method was deprecated in 1.2 and will be removed in 2.0 + */ + public function setRequireIndexes($requireIndexes) + { + if ($requireIndexes) { + @trigger_error( + 'requireIndexes was deprecated in version 1.2 and will be removed altogether in 2.0.', + E_USER_DEPRECATED + ); + } + + $this->requireIndexes = $requireIndexes; + } + + /** + * Returns the array of indexes for this Document. + * + * @return array $indexes The array of indexes. + */ + public function getIndexes() + { + return $this->indexes; + } + + /** + * Checks whether this document has indexes or not. + * + * @return boolean + */ + public function hasIndexes() + { + return $this->indexes ? true : false; + } + + /** + * Set shard key for this Document. + * + * @param array $keys Array of document keys. + * @param array $options Array of sharding options. + * + * @throws MappingException + */ + public function setShardKey(array $keys, array $options = array()) + { + if ($this->inheritanceType === self::INHERITANCE_TYPE_SINGLE_COLLECTION && !is_null($this->shardKey)) { + throw MappingException::shardKeyInSingleCollInheritanceSubclass($this->getName()); + } + + if ($this->isEmbeddedDocument) { + throw MappingException::embeddedDocumentCantHaveShardKey($this->getName()); + } + + foreach (array_keys($keys) as $field) { + if (! isset($this->fieldMappings[$field])) { + continue; + } + + if (in_array($this->fieldMappings[$field]['type'], ['many', 'collection'])) { + throw MappingException::noMultiKeyShardKeys($this->getName(), $field); + } + + if ($this->fieldMappings[$field]['strategy'] !== static::STORAGE_STRATEGY_SET) { + throw MappingException::onlySetStrategyAllowedInShardKey($this->getName(), $field); + } + } + + $this->shardKey = array( + 'keys' => array_map(function($value) { + if ($value == 1 || $value == -1) { + return (int) $value; + } + if (is_string($value)) { + $lower = strtolower($value); + if ($lower === 'asc') { + return 1; + } elseif ($lower === 'desc') { + return -1; + } + } + return $value; + }, $keys), + 'options' => $options + ); + } + + /** + * @return array + */ + public function getShardKey() + { + return $this->shardKey; + } + + /** + * Checks whether this document has shard key or not. + * + * @return bool + */ + public function isSharded() + { + return $this->shardKey ? true : false; + } + + /** + * Sets the read preference used by this class. + * + * @param string $readPreference + * @param array|null $tags + * + * @throws MappingException + */ + public function setReadPreference($readPreference, $tags) + { + if ($this->slaveOkay) { + throw MappingException::canNotCombineReadPreferenceAndSlaveOkay($this->getName()); + } + $this->readPreference = $readPreference; + $this->readPreferenceTags = $tags; + } + + /** + * Sets the write concern used by this class. + * + * @param string $writeConcern + */ + public function setWriteConcern($writeConcern) + { + $this->writeConcern = $writeConcern; + } + + /** + * @return string + */ + public function getWriteConcern() + { + return $this->writeConcern; + } + + /** + * Whether there is a write concern configured for this class. + * + * @return bool + */ + public function hasWriteConcern() + { + return $this->writeConcern !== null; + } + + /** + * Sets the change tracking policy used by this class. + * + * @param integer $policy + */ + public function setChangeTrackingPolicy($policy) + { + $this->changeTrackingPolicy = $policy; + } + + /** + * Whether the change tracking policy of this class is "deferred explicit". + * + * @return boolean + */ + public function isChangeTrackingDeferredExplicit() + { + return $this->changeTrackingPolicy == self::CHANGETRACKING_DEFERRED_EXPLICIT; + } + + /** + * Whether the change tracking policy of this class is "deferred implicit". + * + * @return boolean + */ + public function isChangeTrackingDeferredImplicit() + { + return $this->changeTrackingPolicy == self::CHANGETRACKING_DEFERRED_IMPLICIT; + } + + /** + * Whether the change tracking policy of this class is "notify". + * + * @return boolean + */ + public function isChangeTrackingNotify() + { + return $this->changeTrackingPolicy == self::CHANGETRACKING_NOTIFY; + } + + /** + * Gets the ReflectionProperties of the mapped class. + * + * @return array An array of ReflectionProperty instances. + */ + public function getReflectionProperties() + { + return $this->reflFields; + } + + /** + * Gets a ReflectionProperty for a specific field of the mapped class. + * + * @param string $name + * + * @return \ReflectionProperty + */ + public function getReflectionProperty($name) + { + return $this->reflFields[$name]; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->name; + } + + /** + * The namespace this Document class belongs to. + * + * @return string $namespace The namespace name. + * @deprecated will be removed in 2.0 + */ + public function getNamespace() + { + @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in 2.0.', __METHOD__), E_USER_DEPRECATED); + + return $this->namespace; + } + + /** + * Returns the database this Document is mapped to. + * + * @return string $db The database name. + */ + public function getDatabase() + { + return $this->db; + } + + /** + * Set the database this Document is mapped to. + * + * @param string $db The database name + */ + public function setDatabase($db) + { + $this->db = $db; + } + + /** + * Get the collection this Document is mapped to. + * + * @return string $collection The collection name. + */ + public function getCollection() + { + return $this->collection; + } + + /** + * Sets the collection this Document is mapped to. + * + * @param array|string $name + * + * @throws \InvalidArgumentException + */ + public function setCollection($name) + { + if (is_array($name)) { + if ( ! isset($name['name'])) { + throw new \InvalidArgumentException('A name key is required when passing an array to setCollection()'); + } + $this->collectionCapped = isset($name['capped']) ? $name['capped'] : false; + $this->collectionSize = isset($name['size']) ? $name['size'] : 0; + $this->collectionMax = isset($name['max']) ? $name['max'] : 0; + $this->collection = $name['name']; + } else { + $this->collection = $name; + } + } + + /** + * Get whether or not the documents collection is capped. + * + * @return boolean + */ + public function getCollectionCapped() + { + return $this->collectionCapped; + } + + /** + * Set whether or not the documents collection is capped. + * + * @param boolean $bool + */ + public function setCollectionCapped($bool) + { + $this->collectionCapped = $bool; + } + + /** + * Get the collection size + * + * @return integer + */ + public function getCollectionSize() + { + return $this->collectionSize; + } + + /** + * Set the collection size. + * + * @param integer $size + */ + public function setCollectionSize($size) + { + $this->collectionSize = $size; + } + + /** + * Get the collection max. + * + * @return integer + */ + public function getCollectionMax() + { + return $this->collectionMax; + } + + /** + * Set the collection max. + * + * @param integer $max + */ + public function setCollectionMax($max) + { + $this->collectionMax = $max; + } + + /** + * Returns TRUE if this Document is mapped to a collection FALSE otherwise. + * + * @return boolean + */ + public function isMappedToCollection() + { + return $this->collection ? true : false; + } + + /** + * Returns TRUE if this Document is a file to be stored on the MongoGridFS FALSE otherwise. + * + * @return boolean + */ + public function isFile() + { + return $this->file ? true : false; + } + + /** + * Returns the file field name. + * + * @return string $file The file field name. + */ + public function getFile() + { + return $this->file; + } + + /** + * Set the field name that stores the grid file. + * + * @param string $file + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Returns the distance field name. + * + * @return string $distance The distance field name. + */ + public function getDistance() + { + return $this->distance; + } + + /** + * Set the field name that stores the distance. + * + * @param string $distance + */ + public function setDistance($distance) + { + $this->distance = $distance; + } + + /** + * Map a field. + * + * @param array $mapping The mapping information. + * @return void + */ + public function mapField(array $mapping) + { + if ( ! isset($mapping['fieldName']) && isset($mapping['name'])) { + $mapping['fieldName'] = $mapping['name']; + } + if ( ! isset($mapping['fieldName'])) { + throw MappingException::missingFieldName($this->name); + } + if ( ! isset($mapping['name'])) { + $mapping['name'] = $mapping['fieldName']; + } + if ($this->identifier === $mapping['name'] && empty($mapping['id'])) { + throw MappingException::mustNotChangeIdentifierFieldsType($this->name, $mapping['name']); + } + if (isset($this->fieldMappings[$mapping['fieldName']])) { + //throw MappingException::duplicateFieldMapping($this->name, $mapping['fieldName']); + } + if ($this->discriminatorField !== null && $this->discriminatorField == $mapping['name']) { + throw MappingException::discriminatorFieldConflict($this->name, $this->discriminatorField); + } + if (isset($mapping['targetDocument']) && strpos($mapping['targetDocument'], '\\') === false && strlen($this->namespace)) { + @trigger_error(sprintf('Field "%s" in class "%s" relies on same-namespace resolution for the target document. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $mapping['name'], $this->name), E_USER_DEPRECATED); + + $mapping['targetDocument'] = $this->namespace . '\\' . $mapping['targetDocument']; + } + + if (isset($mapping['collectionClass'])) { + if (strpos($mapping['collectionClass'], '\\') === false && strlen($this->namespace)) { + @trigger_error(sprintf('Field "%s" in class "%s" relies on same-namespace resolution for the collection class. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $mapping['name'], $this->name), E_USER_DEPRECATED); + + $mapping['collectionClass'] = $this->namespace . '\\' . $mapping['collectionClass']; + } + $mapping['collectionClass'] = ltrim($mapping['collectionClass'], '\\'); + } + if ( ! empty($mapping['collectionClass'])) { + $rColl = new \ReflectionClass($mapping['collectionClass']); + if ( ! $rColl->implementsInterface('Doctrine\\Common\\Collections\\Collection')) { + throw MappingException::collectionClassDoesNotImplementCommonInterface($this->name, $mapping['fieldName'], $mapping['collectionClass']); + } + } + + if (isset($mapping['discriminatorMap'])) { + foreach ($mapping['discriminatorMap'] as $key => $class) { + if (strpos($class, '\\') === false && strlen($this->namespace)) { + @trigger_error(sprintf('Field "%s" in class "%s" relies on same-namespace resolution in its discriminator map for value "%s". This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $mapping['name'], $this->name, $key), E_USER_DEPRECATED); + + $mapping['discriminatorMap'][$key] = $this->namespace . '\\' . $class; + } + } + } + + if (isset($mapping['cascade']) && isset($mapping['embedded'])) { + throw MappingException::cascadeOnEmbeddedNotAllowed($this->name, $mapping['fieldName']); + } + + $cascades = isset($mapping['cascade']) ? array_map('strtolower', (array) $mapping['cascade']) : array(); + + if (in_array('all', $cascades) || isset($mapping['embedded'])) { + $cascades = array('remove', 'persist', 'refresh', 'merge', 'detach'); + } + + if (isset($mapping['embedded'])) { + unset($mapping['cascade']); + } elseif (isset($mapping['cascade'])) { + $mapping['cascade'] = $cascades; + } + + $mapping['isCascadeRemove'] = in_array('remove', $cascades); + $mapping['isCascadePersist'] = in_array('persist', $cascades); + $mapping['isCascadeRefresh'] = in_array('refresh', $cascades); + $mapping['isCascadeMerge'] = in_array('merge', $cascades); + $mapping['isCascadeDetach'] = in_array('detach', $cascades); + + if (isset($mapping['type']) && $mapping['type'] === 'file') { + $mapping['file'] = true; + } + if (isset($mapping['type']) && $mapping['type'] === 'increment') { + $mapping['strategy'] = self::STORAGE_STRATEGY_INCREMENT; + } + if (isset($mapping['file']) && $mapping['file'] === true) { + $this->file = $mapping['fieldName']; + $mapping['name'] = 'file'; + } + if (isset($mapping['distance']) && $mapping['distance'] === true) { + $this->distance = $mapping['fieldName']; + } + if (isset($mapping['id']) && $mapping['id'] === true) { + $mapping['name'] = '_id'; + $this->identifier = $mapping['fieldName']; + if (isset($mapping['strategy'])) { + $this->generatorType = constant(ClassMetadata::class . '::GENERATOR_TYPE_' . strtoupper($mapping['strategy'])); + } + $this->generatorOptions = isset($mapping['options']) ? $mapping['options'] : array(); + switch ($this->generatorType) { + case self::GENERATOR_TYPE_AUTO: + $mapping['type'] = 'id'; + break; + default: + if ( ! empty($this->generatorOptions['type'])) { + $mapping['type'] = $this->generatorOptions['type']; + } elseif (empty($mapping['type'])) { + $mapping['type'] = $this->generatorType === self::GENERATOR_TYPE_INCREMENT ? 'int_id' : 'custom_id'; + } + } + unset($this->generatorOptions['type']); + } + + if ( ! isset($mapping['nullable'])) { + $mapping['nullable'] = false; + } + + // Synchronize the "simple" and "storeAs" mapping information for backwards compatibility + if (isset($mapping['simple']) && ($mapping['simple'] === true || $mapping['simple'] === 'true')) { + $mapping['storeAs'] = static::REFERENCE_STORE_AS_ID; + @trigger_error('"simple" attribute of a reference is deprecated - use storeAs="id" instead.', E_USER_DEPRECATED); + } + // Provide the correct value for the "simple" field for backwards compatibility + if (isset($mapping['storeAs'])) { + $mapping['simple'] = $mapping['storeAs'] === static::REFERENCE_STORE_AS_ID; + } + + if (isset($mapping['reference']) + && isset($mapping['storeAs']) + && $mapping['storeAs'] === static::REFERENCE_STORE_AS_ID + && ! isset($mapping['targetDocument']) + ) { + throw MappingException::simpleReferenceRequiresTargetDocument($this->name, $mapping['fieldName']); + } + + if (isset($mapping['reference']) && empty($mapping['targetDocument']) && empty($mapping['discriminatorMap']) && + (isset($mapping['mappedBy']) || isset($mapping['inversedBy']))) { + throw MappingException::owningAndInverseReferencesRequireTargetDocument($this->name, $mapping['fieldName']); + } + + if ($this->isEmbeddedDocument && $mapping['type'] === 'many' && isset($mapping['strategy']) && CollectionHelper::isAtomic($mapping['strategy'])) { + throw MappingException::atomicCollectionStrategyNotAllowed($mapping['strategy'], $this->name, $mapping['fieldName']); + } + + if (isset($mapping['repositoryMethod']) && ! (empty($mapping['skip']) && empty($mapping['limit']) && empty($mapping['sort']))) { + @trigger_error( + sprintf( + "Combining 'repositoryMethod' with skip, limit or sort (used on '%s' in class '%s') was deprecated in 1.3 and will be removed in 2.0. Please include those in the repository method itself.", + $mapping['fieldName'], + $this->name + ), + E_USER_DEPRECATED + ); + } + + if (isset($mapping['reference']) && $mapping['type'] === 'one') { + $mapping['association'] = self::REFERENCE_ONE; + } + if (isset($mapping['reference']) && $mapping['type'] === 'many') { + $mapping['association'] = self::REFERENCE_MANY; + } + if (isset($mapping['embedded']) && $mapping['type'] === 'one') { + $mapping['association'] = self::EMBED_ONE; + } + if (isset($mapping['embedded']) && $mapping['type'] === 'many') { + $mapping['association'] = self::EMBED_MANY; + } + + if (isset($mapping['association']) && ! isset($mapping['targetDocument']) && ! isset($mapping['discriminatorField'])) { + $mapping['discriminatorField'] = self::DEFAULT_DISCRIMINATOR_FIELD; + } + + /* + if (isset($mapping['type']) && ($mapping['type'] === 'one' || $mapping['type'] === 'many')) { + $mapping['type'] = $mapping['type'] === 'one' ? self::ONE : self::MANY; + } + */ + if (isset($mapping['version'])) { + $mapping['notSaved'] = true; + $this->setVersionMapping($mapping); + } + if (isset($mapping['lock'])) { + $mapping['notSaved'] = true; + $this->setLockMapping($mapping); + } + $mapping['isOwningSide'] = true; + $mapping['isInverseSide'] = false; + if (isset($mapping['reference'])) { + if (isset($mapping['inversedBy']) && $mapping['inversedBy']) { + $mapping['isOwningSide'] = true; + $mapping['isInverseSide'] = false; + } + if (isset($mapping['mappedBy']) && $mapping['mappedBy']) { + $mapping['isInverseSide'] = true; + $mapping['isOwningSide'] = false; + } + if (isset($mapping['repositoryMethod'])) { + $mapping['isInverseSide'] = true; + $mapping['isOwningSide'] = false; + } + if (!isset($mapping['orphanRemoval'])) { + $mapping['orphanRemoval'] = false; + } + } + + if (!empty($mapping['prime']) && ($mapping['association'] !== self::REFERENCE_MANY || !$mapping['isInverseSide'])) { + throw MappingException::referencePrimersOnlySupportedForInverseReferenceMany($this->name, $mapping['fieldName']); + } + + $this->applyStorageStrategy($mapping); + + $this->fieldMappings[$mapping['fieldName']] = $mapping; + if (isset($mapping['association'])) { + $this->associationMappings[$mapping['fieldName']] = $mapping; + } + + $reflProp = $this->reflClass->getProperty($mapping['fieldName']); + $reflProp->setAccessible(true); + $this->reflFields[$mapping['fieldName']] = $reflProp; + + 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': + case $mapping['type'] == 'increment': + $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. + * + * @param array $mapping The mapping information. + */ + public function mapFile(array $mapping) + { + $mapping['file'] = true; + $mapping['type'] = 'file'; + $this->mapField($mapping); + } + + /** + * Map a single embedded document. + * + * @param array $mapping The mapping information. + */ + public function mapOneEmbedded(array $mapping) + { + $mapping['embedded'] = true; + $mapping['type'] = 'one'; + $this->mapField($mapping); + } + + /** + * Map a collection of embedded documents. + * + * @param array $mapping The mapping information. + */ + public function mapManyEmbedded(array $mapping) + { + $mapping['embedded'] = true; + $mapping['type'] = 'many'; + $this->mapField($mapping); + } + + /** + * Map a single document reference. + * + * @param array $mapping The mapping information. + */ + public function mapOneReference(array $mapping) + { + $mapping['reference'] = true; + $mapping['type'] = 'one'; + $this->mapField($mapping); + } + + /** + * Map a collection of document references. + * + * @param array $mapping The mapping information. + */ + public function mapManyReference(array $mapping) + { + $mapping['reference'] = true; + $mapping['type'] = 'many'; + $this->mapField($mapping); + } + + /** + * INTERNAL: + * Adds a field mapping without completing/validating it. + * This is mainly used to add inherited field mappings to derived classes. + * + * @param array $fieldMapping + */ + public function addInheritedFieldMapping(array $fieldMapping) + { + $this->fieldMappings[$fieldMapping['fieldName']] = $fieldMapping; + + if (isset($fieldMapping['association'])) { + $this->associationMappings[$fieldMapping['fieldName']] = $fieldMapping; + } + } + + /** + * INTERNAL: + * Adds an association mapping without completing/validating it. + * This is mainly used to add inherited association mappings to derived classes. + * + * @param array $mapping + * + * @return void + * + * @throws MappingException + */ + public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/) + { + $this->associationMappings[$mapping['fieldName']] = $mapping; + } + + /** + * Checks whether the class has a mapped association with the given field name. + * + * @param string $fieldName + * @return boolean + */ + public function hasReference($fieldName) + { + return isset($this->fieldMappings[$fieldName]['reference']); + } + + /** + * Checks whether the class has a mapped embed with the given field name. + * + * @param string $fieldName + * @return boolean + */ + public function hasEmbed($fieldName) + { + return isset($this->fieldMappings[$fieldName]['embedded']); + } + + /** + * {@inheritDoc} + * + * Checks whether the class has a mapped association (embed or reference) with the given field name. + */ + public function hasAssociation($fieldName) + { + return $this->hasReference($fieldName) || $this->hasEmbed($fieldName); + } + + /** + * {@inheritDoc} + * + * Checks whether the class has a mapped reference or embed for the specified field and + * is a single valued association. + */ + public function isSingleValuedAssociation($fieldName) + { + return $this->isSingleValuedReference($fieldName) || $this->isSingleValuedEmbed($fieldName); + } + + /** + * {@inheritDoc} + * + * Checks whether the class has a mapped reference or embed for the specified field and + * is a collection valued association. + */ + public function isCollectionValuedAssociation($fieldName) + { + return $this->isCollectionValuedReference($fieldName) || $this->isCollectionValuedEmbed($fieldName); + } + + /** + * Checks whether the class has a mapped association for the specified field + * and if yes, checks whether it is a single-valued association (to-one). + * + * @param string $fieldName + * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise. + */ + public function isSingleValuedReference($fieldName) + { + return isset($this->fieldMappings[$fieldName]['association']) && + $this->fieldMappings[$fieldName]['association'] === self::REFERENCE_ONE; + } + + /** + * Checks whether the class has a mapped association for the specified field + * and if yes, checks whether it is a collection-valued association (to-many). + * + * @param string $fieldName + * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise. + */ + public function isCollectionValuedReference($fieldName) + { + return isset($this->fieldMappings[$fieldName]['association']) && + $this->fieldMappings[$fieldName]['association'] === self::REFERENCE_MANY; + } + + /** + * Checks whether the class has a mapped embedded document for the specified field + * and if yes, checks whether it is a single-valued association (to-one). + * + * @param string $fieldName + * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise. + */ + public function isSingleValuedEmbed($fieldName) + { + return isset($this->fieldMappings[$fieldName]['association']) && + $this->fieldMappings[$fieldName]['association'] === self::EMBED_ONE; + } + + /** + * Checks whether the class has a mapped embedded document for the specified field + * and if yes, checks whether it is a collection-valued association (to-many). + * + * @param string $fieldName + * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise. + */ + public function isCollectionValuedEmbed($fieldName) + { + return isset($this->fieldMappings[$fieldName]['association']) && + $this->fieldMappings[$fieldName]['association'] === self::EMBED_MANY; + } + + /** + * Sets the ID generator used to generate IDs for instances of this class. + * + * @param \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator $generator + */ + public function setIdGenerator($generator) + { + $this->idGenerator = $generator; + } + + /** + * Casts the identifier to its portable PHP type. + * + * @param mixed $id + * @return mixed $id */ - public $reflFields = array(); + public function getPHPIdentifierValue($id) + { + $idType = $this->fieldMappings[$this->identifier]['type']; + return Type::getType($idType)->convertToPHPValue($id); + } /** - * @var \Doctrine\Instantiator\InstantiatorInterface|null + * Casts the identifier to its database type. + * + * @param mixed $id + * @return mixed $id */ - private $instantiator; + public function getDatabaseIdentifierValue($id) + { + $idType = $this->fieldMappings[$this->identifier]['type']; + return Type::getType($idType)->convertToDatabaseValue($id); + } /** - * Initializes a new ClassMetadata instance that will hold the object-document mapping - * metadata of the class with the given name. + * Sets the document identifier of a document. * - * @param string $documentName The name of the document class the new instance is used for. + * The value will be converted to a PHP type before being set. + * + * @param object $document + * @param mixed $id */ - public function __construct($documentName) + public function setIdentifierValue($document, $id) { - parent::__construct($documentName); - $this->reflClass = new \ReflectionClass($documentName); - $this->namespace = $this->reflClass->getNamespaceName(); - $this->setCollection($this->reflClass->getShortName()); - $this->instantiator = new Instantiator(); + $id = $this->getPHPIdentifierValue($id); + $this->reflFields[$this->identifier]->setValue($document, $id); } /** - * Map a field. + * Gets the document identifier as a PHP type. * - * @param array $mapping The mapping information. - * @return void + * @param object $document + * @return mixed $id */ - public function mapField(array $mapping) + public function getIdentifierValue($document) { - $mapping = parent::mapField($mapping); + return $this->reflFields[$this->identifier]->getValue($document); + } - $reflProp = $this->reflClass->getProperty($mapping['fieldName']); - $reflProp->setAccessible(true); - $this->reflFields[$mapping['fieldName']] = $reflProp; + /** + * {@inheritDoc} + * + * Since MongoDB only allows exactly one identifier field this is a proxy + * to {@see getIdentifierValue()} and returns an array with the identifier + * field as a key. + */ + public function getIdentifierValues($object) + { + return array($this->identifier => $this->getIdentifierValue($object)); + } + + /** + * Get the document identifier object as a database type. + * + * @param object $document + * + * @return \MongoId $id The MongoID object. + */ + public function getIdentifierObject($document) + { + return $this->getDatabaseIdentifierValue($this->getIdentifierValue($document)); + } + + /** + * Sets the specified field to the specified value on the given document. + * + * @param object $document + * @param string $field + * @param mixed $value + */ + public function setFieldValue($document, $field, $value) + { + if ($document instanceof Proxy && ! $document->__isInitialized()) { + //property changes to an uninitialized proxy will not be tracked or persisted, + //so the proxy needs to be loaded first. + $document->__load(); + } + + $this->reflFields[$field]->setValue($document, $value); + } + + /** + * Gets the specified field's value off the given document. + * + * @param object $document + * @param string $field + * + * @return mixed + */ + public function getFieldValue($document, $field) + { + if ($document instanceof Proxy && $field !== $this->identifier && ! $document->__isInitialized()) { + $document->__load(); + } + + return $this->reflFields[$field]->getValue($document); + } + + /** + * Gets the mapping of a field. + * + * @param string $fieldName The field name. + * + * @return array The field mapping. + * + * @throws MappingException if the $fieldName is not found in the fieldMappings array + */ + public function getFieldMapping($fieldName) + { + if ( ! isset($this->fieldMappings[$fieldName])) { + throw MappingException::mappingNotFound($this->name, $fieldName); + } + return $this->fieldMappings[$fieldName]; + } + + /** + * Gets mappings of fields holding embedded document(s). + * + * @return array of field mappings + */ + public function getEmbeddedFieldsMappings() + { + return array_filter( + $this->associationMappings, + function($assoc) { return ! empty($assoc['embedded']); } + ); + } + + /** + * Gets the field mapping by its DB name. + * E.g. it returns identifier's mapping when called with _id. + * + * @param string $dbFieldName + * + * @return array + * @throws MappingException + */ + public function getFieldMappingByDbFieldName($dbFieldName) + { + foreach ($this->fieldMappings as $mapping) { + if ($mapping['name'] == $dbFieldName) { + return $mapping; + } + } + + throw MappingException::mappingNotFoundByDbName($this->name, $dbFieldName); + } + + /** + * Check if the field is not null. + * + * @param string $fieldName The field name + * + * @return boolean TRUE if the field is not null, FALSE otherwise. + */ + public function isNullable($fieldName) + { + $mapping = $this->getFieldMapping($fieldName); + if ($mapping !== false) { + return isset($mapping['nullable']) && $mapping['nullable'] == true; + } + return false; + } + + /** + * Checks whether the document has a discriminator field and value configured. + * + * @return boolean + */ + public function hasDiscriminator() + { + return isset($this->discriminatorField, $this->discriminatorValue); + } + + /** + * Sets the type of Id generator to use for the mapped class. + * + * @param string $generatorType Generator type. + */ + public function setIdGeneratorType($generatorType) + { + $this->generatorType = $generatorType; + } + + /** + * Sets the Id generator options. + * + * @param array $generatorOptions Generator options. + */ + public function setIdGeneratorOptions($generatorOptions) + { + $this->generatorOptions = $generatorOptions; + } + + /** + * @return boolean + */ + public function isInheritanceTypeNone() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_NONE; + } + + /** + * Checks whether the mapped class uses the SINGLE_COLLECTION inheritance mapping strategy. + * + * @return boolean + */ + public function isInheritanceTypeSingleCollection() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_SINGLE_COLLECTION; + } + + /** + * Checks whether the mapped class uses the COLLECTION_PER_CLASS inheritance mapping strategy. + * + * @return boolean + */ + public function isInheritanceTypeCollectionPerClass() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_COLLECTION_PER_CLASS; + } + + /** + * Sets the mapped subclasses of this class. + * + * @param string[] $subclasses The names of all mapped subclasses. + */ + public function setSubclasses(array $subclasses) + { + foreach ($subclasses as $subclass) { + if (strpos($subclass, '\\') === false && strlen($this->namespace)) { + @trigger_error(sprintf('Subclass "%s" in class "%s" relies on same-namespace resolution. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $subclass, $this->name), E_USER_DEPRECATED); + + $this->subClasses[] = $this->namespace . '\\' . $subclass; + } else { + $this->subClasses[] = $subclass; + } + } + } + + /** + * Sets the parent class names. + * Assumes that the class names in the passed array are in the order: + * directParent -> directParentParent -> directParentParentParent ... -> root. + * + * @param string[] $classNames + */ + public function setParentClasses(array $classNames) + { + $this->parentClasses = $classNames; + + if (count($classNames) > 0) { + $this->rootDocumentName = array_pop($classNames); + } + } + + /** + * Checks whether the class will generate a new \MongoId instance for us. + * + * @return boolean TRUE if the class uses the AUTO generator, FALSE otherwise. + */ + public function isIdGeneratorAuto() + { + return $this->generatorType == self::GENERATOR_TYPE_AUTO; + } + + /** + * Checks whether the class will use a collection to generate incremented identifiers. + * + * @return boolean TRUE if the class uses the INCREMENT generator, FALSE otherwise. + */ + public function isIdGeneratorIncrement() + { + return $this->generatorType == self::GENERATOR_TYPE_INCREMENT; + } + + /** + * Checks whether the class will generate a uuid id. + * + * @return boolean TRUE if the class uses the UUID generator, FALSE otherwise. + */ + public function isIdGeneratorUuid() + { + return $this->generatorType == self::GENERATOR_TYPE_UUID; + } + + /** + * Checks whether the class uses no id generator. + * + * @return boolean TRUE if the class does not use any id generator, FALSE otherwise. + */ + public function isIdGeneratorNone() + { + return $this->generatorType == self::GENERATOR_TYPE_NONE; + } + + /** + * Sets the version field mapping used for versioning. Sets the default + * value to use depending on the column type. + * + * @param array $mapping The version field mapping array + * + * @throws LockException + */ + public function setVersionMapping(array &$mapping) + { + if ($mapping['type'] !== 'int' && $mapping['type'] !== 'date') { + throw LockException::invalidVersionFieldType($mapping['type']); + } + + $this->isVersioned = true; + $this->versionField = $mapping['fieldName']; + } + + /** + * Sets whether this class is to be versioned for optimistic locking. + * + * @param boolean $bool + */ + public function setVersioned($bool) + { + $this->isVersioned = $bool; + } + + /** + * Sets the name of the field that is to be used for versioning if this class is + * versioned for optimistic locking. + * + * @param string $versionField + */ + public function setVersionField($versionField) + { + $this->versionField = $versionField; + } + + /** + * Sets the version field mapping used for versioning. Sets the default + * value to use depending on the column type. + * + * @param array $mapping The version field mapping array + * + * @throws \Doctrine\ODM\MongoDB\LockException + */ + public function setLockMapping(array &$mapping) + { + if ($mapping['type'] !== 'int') { + throw LockException::invalidLockFieldType($mapping['type']); + } + + $this->isLockable = true; + $this->lockField = $mapping['fieldName']; + } + + /** + * Sets whether this class is to allow pessimistic locking. + * + * @param boolean $bool + */ + public function setLockable($bool) + { + $this->isLockable = $bool; + } + + /** + * Sets the name of the field that is to be used for storing whether a document + * is currently locked or not. + * + * @param string $lockField + */ + public function setLockField($lockField) + { + $this->lockField = $lockField; + } + + /** + * Marks this class as read only, no change tracking is applied to it. + */ + public function markReadOnly() + { + $this->isReadOnly = true; + } + + /** + * {@inheritDoc} + */ + public function getFieldNames() + { + return array_keys($this->fieldMappings); + } + + /** + * {@inheritDoc} + */ + public function getAssociationNames() + { + return array_keys($this->associationMappings); + } + + /** + * {@inheritDoc} + */ + public function getTypeOfField($fieldName) + { + return isset($this->fieldMappings[$fieldName]) ? + $this->fieldMappings[$fieldName]['type'] : null; + } + + /** + * {@inheritDoc} + */ + public function getAssociationTargetClass($assocName) + { + if ( ! isset($this->associationMappings[$assocName])) { + throw new InvalidArgumentException("Association name expected, '" . $assocName . "' is not an association."); + } + + return $this->associationMappings[$assocName]['targetDocument']; + } + + /** + * Retrieve the collectionClass associated with an association + * + * @param string $assocName + */ + public function getAssociationCollectionClass($assocName) + { + if ( ! isset($this->associationMappings[$assocName])) { + throw new InvalidArgumentException("Association name expected, '" . $assocName . "' is not an association."); + } + + if ( ! array_key_exists('collectionClass', $this->associationMappings[$assocName])) { + throw new InvalidArgumentException("collectionClass can only be applied to 'embedMany' and 'referenceMany' associations."); + } + + return $this->associationMappings[$assocName]['collectionClass']; + } + + /** + * {@inheritDoc} + */ + public function isAssociationInverseSide($fieldName) + { + throw new \BadMethodCallException(__METHOD__ . '() is not implemented yet.'); + } + + /** + * {@inheritDoc} + */ + public function getAssociationMappedByTargetField($fieldName) + { + throw new \BadMethodCallException(__METHOD__ . '() is not implemented yet.'); } /** @@ -213,3 +2389,6 @@ public function newInstance() return $this->instantiator->instantiate($this->name); } } + +// Autoload legacy class to ensure class aliasing works as expected +class_exists(ClassMetadataInfo::class); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php index 967bae3695..2594479e7c 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php @@ -215,7 +215,7 @@ protected function newClassMetadataInstance($className) return new ClassMetadata($className); } - private function completeIdGeneratorMapping(ClassMetadataInfo $class) + private function completeIdGeneratorMapping(ClassMetadata $class) { $idGenOptions = $class->generatorOptions; switch ($class->generatorType) { diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php index 358a1a0b16..7ae86cd3ea 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php @@ -19,2230 +19,28 @@ namespace Doctrine\ODM\MongoDB\Mapping; -use Doctrine\ODM\MongoDB\Utility\CollectionHelper; -use Doctrine\ODM\MongoDB\LockException; -use Doctrine\ODM\MongoDB\Proxy\Proxy; -use Doctrine\ODM\MongoDB\Types\Type; -use InvalidArgumentException; use const E_USER_DEPRECATED; +use function class_exists; +use function sprintf; use function trigger_error; -/** - * A ClassMetadata instance holds all the object-document mapping metadata - * of a document and it's references. - * - * 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). - * - * @since 1.0 - */ -class ClassMetadataInfo implements \Doctrine\Common\Persistence\Mapping\ClassMetadata -{ - /* The Id generator types. */ - /** - * AUTO means Doctrine will automatically create a new \MongoId instance for us. - */ - const GENERATOR_TYPE_AUTO = 1; - - /** - * INCREMENT means a separate collection is used for maintaining and incrementing id generation. - * Offers full portability. - */ - const GENERATOR_TYPE_INCREMENT = 2; - - /** - * UUID means Doctrine will generate a uuid for us. - */ - const GENERATOR_TYPE_UUID = 3; - - /** - * ALNUM means Doctrine will generate Alpha-numeric string identifiers, using the INCREMENT - * generator to ensure identifier uniqueness - */ - const GENERATOR_TYPE_ALNUM = 4; - - /** - * CUSTOM means Doctrine expect a class parameter. It will then try to initiate that class - * and pass other options to the generator. It will throw an Exception if the class - * does not exist or if an option was passed for that there is not setter in the new - * generator class. - * - * The class will have to be a subtype of AbstractIdGenerator. - */ - const GENERATOR_TYPE_CUSTOM = 5; - - /** - * NONE means Doctrine will not generate any id for us and you are responsible for manually - * assigning an id. - */ - const GENERATOR_TYPE_NONE = 6; - - /** - * Default discriminator field name. - * - * This is used for associations value for associations where a that do not define a "targetDocument" or - * "discriminatorField" option in their mapping. - */ - const DEFAULT_DISCRIMINATOR_FIELD = '_doctrine_class_name'; - - const REFERENCE_ONE = 1; - const REFERENCE_MANY = 2; - const EMBED_ONE = 3; - const EMBED_MANY = 4; - const MANY = 'many'; - const ONE = 'one'; - - /** - * The types of storeAs references - */ - const REFERENCE_STORE_AS_ID = 'id'; - const REFERENCE_STORE_AS_DB_REF = 'dbRef'; - const REFERENCE_STORE_AS_DB_REF_WITH_DB = 'dbRefWithDb'; - const REFERENCE_STORE_AS_REF = 'ref'; - - /* The inheritance mapping types */ - /** - * NONE means the class does not participate in an inheritance hierarchy - * and therefore does not need an inheritance mapping type. - */ - const INHERITANCE_TYPE_NONE = 1; - - /** - * SINGLE_COLLECTION means the class will be persisted according to the rules of - * Single Collection Inheritance. - */ - const INHERITANCE_TYPE_SINGLE_COLLECTION = 2; - - /** - * COLLECTION_PER_CLASS means the class will be persisted according to the rules - * of Concrete Collection Inheritance. - */ - const INHERITANCE_TYPE_COLLECTION_PER_CLASS = 3; - - /** - * DEFERRED_IMPLICIT means that changes of entities are calculated at commit-time - * by doing a property-by-property comparison with the original data. This will - * be done for all entities that are in MANAGED state at commit-time. - * - * This is the default change tracking policy. - */ - const CHANGETRACKING_DEFERRED_IMPLICIT = 1; - - /** - * DEFERRED_EXPLICIT means that changes of entities are calculated at commit-time - * by doing a property-by-property comparison with the original data. This will - * be done only for entities that were explicitly saved (through persist() or a cascade). - */ - const CHANGETRACKING_DEFERRED_EXPLICIT = 2; - - /** - * NOTIFY means that Doctrine relies on the entities sending out notifications - * when their properties change. Such entity classes must implement - * the NotifyPropertyChanged interface. - */ - const CHANGETRACKING_NOTIFY = 3; - - /** - * SET means that fields will be written to the database using a $set operator - */ - const STORAGE_STRATEGY_SET = 'set'; - - /** - * INCREMENT means that fields will be written to the database by calculating - * the difference and using the $inc operator - */ - const STORAGE_STRATEGY_INCREMENT = 'increment'; - - const STORAGE_STRATEGY_PUSH_ALL = 'pushAll'; - const STORAGE_STRATEGY_ADD_TO_SET = 'addToSet'; - const STORAGE_STRATEGY_ATOMIC_SET = 'atomicSet'; - const STORAGE_STRATEGY_ATOMIC_SET_ARRAY = 'atomicSetArray'; - const STORAGE_STRATEGY_SET_ARRAY = 'setArray'; - - /** - * READ-ONLY: The name of the mongo database the document is mapped to. - */ - public $db; - - /** - * READ-ONLY: The name of the mongo collection the document is mapped to. - */ - public $collection; - - /** - * READ-ONLY: If the collection should be a fixed size. - */ - public $collectionCapped; - - /** - * READ-ONLY: If the collection is fixed size, its size in bytes. - */ - public $collectionSize; - - /** - * READ-ONLY: If the collection is fixed size, the maximum number of elements to store in the collection. - */ - public $collectionMax; - - /** - * READ-ONLY Describes how MongoDB clients route read operations to the members of a replica set. - */ - public $readPreference; - - /** - * READ-ONLY Associated with readPreference Allows to specify criteria so that your application can target read - * operations to specific members, based on custom parameters. - */ - public $readPreferenceTags; - - /** - * READ-ONLY: Describes the level of acknowledgement requested from MongoDB for write operations. - */ - public $writeConcern; - - /** - * READ-ONLY: The field name of the document identifier. - */ - public $identifier; - - /** - * READ-ONLY: The field that stores a file reference and indicates the - * document is a file and should be stored on the MongoGridFS. - */ - public $file; - - /** - * READ-ONLY: The field that stores the calculated distance when performing geo spatial - * queries. - */ - public $distance; - - /** - * READ-ONLY: Whether or not reads for this class are okay to read from a slave. - * - * @deprecated in version 1.2 and will be removed in 2.0. - */ - public $slaveOkay; - - /** - * READ-ONLY: The array of indexes for the document collection. - */ - public $indexes = array(); - - /** - * READ-ONLY: Keys and options describing shard key. Only for sharded collections. - */ - public $shardKey; - - /** - * READ-ONLY: Whether or not queries on this document should require indexes. - * - * @deprecated property was deprecated in 1.2 and will be removed in 2.0 - */ - public $requireIndexes = false; - - /** - * READ-ONLY: The name of the document class. - */ - public $name; - - /** - * READ-ONLY: The namespace the document class is contained in. - * - * @var string - * @deprecated Will be removed in 2.0. Use fully qualified class names instead - */ - public $namespace; - - /** - * READ-ONLY: The name of the document class that is at the root of the mapped document inheritance - * hierarchy. If the document is not part of a mapped inheritance hierarchy this is the same - * as {@link $documentName}. - * - * @var string - */ - public $rootDocumentName; - - /** - * The name of the custom repository class used for the document class. - * (Optional). - * - * @var string - */ - public $customRepositoryClassName; - - /** - * READ-ONLY: The names of the parent classes (ancestors). - * - * @var array - */ - public $parentClasses = array(); - - /** - * READ-ONLY: The names of all subclasses (descendants). - * - * @var array - */ - public $subClasses = array(); - - /** - * The ReflectionProperty instances of the mapped class. - * - * @var \ReflectionProperty[] - */ - public $reflFields = array(); - - /** - * READ-ONLY: The inheritance mapping type used by the class. - * - * @var integer - */ - public $inheritanceType = self::INHERITANCE_TYPE_NONE; - - /** - * READ-ONLY: The Id generator type used by the class. - * - * @var string - */ - public $generatorType = self::GENERATOR_TYPE_AUTO; - - /** - * READ-ONLY: The Id generator options. - * - * @var array - */ - public $generatorOptions = array(); - - /** - * READ-ONLY: The ID generator used for generating IDs for this class. - * - * @var \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator - */ - public $idGenerator; - - /** - * READ-ONLY: The field mappings of the class. - * Keys are field names and values are mapping definitions. - * - * The mapping definition array has the following values: - * - * - fieldName (string) - * The name of the field in the Document. - * - * - id (boolean, optional) - * Marks the field as the primary key of the document. Multiple fields of an - * document can have the id attribute, forming a composite key. - * - * @var array - */ - public $fieldMappings = array(); - - /** - * READ-ONLY: The association mappings of the class. - * Keys are field names and values are mapping definitions. - * - * @var array - */ - public $associationMappings = array(); - - /** - * READ-ONLY: Array of fields to also load with a given method. - * - * @var array - */ - public $alsoLoadMethods = array(); - - /** - * READ-ONLY: The registered lifecycle callbacks for documents of this class. - * - * @var array - */ - public $lifecycleCallbacks = array(); - - /** - * READ-ONLY: The discriminator value of this class. - * - * This does only apply to the JOINED and SINGLE_COLLECTION inheritance mapping strategies - * where a discriminator field is used. - * - * @var mixed - * @see discriminatorField - */ - public $discriminatorValue; - - /** - * READ-ONLY: The discriminator map of all mapped classes in the hierarchy. - * - * This does only apply to the SINGLE_COLLECTION inheritance mapping strategy - * where a discriminator field is used. - * - * @var mixed - * @see discriminatorField - */ - public $discriminatorMap = array(); - - /** - * READ-ONLY: The definition of the discriminator field used in SINGLE_COLLECTION - * inheritance mapping. - * - * @var string - */ - public $discriminatorField; - - /** - * READ-ONLY: The default value for discriminatorField in case it's not set in the document - * - * @var string - * @see discriminatorField - */ - public $defaultDiscriminatorValue; - - /** - * READ-ONLY: Whether this class describes the mapping of a mapped superclass. - * - * @var boolean - */ - public $isMappedSuperclass = false; - - /** - * READ-ONLY: Whether this class describes the mapping of a embedded document. - * - * @var boolean - */ - public $isEmbeddedDocument = false; - - /** - * READ-ONLY: Whether this class describes the mapping of an aggregation result document. - * - * @var boolean - */ - public $isQueryResultDocument = false; - - /** - * READ-ONLY: The policy used for change-tracking on entities of this class. - * - * @var integer - */ - public $changeTrackingPolicy = self::CHANGETRACKING_DEFERRED_IMPLICIT; - - /** - * READ-ONLY: A flag for whether or not instances of this class are to be versioned - * with optimistic locking. - * - * @var boolean $isVersioned - */ - public $isVersioned; - - /** - * READ-ONLY: The name of the field which is used for versioning in optimistic locking (if any). - * - * @var mixed $versionField - */ - public $versionField; - - /** - * READ-ONLY: A flag for whether or not instances of this class are to allow pessimistic - * locking. - * - * @var boolean $isLockable - */ - public $isLockable; - - /** - * READ-ONLY: The name of the field which is used for locking a document. - * - * @var mixed $lockField - */ - public $lockField; - - /** - * The ReflectionClass instance of the mapped class. - * - * @var \ReflectionClass - */ - public $reflClass; - - /** - * READ_ONLY: A flag for whether or not this document is read-only. - * - * @var bool - */ - public $isReadOnly; - - /** - * Initializes a new ClassMetadata instance that will hold the object-document mapping - * metadata of the class with the given name. - * - * @param string $documentName The name of the document class the new instance is used for. - */ - public function __construct($documentName) - { - $this->name = $documentName; - $this->rootDocumentName = $documentName; - } - - /** - * Helper method to get reference id of ref* type references - * @param mixed $reference - * @param string $storeAs - * @return mixed - * @internal - */ - public static function getReferenceId($reference, $storeAs) - { - return $storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_ID ? $reference : $reference[ClassMetadataInfo::getReferencePrefix($storeAs) . 'id']; - } - - /** - * Returns the reference prefix used for a reference - * @param string $storeAs - * @return string - */ - private static function getReferencePrefix($storeAs) - { - if (!in_array($storeAs, [ClassMetadataInfo::REFERENCE_STORE_AS_REF, ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF, ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB])) { - throw new \LogicException('Can only get a reference prefix for DBRef and reference arrays'); - } - - return $storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_REF ? '' : '$'; - } - - /** - * Returns a fully qualified field name for a given reference - * @param string $storeAs - * @param string $pathPrefix The field path prefix - * @return string - * @internal - */ - public static function getReferenceFieldName($storeAs, $pathPrefix = '') - { - if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_ID) { - return $pathPrefix; - } - - return ($pathPrefix ? $pathPrefix . '.' : '') . static::getReferencePrefix($storeAs) . 'id'; - } - - /** - * {@inheritDoc} - */ - public function getReflectionClass() - { - if ( ! $this->reflClass) { - $this->reflClass = new \ReflectionClass($this->name); - } - - return $this->reflClass; - } - - /** - * {@inheritDoc} - */ - public function isIdentifier($fieldName) - { - return $this->identifier === $fieldName; - } - - /** - * INTERNAL: - * Sets the mapped identifier field of this class. - * - * @param string $identifier - */ - public function setIdentifier($identifier) - { - $this->identifier = $identifier; - } - - /** - * {@inheritDoc} - * - * Since MongoDB only allows exactly one identifier field - * this will always return an array with only one value - */ - public function getIdentifier() - { - return array($this->identifier); - } - - /** - * {@inheritDoc} - * - * Since MongoDB only allows exactly one identifier field - * this will always return an array with only one value - */ - public function getIdentifierFieldNames() - { - return array($this->identifier); - } - - /** - * {@inheritDoc} - */ - public function hasField($fieldName) - { - return isset($this->fieldMappings[$fieldName]); - } - - /** - * Sets the inheritance type used by the class and it's subclasses. - * - * @param integer $type - */ - public function setInheritanceType($type) - { - $this->inheritanceType = $type; - } - - /** - * Checks whether a mapped field is inherited from an entity superclass. - * - * @param string $fieldName - * - * @return boolean TRUE if the field is inherited, FALSE otherwise. - */ - public function isInheritedField($fieldName) - { - return isset($this->fieldMappings[$fieldName]['inherited']); - } - - /** - * Registers a custom repository class for the document class. - * - * @param string $repositoryClassName The class name of the custom repository. - */ - public function setCustomRepositoryClass($repositoryClassName) - { - if ($this->isEmbeddedDocument || $this->isQueryResultDocument) { - return; - } - - if ($repositoryClassName && strpos($repositoryClassName, '\\') === false && strlen($this->namespace)) { - @trigger_error(sprintf('Class "%s" relies on same-namespace resolution for its repository class. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $this->name), E_USER_DEPRECATED); - - $repositoryClassName = $this->namespace . '\\' . $repositoryClassName; - } - - $this->customRepositoryClassName = $repositoryClassName; - } - - /** - * Dispatches the lifecycle event of the given document by invoking all - * registered callbacks. - * - * @param string $event Lifecycle event - * @param object $document Document on which the event occurred - * @param array $arguments Arguments to pass to all callbacks - * @throws \InvalidArgumentException if document class is not this class or - * a Proxy of this class - */ - public function invokeLifecycleCallbacks($event, $document, array $arguments = null) - { - if ( ! $document instanceof $this->name) { - throw new \InvalidArgumentException(sprintf('Expected document class "%s"; found: "%s"', $this->name, get_class($document))); - } - - if (empty($this->lifecycleCallbacks[$event])) { - return; - } - - foreach ($this->lifecycleCallbacks[$event] as $callback) { - if ($arguments !== null) { - call_user_func_array(array($document, $callback), $arguments); - } else { - $document->$callback(); - } - } - } - - /** - * Checks whether the class has callbacks registered for a lifecycle event. - * - * @param string $event Lifecycle event - * - * @return boolean - */ - public function hasLifecycleCallbacks($event) - { - return ! empty($this->lifecycleCallbacks[$event]); - } - - /** - * Gets the registered lifecycle callbacks for an event. - * - * @param string $event - * @return array - */ - public function getLifecycleCallbacks($event) - { - return isset($this->lifecycleCallbacks[$event]) ? $this->lifecycleCallbacks[$event] : array(); - } - - /** - * Adds a lifecycle callback for documents of this class. - * - * If the callback is already registered, this is a NOOP. - * - * @param string $callback - * @param string $event - */ - public function addLifecycleCallback($callback, $event) - { - if (isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) { - return; - } - - $this->lifecycleCallbacks[$event][] = $callback; - } - - /** - * Sets the lifecycle callbacks for documents of this class. - * - * Any previously registered callbacks are overwritten. - * - * @param array $callbacks - */ - public function setLifecycleCallbacks(array $callbacks) - { - $this->lifecycleCallbacks = $callbacks; - } - - /** - * Registers a method for loading document data before field hydration. - * - * Note: A method may be registered multiple times for different fields. - * it will be invoked only once for the first field found. - * - * @param string $method Method name - * @param array|string $fields Database field name(s) - */ - public function registerAlsoLoadMethod($method, $fields) - { - $this->alsoLoadMethods[$method] = is_array($fields) ? $fields : array($fields); - } - - /** - * Sets the AlsoLoad methods for documents of this class. - * - * Any previously registered methods are overwritten. - * - * @param array $methods - */ - public function setAlsoLoadMethods(array $methods) - { - $this->alsoLoadMethods = $methods; - } - - /** - * Sets the discriminator field. - * - * The field name is the the unmapped database field. Discriminator values - * are only used to discern the hydration class and are not mapped to class - * properties. - * - * @param string $discriminatorField - * - * @throws MappingException If the discriminator field conflicts with the - * "name" attribute of a mapped field. - */ - public function setDiscriminatorField($discriminatorField) - { - if ($discriminatorField === null) { - $this->discriminatorField = null; - - return; - } - - // Handle array argument with name/fieldName keys for BC - if (is_array($discriminatorField)) { - if (isset($discriminatorField['name'])) { - $discriminatorField = $discriminatorField['name']; - } elseif (isset($discriminatorField['fieldName'])) { - $discriminatorField = $discriminatorField['fieldName']; - } - } - - foreach ($this->fieldMappings as $fieldMapping) { - if ($discriminatorField == $fieldMapping['name']) { - throw MappingException::discriminatorFieldConflict($this->name, $discriminatorField); - } - } - - $this->discriminatorField = $discriminatorField; - } - - /** - * Sets the discriminator values used by this class. - * Used for JOINED and SINGLE_TABLE inheritance mapping strategies. - * - * @param array $map - * - * @throws MappingException - */ - public function setDiscriminatorMap(array $map) - { - foreach ($map as $value => $className) { - if (strpos($className, '\\') === false && strlen($this->namespace)) { - @trigger_error(sprintf('Class "%s" relies on same-namespace resolution in its discriminator map for value "%s". This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $this->name, $value), E_USER_DEPRECATED); - - $className = $this->namespace . '\\' . $className; - } - $this->discriminatorMap[$value] = $className; - if ($this->name == $className) { - $this->discriminatorValue = $value; - } else { - if ( ! class_exists($className)) { - throw MappingException::invalidClassInDiscriminatorMap($className, $this->name); - } - if (is_subclass_of($className, $this->name)) { - $this->subClasses[] = $className; - } - } - } - } - - /** - * Sets the default discriminator value to be used for this class - * Used for JOINED and SINGLE_TABLE inheritance mapping strategies if the document has no discriminator value - * - * @param string $defaultDiscriminatorValue - * - * @throws MappingException - */ - public function setDefaultDiscriminatorValue($defaultDiscriminatorValue) - { - if ($defaultDiscriminatorValue === null) { - $this->defaultDiscriminatorValue = null; - - return; - } - - if (!array_key_exists($defaultDiscriminatorValue, $this->discriminatorMap)) { - throw MappingException::invalidDiscriminatorValue($defaultDiscriminatorValue, $this->name); - } - - $this->defaultDiscriminatorValue = $defaultDiscriminatorValue; - } - - /** - * Sets the discriminator value for this class. - * Used for JOINED/SINGLE_TABLE inheritance and multiple document types in a single - * collection. - * - * @param string $value - */ - public function setDiscriminatorValue($value) - { - $this->discriminatorMap[$value] = $this->name; - $this->discriminatorValue = $value; - } - - /** - * Sets the slaveOkay option applied to collections for this class. - * - * @param boolean|null $slaveOkay - * - * @deprecated in version 1.2 and will be removed in 2.0. - * - * @throws MappingException - */ - public function setSlaveOkay($slaveOkay) - { - if ($slaveOkay) { - @trigger_error( - sprintf('%s was deprecated in version 1.2 and will be removed in 2.0.', __METHOD__), - E_USER_DEPRECATED - ); - } - - if ($this->readPreference) { - throw MappingException::canNotCombineReadPreferenceAndSlaveOkay($this->getName()); - } - $this->slaveOkay = $slaveOkay === null ? null : (boolean) $slaveOkay; - } - - /** - * Add a index for this Document. - * - * @param array $keys Array of keys for the index. - * @param array $options Array of options for the index. - */ - public function addIndex($keys, array $options = array()) - { - $this->indexes[] = array( - 'keys' => array_map(function($value) { - if ($value == 1 || $value == -1) { - return (int) $value; - } - if (is_string($value)) { - $lower = strtolower($value); - if ($lower === 'asc') { - return 1; - } elseif ($lower === 'desc') { - return -1; - } - } - return $value; - }, $keys), - 'options' => $options - ); - } - - /** - * Set whether or not queries on this document should require indexes. - * - * @param bool $requireIndexes - * - * @deprecated method was deprecated in 1.2 and will be removed in 2.0 - */ - public function setRequireIndexes($requireIndexes) - { - if ($requireIndexes) { - @trigger_error( - 'requireIndexes was deprecated in version 1.2 and will be removed altogether in 2.0.', - E_USER_DEPRECATED - ); - } - - $this->requireIndexes = $requireIndexes; - } - - /** - * Returns the array of indexes for this Document. - * - * @return array $indexes The array of indexes. - */ - public function getIndexes() - { - return $this->indexes; - } - - /** - * Checks whether this document has indexes or not. - * - * @return boolean - */ - public function hasIndexes() - { - return $this->indexes ? true : false; - } - - /** - * Set shard key for this Document. - * - * @param array $keys Array of document keys. - * @param array $options Array of sharding options. - * - * @throws MappingException - */ - public function setShardKey(array $keys, array $options = array()) - { - if ($this->inheritanceType === self::INHERITANCE_TYPE_SINGLE_COLLECTION && !is_null($this->shardKey)) { - throw MappingException::shardKeyInSingleCollInheritanceSubclass($this->getName()); - } - - if ($this->isEmbeddedDocument) { - throw MappingException::embeddedDocumentCantHaveShardKey($this->getName()); - } - - foreach (array_keys($keys) as $field) { - if (! isset($this->fieldMappings[$field])) { - continue; - } - - if (in_array($this->fieldMappings[$field]['type'], ['many', 'collection'])) { - throw MappingException::noMultiKeyShardKeys($this->getName(), $field); - } - - if ($this->fieldMappings[$field]['strategy'] !== static::STORAGE_STRATEGY_SET) { - throw MappingException::onlySetStrategyAllowedInShardKey($this->getName(), $field); - } - } - - $this->shardKey = array( - 'keys' => array_map(function($value) { - if ($value == 1 || $value == -1) { - return (int) $value; - } - if (is_string($value)) { - $lower = strtolower($value); - if ($lower === 'asc') { - return 1; - } elseif ($lower === 'desc') { - return -1; - } - } - return $value; - }, $keys), - 'options' => $options - ); - } - - /** - * @return array - */ - public function getShardKey() - { - return $this->shardKey; - } - - /** - * Checks whether this document has shard key or not. - * - * @return bool - */ - public function isSharded() - { - return $this->shardKey ? true : false; - } - - /** - * Sets the read preference used by this class. - * - * @param string $readPreference - * @param array|null $tags - * - * @throws MappingException - */ - public function setReadPreference($readPreference, $tags) - { - if ($this->slaveOkay) { - throw MappingException::canNotCombineReadPreferenceAndSlaveOkay($this->getName()); - } - $this->readPreference = $readPreference; - $this->readPreferenceTags = $tags; - } - - /** - * Sets the write concern used by this class. - * - * @param string $writeConcern - */ - public function setWriteConcern($writeConcern) - { - $this->writeConcern = $writeConcern; - } - - /** - * @return string - */ - public function getWriteConcern() - { - return $this->writeConcern; - } - - /** - * Whether there is a write concern configured for this class. - * - * @return bool - */ - public function hasWriteConcern() - { - return $this->writeConcern !== null; - } - - /** - * Sets the change tracking policy used by this class. - * - * @param integer $policy - */ - public function setChangeTrackingPolicy($policy) - { - $this->changeTrackingPolicy = $policy; - } - - /** - * Whether the change tracking policy of this class is "deferred explicit". - * - * @return boolean - */ - public function isChangeTrackingDeferredExplicit() - { - return $this->changeTrackingPolicy == self::CHANGETRACKING_DEFERRED_EXPLICIT; - } - - /** - * Whether the change tracking policy of this class is "deferred implicit". - * - * @return boolean - */ - public function isChangeTrackingDeferredImplicit() - { - return $this->changeTrackingPolicy == self::CHANGETRACKING_DEFERRED_IMPLICIT; - } - - /** - * Whether the change tracking policy of this class is "notify". - * - * @return boolean - */ - public function isChangeTrackingNotify() - { - return $this->changeTrackingPolicy == self::CHANGETRACKING_NOTIFY; - } - - /** - * Gets the ReflectionProperties of the mapped class. - * - * @return array An array of ReflectionProperty instances. - */ - public function getReflectionProperties() - { - return $this->reflFields; - } - - /** - * Gets a ReflectionProperty for a specific field of the mapped class. - * - * @param string $name - * - * @return \ReflectionProperty - */ - public function getReflectionProperty($name) - { - return $this->reflFields[$name]; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return $this->name; - } - - /** - * The namespace this Document class belongs to. - * - * @return string $namespace The namespace name. - * @deprecated will be removed in 2.0 - */ - public function getNamespace() - { - @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in 2.0.', __METHOD__), E_USER_DEPRECATED); - - return $this->namespace; - } - - /** - * Returns the database this Document is mapped to. - * - * @return string $db The database name. - */ - public function getDatabase() - { - return $this->db; - } - - /** - * Set the database this Document is mapped to. - * - * @param string $db The database name - */ - public function setDatabase($db) - { - $this->db = $db; - } - - /** - * Get the collection this Document is mapped to. - * - * @return string $collection The collection name. - */ - public function getCollection() - { - return $this->collection; - } - - /** - * Sets the collection this Document is mapped to. - * - * @param array|string $name - * - * @throws \InvalidArgumentException - */ - public function setCollection($name) - { - if (is_array($name)) { - if ( ! isset($name['name'])) { - throw new \InvalidArgumentException('A name key is required when passing an array to setCollection()'); - } - $this->collectionCapped = isset($name['capped']) ? $name['capped'] : false; - $this->collectionSize = isset($name['size']) ? $name['size'] : 0; - $this->collectionMax = isset($name['max']) ? $name['max'] : 0; - $this->collection = $name['name']; - } else { - $this->collection = $name; - } - } - - /** - * Get whether or not the documents collection is capped. - * - * @return boolean - */ - public function getCollectionCapped() - { - return $this->collectionCapped; - } - - /** - * Set whether or not the documents collection is capped. - * - * @param boolean $bool - */ - public function setCollectionCapped($bool) - { - $this->collectionCapped = $bool; - } - - /** - * Get the collection size - * - * @return integer - */ - public function getCollectionSize() - { - return $this->collectionSize; - } - - /** - * Set the collection size. - * - * @param integer $size - */ - public function setCollectionSize($size) - { - $this->collectionSize = $size; - } - - /** - * Get the collection max. - * - * @return integer - */ - public function getCollectionMax() - { - return $this->collectionMax; - } - - /** - * Set the collection max. - * - * @param integer $max - */ - public function setCollectionMax($max) - { - $this->collectionMax = $max; - } - - /** - * Returns TRUE if this Document is mapped to a collection FALSE otherwise. - * - * @return boolean - */ - public function isMappedToCollection() - { - return $this->collection ? true : false; - } - - /** - * Returns TRUE if this Document is a file to be stored on the MongoGridFS FALSE otherwise. - * - * @return boolean - */ - public function isFile() - { - return $this->file ? true : false; - } - - /** - * Returns the file field name. - * - * @return string $file The file field name. - */ - public function getFile() - { - return $this->file; - } - - /** - * Set the field name that stores the grid file. - * - * @param string $file - */ - public function setFile($file) - { - $this->file = $file; - } - - /** - * Returns the distance field name. - * - * @return string $distance The distance field name. - */ - public function getDistance() - { - return $this->distance; - } - - /** - * Set the field name that stores the distance. - * - * @param string $distance - */ - public function setDistance($distance) - { - $this->distance = $distance; - } - - /** - * Map a field. - * - * @param array $mapping The mapping information. - * - * @return array - * - * @throws MappingException - */ - public function mapField(array $mapping) - { - if ( ! isset($mapping['fieldName']) && isset($mapping['name'])) { - $mapping['fieldName'] = $mapping['name']; - } - if ( ! isset($mapping['fieldName'])) { - throw MappingException::missingFieldName($this->name); - } - if ( ! isset($mapping['name'])) { - $mapping['name'] = $mapping['fieldName']; - } - if ($this->identifier === $mapping['name'] && empty($mapping['id'])) { - throw MappingException::mustNotChangeIdentifierFieldsType($this->name, $mapping['name']); - } - if (isset($this->fieldMappings[$mapping['fieldName']])) { - //throw MappingException::duplicateFieldMapping($this->name, $mapping['fieldName']); - } - if ($this->discriminatorField !== null && $this->discriminatorField == $mapping['name']) { - throw MappingException::discriminatorFieldConflict($this->name, $this->discriminatorField); - } - if (isset($mapping['targetDocument']) && strpos($mapping['targetDocument'], '\\') === false && strlen($this->namespace)) { - @trigger_error(sprintf('Field "%s" in class "%s" relies on same-namespace resolution for the target document. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $mapping['name'], $this->name), E_USER_DEPRECATED); - - $mapping['targetDocument'] = $this->namespace . '\\' . $mapping['targetDocument']; - } - - if (isset($mapping['collectionClass'])) { - if (strpos($mapping['collectionClass'], '\\') === false && strlen($this->namespace)) { - @trigger_error(sprintf('Field "%s" in class "%s" relies on same-namespace resolution for the collection class. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $mapping['name'], $this->name), E_USER_DEPRECATED); - - $mapping['collectionClass'] = $this->namespace . '\\' . $mapping['collectionClass']; - } - $mapping['collectionClass'] = ltrim($mapping['collectionClass'], '\\'); - } - if ( ! empty($mapping['collectionClass'])) { - $rColl = new \ReflectionClass($mapping['collectionClass']); - if ( ! $rColl->implementsInterface('Doctrine\\Common\\Collections\\Collection')) { - throw MappingException::collectionClassDoesNotImplementCommonInterface($this->name, $mapping['fieldName'], $mapping['collectionClass']); - } - } - - if (isset($mapping['discriminatorMap'])) { - foreach ($mapping['discriminatorMap'] as $key => $class) { - if (strpos($class, '\\') === false && strlen($this->namespace)) { - @trigger_error(sprintf('Field "%s" in class "%s" relies on same-namespace resolution in its discriminator map for value "%s". This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $mapping['name'], $this->name, $key), E_USER_DEPRECATED); - - $mapping['discriminatorMap'][$key] = $this->namespace . '\\' . $class; - } - } - } - - if (isset($mapping['cascade']) && isset($mapping['embedded'])) { - throw MappingException::cascadeOnEmbeddedNotAllowed($this->name, $mapping['fieldName']); - } - - $cascades = isset($mapping['cascade']) ? array_map('strtolower', (array) $mapping['cascade']) : array(); - - if (in_array('all', $cascades) || isset($mapping['embedded'])) { - $cascades = array('remove', 'persist', 'refresh', 'merge', 'detach'); - } - - if (isset($mapping['embedded'])) { - unset($mapping['cascade']); - } elseif (isset($mapping['cascade'])) { - $mapping['cascade'] = $cascades; - } - - $mapping['isCascadeRemove'] = in_array('remove', $cascades); - $mapping['isCascadePersist'] = in_array('persist', $cascades); - $mapping['isCascadeRefresh'] = in_array('refresh', $cascades); - $mapping['isCascadeMerge'] = in_array('merge', $cascades); - $mapping['isCascadeDetach'] = in_array('detach', $cascades); - - if (isset($mapping['type']) && $mapping['type'] === 'file') { - $mapping['file'] = true; - } - if (isset($mapping['type']) && $mapping['type'] === 'increment') { - $mapping['strategy'] = self::STORAGE_STRATEGY_INCREMENT; - } - if (isset($mapping['file']) && $mapping['file'] === true) { - $this->file = $mapping['fieldName']; - $mapping['name'] = 'file'; - } - if (isset($mapping['distance']) && $mapping['distance'] === true) { - $this->distance = $mapping['fieldName']; - } - if (isset($mapping['id']) && $mapping['id'] === true) { - $mapping['name'] = '_id'; - $this->identifier = $mapping['fieldName']; - if (isset($mapping['strategy'])) { - $this->generatorType = constant(ClassMetadata::class . '::GENERATOR_TYPE_' . strtoupper($mapping['strategy'])); - } - $this->generatorOptions = isset($mapping['options']) ? $mapping['options'] : array(); - switch ($this->generatorType) { - case self::GENERATOR_TYPE_AUTO: - $mapping['type'] = 'id'; - break; - default: - if ( ! empty($this->generatorOptions['type'])) { - $mapping['type'] = $this->generatorOptions['type']; - } elseif (empty($mapping['type'])) { - $mapping['type'] = $this->generatorType === self::GENERATOR_TYPE_INCREMENT ? 'int_id' : 'custom_id'; - } - } - unset($this->generatorOptions['type']); - } - - if ( ! isset($mapping['nullable'])) { - $mapping['nullable'] = false; - } - - // Synchronize the "simple" and "storeAs" mapping information for backwards compatibility - if (isset($mapping['simple']) && ($mapping['simple'] === true || $mapping['simple'] === 'true')) { - $mapping['storeAs'] = ClassMetadataInfo::REFERENCE_STORE_AS_ID; - @trigger_error('"simple" attribute of a reference is deprecated - use storeAs="id" instead.', E_USER_DEPRECATED); - } - // Provide the correct value for the "simple" field for backwards compatibility - if (isset($mapping['storeAs'])) { - $mapping['simple'] = $mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID; - } - - if (isset($mapping['reference']) - && isset($mapping['storeAs']) - && $mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID - && ! isset($mapping['targetDocument']) - ) { - throw MappingException::simpleReferenceRequiresTargetDocument($this->name, $mapping['fieldName']); - } - - if (isset($mapping['reference']) && empty($mapping['targetDocument']) && empty($mapping['discriminatorMap']) && - (isset($mapping['mappedBy']) || isset($mapping['inversedBy']))) { - throw MappingException::owningAndInverseReferencesRequireTargetDocument($this->name, $mapping['fieldName']); - } - - if ($this->isEmbeddedDocument && $mapping['type'] === 'many' && isset($mapping['strategy']) && CollectionHelper::isAtomic($mapping['strategy'])) { - throw MappingException::atomicCollectionStrategyNotAllowed($mapping['strategy'], $this->name, $mapping['fieldName']); - } - - if (isset($mapping['repositoryMethod']) && ! (empty($mapping['skip']) && empty($mapping['limit']) && empty($mapping['sort']))) { - @trigger_error( - sprintf( - "Combining 'repositoryMethod' with skip, limit or sort (used on '%s' in class '%s') was deprecated in 1.3 and will be removed in 2.0. Please include those in the repository method itself.", - $mapping['fieldName'], - $this->name - ), - E_USER_DEPRECATED - ); - } - - if (isset($mapping['reference']) && $mapping['type'] === 'one') { - $mapping['association'] = self::REFERENCE_ONE; - } - if (isset($mapping['reference']) && $mapping['type'] === 'many') { - $mapping['association'] = self::REFERENCE_MANY; - } - if (isset($mapping['embedded']) && $mapping['type'] === 'one') { - $mapping['association'] = self::EMBED_ONE; - } - if (isset($mapping['embedded']) && $mapping['type'] === 'many') { - $mapping['association'] = self::EMBED_MANY; - } - - if (isset($mapping['association']) && ! isset($mapping['targetDocument']) && ! isset($mapping['discriminatorField'])) { - $mapping['discriminatorField'] = self::DEFAULT_DISCRIMINATOR_FIELD; - } - - /* - if (isset($mapping['type']) && ($mapping['type'] === 'one' || $mapping['type'] === 'many')) { - $mapping['type'] = $mapping['type'] === 'one' ? self::ONE : self::MANY; - } - */ - if (isset($mapping['version'])) { - $mapping['notSaved'] = true; - $this->setVersionMapping($mapping); - } - if (isset($mapping['lock'])) { - $mapping['notSaved'] = true; - $this->setLockMapping($mapping); - } - $mapping['isOwningSide'] = true; - $mapping['isInverseSide'] = false; - if (isset($mapping['reference'])) { - if (isset($mapping['inversedBy']) && $mapping['inversedBy']) { - $mapping['isOwningSide'] = true; - $mapping['isInverseSide'] = false; - } - if (isset($mapping['mappedBy']) && $mapping['mappedBy']) { - $mapping['isInverseSide'] = true; - $mapping['isOwningSide'] = false; - } - if (isset($mapping['repositoryMethod'])) { - $mapping['isInverseSide'] = true; - $mapping['isOwningSide'] = false; - } - if (!isset($mapping['orphanRemoval'])) { - $mapping['orphanRemoval'] = false; - } - } - - if (!empty($mapping['prime']) && ($mapping['association'] !== self::REFERENCE_MANY || !$mapping['isInverseSide'])) { - throw MappingException::referencePrimersOnlySupportedForInverseReferenceMany($this->name, $mapping['fieldName']); - } - - $this->applyStorageStrategy($mapping); - - $this->fieldMappings[$mapping['fieldName']] = $mapping; - if (isset($mapping['association'])) { - $this->associationMappings[$mapping['fieldName']] = $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': - case $mapping['type'] == 'increment': - $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. - * - * @param array $mapping The mapping information. - */ - public function mapFile(array $mapping) - { - $mapping['file'] = true; - $mapping['type'] = 'file'; - $this->mapField($mapping); - } - - /** - * Map a single embedded document. - * - * @param array $mapping The mapping information. - */ - public function mapOneEmbedded(array $mapping) - { - $mapping['embedded'] = true; - $mapping['type'] = 'one'; - $this->mapField($mapping); - } - - /** - * Map a collection of embedded documents. - * - * @param array $mapping The mapping information. - */ - public function mapManyEmbedded(array $mapping) - { - $mapping['embedded'] = true; - $mapping['type'] = 'many'; - $this->mapField($mapping); - } - - /** - * Map a single document reference. - * - * @param array $mapping The mapping information. - */ - public function mapOneReference(array $mapping) - { - $mapping['reference'] = true; - $mapping['type'] = 'one'; - $this->mapField($mapping); - } - - /** - * Map a collection of document references. - * - * @param array $mapping The mapping information. - */ - public function mapManyReference(array $mapping) - { - $mapping['reference'] = true; - $mapping['type'] = 'many'; - $this->mapField($mapping); - } - - /** - * INTERNAL: - * Adds a field mapping without completing/validating it. - * This is mainly used to add inherited field mappings to derived classes. - * - * @param array $fieldMapping - */ - public function addInheritedFieldMapping(array $fieldMapping) - { - $this->fieldMappings[$fieldMapping['fieldName']] = $fieldMapping; - - if (isset($fieldMapping['association'])) { - $this->associationMappings[$fieldMapping['fieldName']] = $fieldMapping; - } - } - - /** - * INTERNAL: - * Adds an association mapping without completing/validating it. - * This is mainly used to add inherited association mappings to derived classes. - * - * @param array $mapping - * - * @return void - * - * @throws MappingException - */ - public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/) - { - $this->associationMappings[$mapping['fieldName']] = $mapping; - } - - /** - * Checks whether the class has a mapped association with the given field name. - * - * @param string $fieldName - * @return boolean - */ - public function hasReference($fieldName) - { - return isset($this->fieldMappings[$fieldName]['reference']); - } - - /** - * Checks whether the class has a mapped embed with the given field name. - * - * @param string $fieldName - * @return boolean - */ - public function hasEmbed($fieldName) - { - return isset($this->fieldMappings[$fieldName]['embedded']); - } - - /** - * {@inheritDoc} - * - * Checks whether the class has a mapped association (embed or reference) with the given field name. - */ - public function hasAssociation($fieldName) - { - return $this->hasReference($fieldName) || $this->hasEmbed($fieldName); - } - - /** - * {@inheritDoc} - * - * Checks whether the class has a mapped reference or embed for the specified field and - * is a single valued association. - */ - public function isSingleValuedAssociation($fieldName) - { - return $this->isSingleValuedReference($fieldName) || $this->isSingleValuedEmbed($fieldName); - } - - /** - * {@inheritDoc} - * - * Checks whether the class has a mapped reference or embed for the specified field and - * is a collection valued association. - */ - public function isCollectionValuedAssociation($fieldName) - { - return $this->isCollectionValuedReference($fieldName) || $this->isCollectionValuedEmbed($fieldName); - } - - /** - * Checks whether the class has a mapped association for the specified field - * and if yes, checks whether it is a single-valued association (to-one). - * - * @param string $fieldName - * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise. - */ - public function isSingleValuedReference($fieldName) - { - return isset($this->fieldMappings[$fieldName]['association']) && - $this->fieldMappings[$fieldName]['association'] === self::REFERENCE_ONE; - } - - /** - * Checks whether the class has a mapped association for the specified field - * and if yes, checks whether it is a collection-valued association (to-many). - * - * @param string $fieldName - * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise. - */ - public function isCollectionValuedReference($fieldName) - { - return isset($this->fieldMappings[$fieldName]['association']) && - $this->fieldMappings[$fieldName]['association'] === self::REFERENCE_MANY; - } - - /** - * Checks whether the class has a mapped embedded document for the specified field - * and if yes, checks whether it is a single-valued association (to-one). - * - * @param string $fieldName - * @return boolean TRUE if the association exists and is single-valued, FALSE otherwise. - */ - public function isSingleValuedEmbed($fieldName) - { - return isset($this->fieldMappings[$fieldName]['association']) && - $this->fieldMappings[$fieldName]['association'] === self::EMBED_ONE; - } - - /** - * Checks whether the class has a mapped embedded document for the specified field - * and if yes, checks whether it is a collection-valued association (to-many). - * - * @param string $fieldName - * @return boolean TRUE if the association exists and is collection-valued, FALSE otherwise. - */ - public function isCollectionValuedEmbed($fieldName) - { - return isset($this->fieldMappings[$fieldName]['association']) && - $this->fieldMappings[$fieldName]['association'] === self::EMBED_MANY; - } - - /** - * Sets the ID generator used to generate IDs for instances of this class. - * - * @param \Doctrine\ODM\MongoDB\Id\AbstractIdGenerator $generator - */ - public function setIdGenerator($generator) - { - $this->idGenerator = $generator; - } - - /** - * Casts the identifier to its portable PHP type. - * - * @param mixed $id - * @return mixed $id - */ - public function getPHPIdentifierValue($id) - { - $idType = $this->fieldMappings[$this->identifier]['type']; - return Type::getType($idType)->convertToPHPValue($id); - } - - /** - * Casts the identifier to its database type. - * - * @param mixed $id - * @return mixed $id - */ - public function getDatabaseIdentifierValue($id) - { - $idType = $this->fieldMappings[$this->identifier]['type']; - return Type::getType($idType)->convertToDatabaseValue($id); - } - - /** - * Sets the document identifier of a document. - * - * The value will be converted to a PHP type before being set. - * - * @param object $document - * @param mixed $id - */ - public function setIdentifierValue($document, $id) - { - $id = $this->getPHPIdentifierValue($id); - $this->reflFields[$this->identifier]->setValue($document, $id); - } - - /** - * Gets the document identifier as a PHP type. - * - * @param object $document - * @return mixed $id - */ - public function getIdentifierValue($document) - { - return $this->reflFields[$this->identifier]->getValue($document); - } - - /** - * {@inheritDoc} - * - * Since MongoDB only allows exactly one identifier field this is a proxy - * to {@see getIdentifierValue()} and returns an array with the identifier - * field as a key. - */ - public function getIdentifierValues($object) - { - return array($this->identifier => $this->getIdentifierValue($object)); - } - - /** - * Get the document identifier object as a database type. - * - * @param object $document - * - * @return \MongoId $id The MongoID object. - */ - public function getIdentifierObject($document) - { - return $this->getDatabaseIdentifierValue($this->getIdentifierValue($document)); - } - - /** - * Sets the specified field to the specified value on the given document. - * - * @param object $document - * @param string $field - * @param mixed $value - */ - public function setFieldValue($document, $field, $value) - { - if ($document instanceof Proxy && ! $document->__isInitialized()) { - //property changes to an uninitialized proxy will not be tracked or persisted, - //so the proxy needs to be loaded first. - $document->__load(); - } - - $this->reflFields[$field]->setValue($document, $value); - } - - /** - * Gets the specified field's value off the given document. - * - * @param object $document - * @param string $field - * - * @return mixed - */ - public function getFieldValue($document, $field) - { - if ($document instanceof Proxy && $field !== $this->identifier && ! $document->__isInitialized()) { - $document->__load(); - } - - return $this->reflFields[$field]->getValue($document); - } - - /** - * Gets the mapping of a field. - * - * @param string $fieldName The field name. - * - * @return array The field mapping. - * - * @throws MappingException if the $fieldName is not found in the fieldMappings array - */ - public function getFieldMapping($fieldName) - { - if ( ! isset($this->fieldMappings[$fieldName])) { - throw MappingException::mappingNotFound($this->name, $fieldName); - } - return $this->fieldMappings[$fieldName]; - } - - /** - * Gets mappings of fields holding embedded document(s). - * - * @return array of field mappings - */ - public function getEmbeddedFieldsMappings() - { - return array_filter( - $this->associationMappings, - function($assoc) { return ! empty($assoc['embedded']); } - ); - } - - /** - * Gets the field mapping by its DB name. - * E.g. it returns identifier's mapping when called with _id. - * - * @param string $dbFieldName - * - * @return array - * @throws MappingException - */ - public function getFieldMappingByDbFieldName($dbFieldName) - { - foreach ($this->fieldMappings as $mapping) { - if ($mapping['name'] == $dbFieldName) { - return $mapping; - } - } - - throw MappingException::mappingNotFoundByDbName($this->name, $dbFieldName); - } - - /** - * Check if the field is not null. - * - * @param string $fieldName The field name - * - * @return boolean TRUE if the field is not null, FALSE otherwise. - */ - public function isNullable($fieldName) - { - $mapping = $this->getFieldMapping($fieldName); - if ($mapping !== false) { - return isset($mapping['nullable']) && $mapping['nullable'] == true; - } - return false; - } - - /** - * Checks whether the document has a discriminator field and value configured. - * - * @return boolean - */ - public function hasDiscriminator() - { - return isset($this->discriminatorField, $this->discriminatorValue); - } - - /** - * Sets the type of Id generator to use for the mapped class. - * - * @param string $generatorType Generator type. - */ - public function setIdGeneratorType($generatorType) - { - $this->generatorType = $generatorType; - } - - /** - * Sets the Id generator options. - * - * @param array $generatorOptions Generator options. - */ - public function setIdGeneratorOptions($generatorOptions) - { - $this->generatorOptions = $generatorOptions; - } - - /** - * @return boolean - */ - public function isInheritanceTypeNone() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_NONE; - } - - /** - * Checks whether the mapped class uses the SINGLE_COLLECTION inheritance mapping strategy. - * - * @return boolean - */ - public function isInheritanceTypeSingleCollection() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_SINGLE_COLLECTION; - } - - /** - * Checks whether the mapped class uses the COLLECTION_PER_CLASS inheritance mapping strategy. - * - * @return boolean - */ - public function isInheritanceTypeCollectionPerClass() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_COLLECTION_PER_CLASS; - } - - /** - * Sets the mapped subclasses of this class. - * - * @param string[] $subclasses The names of all mapped subclasses. - */ - public function setSubclasses(array $subclasses) - { - foreach ($subclasses as $subclass) { - if (strpos($subclass, '\\') === false && strlen($this->namespace)) { - @trigger_error(sprintf('Subclass "%s" in class "%s" relies on same-namespace resolution. This is deprecated and will be dropped in 2.0. Please use a FQCN instead.', $subclass, $this->name), E_USER_DEPRECATED); - - $this->subClasses[] = $this->namespace . '\\' . $subclass; - } else { - $this->subClasses[] = $subclass; - } - } - } - - /** - * Sets the parent class names. - * Assumes that the class names in the passed array are in the order: - * directParent -> directParentParent -> directParentParentParent ... -> root. - * - * @param string[] $classNames - */ - public function setParentClasses(array $classNames) - { - $this->parentClasses = $classNames; - - if (count($classNames) > 0) { - $this->rootDocumentName = array_pop($classNames); - } - } - - /** - * Checks whether the class will generate a new \MongoId instance for us. - * - * @return boolean TRUE if the class uses the AUTO generator, FALSE otherwise. - */ - public function isIdGeneratorAuto() - { - return $this->generatorType == self::GENERATOR_TYPE_AUTO; - } - - /** - * Checks whether the class will use a collection to generate incremented identifiers. - * - * @return boolean TRUE if the class uses the INCREMENT generator, FALSE otherwise. - */ - public function isIdGeneratorIncrement() - { - return $this->generatorType == self::GENERATOR_TYPE_INCREMENT; - } - - /** - * Checks whether the class will generate a uuid id. - * - * @return boolean TRUE if the class uses the UUID generator, FALSE otherwise. - */ - public function isIdGeneratorUuid() - { - return $this->generatorType == self::GENERATOR_TYPE_UUID; - } - - /** - * Checks whether the class uses no id generator. - * - * @return boolean TRUE if the class does not use any id generator, FALSE otherwise. - */ - public function isIdGeneratorNone() - { - return $this->generatorType == self::GENERATOR_TYPE_NONE; - } - - /** - * Sets the version field mapping used for versioning. Sets the default - * value to use depending on the column type. - * - * @param array $mapping The version field mapping array - * - * @throws LockException - */ - public function setVersionMapping(array &$mapping) - { - if ($mapping['type'] !== 'int' && $mapping['type'] !== 'date') { - throw LockException::invalidVersionFieldType($mapping['type']); - } - - $this->isVersioned = true; - $this->versionField = $mapping['fieldName']; - } - - /** - * Sets whether this class is to be versioned for optimistic locking. - * - * @param boolean $bool - */ - public function setVersioned($bool) - { - $this->isVersioned = $bool; - } - - /** - * Sets the name of the field that is to be used for versioning if this class is - * versioned for optimistic locking. - * - * @param string $versionField - */ - public function setVersionField($versionField) - { - $this->versionField = $versionField; - } - - /** - * Sets the version field mapping used for versioning. Sets the default - * value to use depending on the column type. - * - * @param array $mapping The version field mapping array - * - * @throws \Doctrine\ODM\MongoDB\LockException - */ - public function setLockMapping(array &$mapping) - { - if ($mapping['type'] !== 'int') { - throw LockException::invalidLockFieldType($mapping['type']); - } - - $this->isLockable = true; - $this->lockField = $mapping['fieldName']; - } - - /** - * Sets whether this class is to allow pessimistic locking. - * - * @param boolean $bool - */ - public function setLockable($bool) - { - $this->isLockable = $bool; - } - - /** - * Sets the name of the field that is to be used for storing whether a document - * is currently locked or not. - * - * @param string $lockField - */ - public function setLockField($lockField) - { - $this->lockField = $lockField; - } - - /** - * Marks this class as read only, no change tracking is applied to it. - */ - public function markReadOnly() - { - $this->isReadOnly = true; - } - - /** - * {@inheritDoc} - */ - public function getFieldNames() - { - return array_keys($this->fieldMappings); - } - - /** - * {@inheritDoc} - */ - public function getAssociationNames() - { - return array_keys($this->associationMappings); - } - - /** - * {@inheritDoc} - */ - public function getTypeOfField($fieldName) - { - return isset($this->fieldMappings[$fieldName]) ? - $this->fieldMappings[$fieldName]['type'] : null; - } - - /** - * {@inheritDoc} - */ - public function getAssociationTargetClass($assocName) - { - if ( ! isset($this->associationMappings[$assocName])) { - throw new InvalidArgumentException("Association name expected, '" . $assocName . "' is not an association."); - } +if (! class_exists(ClassMetadata::class, false)) { + @trigger_error(sprintf('The "%s" class is deprecated and will be removed in 2.0. Use "%s" instead.', ClassMetadataInfo::class, ClassMetadata::class), E_USER_DEPRECATED); +} - return $this->associationMappings[$assocName]['targetDocument']; - } +class_alias(ClassMetadata::class, ClassMetadataInfo::class); +if (false) { /** - * Retrieve the collectionClass associated with an association + * This stub has two purposes: + * - it provides a class for IDEs so they still provide autocompletion for + * this class even when they don't support class_alias + * - it gets composer to think there's a class in here when using the + * --classmap-authoritative autoloader optimization. * - * @param string $assocName - */ - public function getAssociationCollectionClass($assocName) - { - if ( ! isset($this->associationMappings[$assocName])) { - throw new InvalidArgumentException("Association name expected, '" . $assocName . "' is not an association."); - } - - if ( ! array_key_exists('collectionClass', $this->associationMappings[$assocName])) { - throw new InvalidArgumentException("collectionClass can only be applied to 'embedMany' and 'referenceMany' associations."); - } - - return $this->associationMappings[$assocName]['collectionClass']; - } - - /** - * {@inheritDoc} - */ - public function isAssociationInverseSide($fieldName) - { - throw new \BadMethodCallException(__METHOD__ . '() is not implemented yet.'); - } - - /** - * {@inheritDoc} + * @deprecated in favor of ClassMetadata */ - public function getAssociationMappedByTargetField($fieldName) + class ClassMetadataInfo extends ClassMetadata { - throw new \BadMethodCallException(__METHOD__ . '() is not implemented yet.'); } } diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/AnnotationDriver.php index 30d04beebc..86e9034d3c 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/AnnotationDriver.php @@ -27,7 +27,6 @@ use Doctrine\ODM\MongoDB\Events; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MappingClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Mapping\MappingException; /** @@ -65,7 +64,7 @@ public static function registerAnnotationClasses() */ public function loadMetadataForClass($className, ClassMetadata $class) { - /** @var $class ClassMetadataInfo */ + /** @var $class MappingClassMetadata */ $reflClass = $class->getReflectionClass(); $classAnnotations = $this->reader->getClassAnnotations($reflClass); @@ -258,7 +257,7 @@ public function loadMetadataForClass($className, ClassMetadata $class) } } - private function addIndex(ClassMetadataInfo $class, $index, array $keys = array()) + private function addIndex(MappingClassMetadata $class, $index, array $keys = array()) { $keys = array_merge($keys, $index->keys); $options = array(); @@ -276,12 +275,12 @@ private function addIndex(ClassMetadataInfo $class, $index, array $keys = array( } /** - * @param ClassMetadataInfo $class - * @param ODM\ShardKey $shardKey + * @param MappingClassMetadata $class + * @param ODM\ShardKey $shardKey * * @throws MappingException */ - private function setShardKey(ClassMetadataInfo $class, ODM\ShardKey $shardKey) + private function setShardKey(MappingClassMetadata $class, ODM\ShardKey $shardKey) { $options = array(); $allowed = array('unique', 'numInitialChunks'); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php index 2b0c609d42..2377df9f4e 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php @@ -23,7 +23,6 @@ use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MappingClassMetadata; use Doctrine\ODM\MongoDB\Utility\CollectionHelper; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use SimpleXMLElement; use const E_USER_DEPRECATED; use function sprintf; @@ -51,7 +50,7 @@ public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENS */ public function loadMetadataForClass($className, ClassMetadata $class) { - /* @var $class ClassMetadataInfo */ + /* @var $class MappingClassMetadata */ /* @var $xmlRoot SimpleXMLElement */ $xmlRoot = $this->getElement($className); if ( ! $xmlRoot) { @@ -248,7 +247,7 @@ public function loadMetadataForClass($className, ClassMetadata $class) } } - private function addFieldMapping(ClassMetadataInfo $class, $mapping) + private function addFieldMapping(MappingClassMetadata $class, $mapping) { if (isset($mapping['name'])) { $name = $mapping['name']; @@ -290,10 +289,10 @@ private function addFieldMapping(ClassMetadataInfo $class, $mapping) $class->addIndex($keys, $options); } - private function addEmbedMapping(ClassMetadataInfo $class, $embed, $type) + private function addEmbedMapping(MappingClassMetadata $class, $embed, $type) { $attributes = $embed->attributes(); - $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; + $defaultStrategy = $type == 'one' ? MappingClassMetadata::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'type' => $type, 'embedded' => true, @@ -327,21 +326,21 @@ private function addEmbedMapping(ClassMetadataInfo $class, $embed, $type) $this->addFieldMapping($class, $mapping); } - private function addReferenceMapping(ClassMetadataInfo $class, $reference, $type) + private function addReferenceMapping(MappingClassMetadata $class, $reference, $type) { $cascade = array_keys((array) $reference->cascade); if (1 === count($cascade)) { $cascade = current($cascade) ?: next($cascade); } $attributes = $reference->attributes(); - $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; + $defaultStrategy = $type == 'one' ? MappingClassMetadata::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'cascade' => $cascade, 'orphanRemoval' => isset($attributes['orphan-removal']) ? ('true' === (string) $attributes['orphan-removal']) : false, 'type' => $type, 'reference' => true, 'simple' => isset($attributes['simple']) ? ('true' === (string) $attributes['simple']) : false, // deprecated - 'storeAs' => isset($attributes['store-as']) ? (string) $attributes['store-as'] : ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, + 'storeAs' => isset($attributes['store-as']) ? (string) $attributes['store-as'] : MappingClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, 'targetDocument' => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null, 'collectionClass' => isset($attributes['collection-class']) ? (string) $attributes['collection-class'] : null, 'name' => (string) $attributes['field'], @@ -398,7 +397,7 @@ private function addReferenceMapping(ClassMetadataInfo $class, $reference, $type $this->addFieldMapping($class, $mapping); } - private function addIndex(ClassMetadataInfo $class, SimpleXmlElement $xmlIndex) + private function addIndex(MappingClassMetadata $class, SimpleXmlElement $xmlIndex) { $attributes = $xmlIndex->attributes(); @@ -506,7 +505,7 @@ private function getPartialFilterExpression(SimpleXMLElement $fields) return $partialFilterExpression; } - private function setShardKey(ClassMetadataInfo $class, SimpleXmlElement $xmlShardkey) + private function setShardKey(MappingClassMetadata $class, SimpleXmlElement $xmlShardkey) { $attributes = $xmlShardkey->attributes(); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php index 2b7eb5e5ac..eda40aa7e6 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php @@ -23,7 +23,6 @@ use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MappingClassMetadata; use Doctrine\ODM\MongoDB\Utility\CollectionHelper; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Exception\ParseException; use const E_USER_DEPRECATED; @@ -54,7 +53,7 @@ public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENS */ public function loadMetadataForClass($className, ClassMetadata $class) { - /* @var $class ClassMetadataInfo */ + /* @var $class MappingClassMetadata */ $element = $this->getElement($className); if ( ! $element) { return; @@ -178,7 +177,7 @@ public function loadMetadataForClass($className, ClassMetadata $class) } } - private function addFieldMapping(ClassMetadataInfo $class, $mapping) + private function addFieldMapping(MappingClassMetadata $class, $mapping) { if (isset($mapping['name'])) { $name = $mapping['name']; @@ -257,9 +256,9 @@ private function addFieldMapping(ClassMetadataInfo $class, $mapping) $class->addIndex($keys, $options); } - private function addMappingFromEmbed(ClassMetadataInfo $class, $fieldName, $embed, $type) + private function addMappingFromEmbed(MappingClassMetadata $class, $fieldName, $embed, $type) { - $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; + $defaultStrategy = $type == 'one' ? MappingClassMetadata::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'type' => $type, 'embedded' => true, @@ -283,16 +282,16 @@ private function addMappingFromEmbed(ClassMetadataInfo $class, $fieldName, $embe $this->addFieldMapping($class, $mapping); } - private function addMappingFromReference(ClassMetadataInfo $class, $fieldName, $reference, $type) + private function addMappingFromReference(MappingClassMetadata $class, $fieldName, $reference, $type) { - $defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; + $defaultStrategy = $type == 'one' ? MappingClassMetadata::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY; $mapping = array( 'cascade' => isset($reference['cascade']) ? $reference['cascade'] : [], 'orphanRemoval' => isset($reference['orphanRemoval']) ? $reference['orphanRemoval'] : false, 'type' => $type, 'reference' => true, 'simple' => isset($reference['simple']) ? (boolean) $reference['simple'] : false, // deprecated - 'storeAs' => isset($reference['storeAs']) ? (string) $reference['storeAs'] : ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, + 'storeAs' => isset($reference['storeAs']) ? (string) $reference['storeAs'] : MappingClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, 'targetDocument' => isset($reference['targetDocument']) ? $reference['targetDocument'] : null, 'collectionClass' => isset($reference['collectionClass']) ? $reference['collectionClass'] : null, 'fieldName' => $fieldName, @@ -372,7 +371,7 @@ protected function loadMappingFile($file) } } - private function setShardKey(ClassMetadataInfo $class, array $shardKey) + private function setShardKey(MappingClassMetadata $class, array $shardKey) { $keys = $shardKey['keys']; $options = array(); diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php index f06001606d..687dc6ee53 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php @@ -21,7 +21,7 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\LockException; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; use Doctrine\ODM\MongoDB\UnitOfWork; use Doctrine\ODM\MongoDB\Utility\CollectionHelper; @@ -104,17 +104,17 @@ public function update(PersistentCollectionInterface $coll, array $options) } switch ($mapping['strategy']) { - case ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET: - case ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET_ARRAY: + case ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET: + case ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET_ARRAY: throw new \UnexpectedValueException($mapping['strategy'] . ' update collection strategy should have been handled by DocumentPersister. Please report a bug in issue tracker'); - case ClassMetadataInfo::STORAGE_STRATEGY_SET: - case ClassMetadataInfo::STORAGE_STRATEGY_SET_ARRAY: + case ClassMetadata::STORAGE_STRATEGY_SET: + case ClassMetadata::STORAGE_STRATEGY_SET_ARRAY: $this->setCollection($coll, $options); break; - case ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET: - case ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL: + case ClassMetadata::STORAGE_STRATEGY_ADD_TO_SET: + case ClassMetadata::STORAGE_STRATEGY_PUSH_ALL: $coll->initialize(); $this->deleteElements($coll, $options); $this->insertElements($coll, $options); @@ -202,11 +202,11 @@ private function insertElements(PersistentCollectionInterface $coll, array $opti $mapping = $coll->getMapping(); switch ($mapping['strategy']) { - case ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL: + case ClassMetadata::STORAGE_STRATEGY_PUSH_ALL: $operator = 'push'; break; - case ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET: + case ClassMetadata::STORAGE_STRATEGY_ADD_TO_SET: $operator = 'addToSet'; break; diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php index 0d709ef429..dccfa6a436 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php @@ -25,7 +25,6 @@ use Doctrine\MongoDB\EagerCursor; use Doctrine\ODM\MongoDB\Cursor; use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Query\ReferencePrimer; use Doctrine\ODM\MongoDB\Utility\CollectionHelper; use Doctrine\ODM\MongoDB\Hydrator\HydratorFactory; @@ -736,7 +735,7 @@ private function loadReferenceManyCollectionOwningSide(PersistentCollectionInter foreach ($collection->getMongoData() as $key => $reference) { $className = $this->uow->getClassNameForAssociation($mapping, $reference); - $mongoId = ClassMetadataInfo::getReferenceId($reference, $mapping['storeAs']); + $mongoId = ClassMetadata::getReferenceId($reference, $mapping['storeAs']); $id = $this->dm->getClassMetadata($className)->getPHPIdentifierValue($mongoId); // create a reference to the class and id @@ -818,7 +817,7 @@ public function createReferenceManyInverseSideQuery(PersistentCollectionInterfac $ownerClass = $this->dm->getClassMetadata(get_class($owner)); $targetClass = $this->dm->getClassMetadata($mapping['targetDocument']); $mappedByMapping = isset($targetClass->fieldMappings[$mapping['mappedBy']]) ? $targetClass->fieldMappings[$mapping['mappedBy']] : array(); - $mappedByFieldName = ClassMetadataInfo::getReferenceFieldName(isset($mappedByMapping['storeAs']) ? $mappedByMapping['storeAs'] : ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF, $mapping['mappedBy']); + $mappedByFieldName = ClassMetadata::getReferenceFieldName(isset($mappedByMapping['storeAs']) ? $mappedByMapping['storeAs'] : ClassMetadata::REFERENCE_STORE_AS_DB_REF, $mapping['mappedBy']); $criteria = $this->cm->merge( array($mappedByFieldName => $ownerClass->getIdentifierObject($owner)), @@ -1050,7 +1049,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $ { $class = isset($class) ? $class : $this->class; - // @todo Consider inlining calls to ClassMetadataInfo methods + // @todo Consider inlining calls to ClassMetadata methods // Process all non-identifier fields by translating field names if ($class->hasField($fieldName) && ! $class->isIdentifier($fieldName)) { @@ -1078,7 +1077,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $ // No further preparation unless we're dealing with a simple reference // We can't have expressions in empty() with PHP < 5.5, so store it in a variable $arrayValue = (array) $value; - if (empty($mapping['reference']) || $mapping['storeAs'] !== ClassMetadataInfo::REFERENCE_STORE_AS_ID || empty($arrayValue)) { + if (empty($mapping['reference']) || $mapping['storeAs'] !== ClassMetadata::REFERENCE_STORE_AS_ID || empty($arrayValue)) { return [[$fieldName, $value]]; } @@ -1190,8 +1189,8 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $ $objectPropertyIsId = $targetClass->isIdentifier($objectProperty); // Prepare DBRef identifiers or the mapped field's property path - $fieldName = ($objectPropertyIsId && ! empty($mapping['reference']) && $mapping['storeAs'] !== ClassMetadataInfo::REFERENCE_STORE_AS_ID) - ? ClassMetadataInfo::getReferenceFieldName($mapping['storeAs'], $e[0]) + $fieldName = ($objectPropertyIsId && ! empty($mapping['reference']) && $mapping['storeAs'] !== ClassMetadata::REFERENCE_STORE_AS_ID) + ? ClassMetadata::getReferenceFieldName($mapping['storeAs'], $e[0]) : $e[0] . '.' . $objectPropertyPrefix . $targetMapping['name']; // Process targetDocument identifier fields @@ -1226,7 +1225,7 @@ private function prepareQueryElement($fieldName, $value = null, $class = null, $ $fieldNames = $this->prepareQueryElement($nextObjectProperty, $value, $nextTargetClass, $prepareValue); } else { // No recursive processing for references as most probably somebody is querying DBRef or alike - if ($nextObjectProperty[0] !== '$' && in_array($targetMapping['storeAs'], [ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF])) { + if ($nextObjectProperty[0] !== '$' && in_array($targetMapping['storeAs'], [ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, ClassMetadata::REFERENCE_STORE_AS_DB_REF])) { $nextObjectProperty = '$' . $nextObjectProperty; } $fieldNames = [[$nextObjectProperty, $value]]; @@ -1446,20 +1445,20 @@ private function getWriteOptions(array $options = array()) private function prepareReference($fieldName, $value, array $mapping, $inNewObj) { $reference = $this->dm->createReference($value, $mapping); - if ($inNewObj || $mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID) { + if ($inNewObj || $mapping['storeAs'] === ClassMetadata::REFERENCE_STORE_AS_ID) { return [[$fieldName, $reference]]; } switch ($mapping['storeAs']) { - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: + case ClassMetadata::REFERENCE_STORE_AS_REF: $keys = ['id' => true]; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF: - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB: $keys = ['$ref' => true, '$id' => true, '$db' => true]; - if ($mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) { + if ($mapping['storeAs'] === ClassMetadata::REFERENCE_STORE_AS_DB_REF) { unset($keys['$db']); } diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php b/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php index 7d65b9fe10..8808c67fa0 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php @@ -20,7 +20,6 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; use Doctrine\ODM\MongoDB\Types\Type; use Doctrine\ODM\MongoDB\UnitOfWork; @@ -104,7 +103,7 @@ public function prepareInsertData($document) // We're excluding collections using addToSet since there is a risk // of duplicated entries stored in the collection } elseif ($mapping['type'] === ClassMetadata::MANY && ! $mapping['isInverseSide'] - && $mapping['strategy'] !== ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET && ! $new->isEmpty()) { + && $mapping['strategy'] !== ClassMetadata::STORAGE_STRATEGY_ADD_TO_SET && ! $new->isEmpty()) { $insertData[$mapping['name']] = $this->prepareAssociatedCollectionValue($new, true); } } @@ -146,7 +145,7 @@ public function prepareUpdateData($document) if ($new === null && $mapping['nullable'] !== true) { $updateData['$unset'][$mapping['name']] = true; } else { - if ($new !== null && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadataInfo::STORAGE_STRATEGY_INCREMENT) { + if ($new !== null && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) { $operator = '$inc'; $value = Type::getType($mapping['type'])->convertToDatabaseValue($new - $old); } else { @@ -244,7 +243,7 @@ public function prepareUpsertData($document) // Scalar fields if ( ! isset($mapping['association'])) { if ($new !== null) { - if (empty($mapping['id']) && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadataInfo::STORAGE_STRATEGY_INCREMENT) { + if (empty($mapping['id']) && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) { $operator = '$inc'; $value = Type::getType($mapping['type'])->convertToDatabaseValue($new - $old); } else { @@ -344,7 +343,7 @@ public function prepareEmbeddedDocumentValue(array $embeddedMapping, $embeddedDo continue; } - // Inline ClassMetadataInfo::getFieldValue() + // Inline ClassMetadata::getFieldValue() $rawValue = $class->reflFields[$mapping['fieldName']]->getValue($embeddedDocument); $value = null; diff --git a/lib/Doctrine/ODM/MongoDB/Proxy/ProxyFactory.php b/lib/Doctrine/ODM/MongoDB/Proxy/ProxyFactory.php index 51fb6e9d7e..db0d989968 100644 --- a/lib/Doctrine/ODM/MongoDB/Proxy/ProxyFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Proxy/ProxyFactory.php @@ -28,6 +28,7 @@ use Doctrine\Common\Util\ClassUtils; use Doctrine\Common\Proxy\Proxy as BaseProxy; use Doctrine\Common\Persistence\Mapping\ClassMetadata as BaseClassMetadata; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Persisters\DocumentPersister; use Doctrine\ODM\MongoDB\Utility\LifecycleEventManager; use ReflectionProperty; @@ -87,7 +88,7 @@ public function __construct(DocumentManager $documentManager, $proxyDir, $proxyN */ public function skipClass(BaseClassMetadata $class) { - /* @var $class \Doctrine\ODM\Mongodb\Mapping\ClassMetadataInfo */ + /* @var $class ClassMetadata */ return $class->isMappedSuperclass || $class->isQueryResultDocument || $class->getReflectionClass()->isAbstract(); } @@ -96,7 +97,7 @@ public function skipClass(BaseClassMetadata $class) */ public function createProxyDefinition($className) { - /* @var $classMetadata \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo */ + /* @var $classMetadata ClassMetadata */ $classMetadata = $this->metadataFactory->getMetadataFor($className); $documentPersister = $this->uow->getDocumentPersister($className); $reflectionId = $classMetadata->reflFields[$classMetadata->identifier]; diff --git a/lib/Doctrine/ODM/MongoDB/Query/Builder.php b/lib/Doctrine/ODM/MongoDB/Query/Builder.php index 46cd14a32e..8fb3146e89 100644 --- a/lib/Doctrine/ODM/MongoDB/Query/Builder.php +++ b/lib/Doctrine/ODM/MongoDB/Query/Builder.php @@ -21,7 +21,7 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Hydrator; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; /** * Query builder for ODM. @@ -407,7 +407,7 @@ public function getQuery(array $options = array()) $query['distinct'] = $documentPersister->prepareFieldName($query['distinct']); } - if ($this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION && ! empty($query['upsert']) && + if ($this->class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION && ! empty($query['upsert']) && (empty($query['query'][$this->class->discriminatorField]) || is_array($query['query'][$this->class->discriminatorField]))) { throw new \InvalidArgumentException('Upsert query that is to be performed on discriminated document does not have single ' . 'discriminator. Either not use base class or set \'' . $this->class->discriminatorField . '\' field manually.'); @@ -415,7 +415,7 @@ public function getQuery(array $options = array()) if ( ! empty($query['select'])) { $query['select'] = $documentPersister->prepareSortOrProjection($query['select']); - if ($this->hydrate && $this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION + if ($this->hydrate && $this->class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION && ! isset($query['select'][$this->class->discriminatorField])) { $includeMode = 0 < count(array_filter($query['select'], function($mode) { return $mode == 1; })); if ($includeMode && ! isset($query['select'][$this->class->discriminatorField])) { diff --git a/lib/Doctrine/ODM/MongoDB/Query/Expr.php b/lib/Doctrine/ODM/MongoDB/Query/Expr.php index 1bed27c6db..6516d6c892 100644 --- a/lib/Doctrine/ODM/MongoDB/Query/Expr.php +++ b/lib/Doctrine/ODM/MongoDB/Query/Expr.php @@ -21,7 +21,6 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Mapping\MappingException; /** @@ -77,20 +76,20 @@ public function references($document) $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null; switch ($storeAs) { - case ClassMetadataInfo::REFERENCE_STORE_AS_ID: + case ClassMetadata::REFERENCE_STORE_AS_ID: $this->query[$mapping['name']] = $reference; return $this; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: + case ClassMetadata::REFERENCE_STORE_AS_REF: $keys = ['id' => true]; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF: - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB: $keys = ['$ref' => true, '$id' => true, '$db' => true]; - if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) { + if ($storeAs === ClassMetadata::REFERENCE_STORE_AS_DB_REF) { unset($keys['$db']); } @@ -129,20 +128,20 @@ public function includesReferenceTo($document) $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null; switch ($storeAs) { - case ClassMetadataInfo::REFERENCE_STORE_AS_ID: + case ClassMetadata::REFERENCE_STORE_AS_ID: $this->query[$mapping['name']] = $reference; return $this; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_REF: + case ClassMetadata::REFERENCE_STORE_AS_REF: $keys = ['id' => true]; break; - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF: - case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF: + case ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB: $keys = ['$ref' => true, '$id' => true, '$db' => true]; - if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) { + if ($storeAs === ClassMetadata::REFERENCE_STORE_AS_DB_REF) { unset($keys['$db']); } diff --git a/lib/Doctrine/ODM/MongoDB/Query/ReferencePrimer.php b/lib/Doctrine/ODM/MongoDB/Query/ReferencePrimer.php index 4db943d925..52609c9941 100644 --- a/lib/Doctrine/ODM/MongoDB/Query/ReferencePrimer.php +++ b/lib/Doctrine/ODM/MongoDB/Query/ReferencePrimer.php @@ -21,7 +21,6 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\PersistentCollection; use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; use Doctrine\ODM\MongoDB\Proxy\Proxy; @@ -126,7 +125,7 @@ public function primeReferences(ClassMetadata $class, $documents, $fieldName, ar /* Simple reference require a target document class so we can construct * the priming query. */ - if ($mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID && empty($mapping['targetDocument'])) { + if ($mapping['storeAs'] === ClassMetadata::REFERENCE_STORE_AS_ID && empty($mapping['targetDocument'])) { throw new \LogicException(sprintf('Field "%s" is a simple reference without a target document class in class "%s"', $fieldName, $class->name)); } @@ -255,15 +254,15 @@ private function addManyReferences(PersistentCollectionInterface $persistentColl { $mapping = $persistentCollection->getMapping(); - if ($mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID) { + if ($mapping['storeAs'] === ClassMetadata::REFERENCE_STORE_AS_ID) { $className = $mapping['targetDocument']; $class = $this->dm->getClassMetadata($className); } foreach ($persistentCollection->getMongoData() as $reference) { - $id = ClassMetadataInfo::getReferenceId($reference, $mapping['storeAs']); + $id = ClassMetadata::getReferenceId($reference, $mapping['storeAs']); - if ($mapping['storeAs'] !== ClassMetadataInfo::REFERENCE_STORE_AS_ID) { + if ($mapping['storeAs'] !== ClassMetadata::REFERENCE_STORE_AS_ID) { $className = $this->uow->getClassNameForAssociation($mapping, $reference); $class = $this->dm->getClassMetadata($className); } diff --git a/lib/Doctrine/ODM/MongoDB/SchemaManager.php b/lib/Doctrine/ODM/MongoDB/SchemaManager.php index b0241c57f8..5af5844e13 100644 --- a/lib/Doctrine/ODM/MongoDB/SchemaManager.php +++ b/lib/Doctrine/ODM/MongoDB/SchemaManager.php @@ -21,7 +21,6 @@ use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; class SchemaManager { @@ -193,7 +192,7 @@ private function doGetDocumentIndexes($documentName, array &$visited) $newKeys = array(); foreach ($index['keys'] as $key => $v) { if ($key == $fieldMapping['name']) { - $key = ClassMetadataInfo::getReferenceFieldName($fieldMapping['storeAs'], $key); + $key = ClassMetadata::getReferenceFieldName($fieldMapping['storeAs'], $key); } $newKeys[$key] = $v; } @@ -689,7 +688,7 @@ private function runShardCollectionCommand($documentName) $fieldName = $mapping['name']; if ($class->isSingleValuedReference($key)) { - $fieldName = ClassMetadataInfo::getReferenceFieldName($mapping['storeAs'], $fieldName); + $fieldName = ClassMetadata::getReferenceFieldName($mapping['storeAs'], $fieldName); } } else { $fieldName = $key; diff --git a/lib/Doctrine/ODM/MongoDB/Tools/Console/Command/GeneratePersistentCollectionsCommand.php b/lib/Doctrine/ODM/MongoDB/Tools/Console/Command/GeneratePersistentCollectionsCommand.php index 2f0238ab25..c9c57187a9 100644 --- a/lib/Doctrine/ODM/MongoDB/Tools/Console/Command/GeneratePersistentCollectionsCommand.php +++ b/lib/Doctrine/ODM/MongoDB/Tools/Console/Command/GeneratePersistentCollectionsCommand.php @@ -19,7 +19,6 @@ namespace Doctrine\ODM\MongoDB\Tools\Console\Command; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Tools\Console\MetadataFilter; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; diff --git a/lib/Doctrine/ODM/MongoDB/Tools/DisconnectedClassMetadataFactory.php b/lib/Doctrine/ODM/MongoDB/Tools/DisconnectedClassMetadataFactory.php index bcdfded5b7..0770062d45 100644 --- a/lib/Doctrine/ODM/MongoDB/Tools/DisconnectedClassMetadataFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Tools/DisconnectedClassMetadataFactory.php @@ -20,7 +20,7 @@ namespace Doctrine\ODM\MongoDB\Tools; use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; /** * The DisconnectedClassMetadataFactory is used to create ClassMetadata objects @@ -37,7 +37,7 @@ class DisconnectedClassMetadataFactory extends ClassMetadataFactory */ protected function newClassMetadataInstance($className) { - $metadata = new ClassMetadataInfo($className); + $metadata = new ClassMetadata($className); if (strpos($className, "\\") !== false) { $metadata->namespace = strrev(substr( strrev($className), strpos(strrev($className), "\\")+1 )); } else { diff --git a/lib/Doctrine/ODM/MongoDB/Tools/DocumentGenerator.php b/lib/Doctrine/ODM/MongoDB/Tools/DocumentGenerator.php index 6b380a9e68..914743eeec 100644 --- a/lib/Doctrine/ODM/MongoDB/Tools/DocumentGenerator.php +++ b/lib/Doctrine/ODM/MongoDB/Tools/DocumentGenerator.php @@ -20,14 +20,14 @@ namespace Doctrine\ODM\MongoDB\Tools; use Doctrine\Common\Inflector\Inflector; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Types\Type; /** - * Generic class used to generate PHP5 document classes from ClassMetadataInfo instances + * Generic class used to generate PHP5 document classes from ClassMetadata instances * * [php] - * $classes = $dm->getClassMetadataInfoFactory()->getAllMetadata(); + * $classes = $dm->getClassMetadataFactory()->getAllMetadata(); * * $generator = new \Doctrine\ODM\MongoDB\Tools\DocumentGenerator(); * $generator->setGenerateAnnotations(true); @@ -48,7 +48,7 @@ class DocumentGenerator /** The extension to use for written php files */ private $extension = '.php'; - /** Whether or not the current ClassMetadataInfo instance is new or old */ + /** Whether or not the current ClassMetadata instance is new or old */ private $isNew = true; private $staticReflection = array(); @@ -149,7 +149,7 @@ public function () '; /** - * Generate and write document classes for the given array of ClassMetadataInfo instances + * Generate and write document classes for the given array of ClassMetadata instances * * @param array $metadatas * @param string $outputDirectory @@ -163,14 +163,14 @@ public function generate(array $metadatas, $outputDirectory) } /** - * Generated and write document class to disk for the given ClassMetadataInfo instance + * Generated and write document class to disk for the given ClassMetadata instance * - * @param ClassMetadataInfo $metadata + * @param ClassMetadata $metadata * @param string $outputDirectory * @throws \RuntimeException * @return void */ - public function writeDocumentClass(ClassMetadataInfo $metadata, $outputDirectory) + public function writeDocumentClass(ClassMetadata $metadata, $outputDirectory) { $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->extension; $dir = dirname($path); @@ -204,12 +204,12 @@ public function writeDocumentClass(ClassMetadataInfo $metadata, $outputDirectory } /** - * Generate a PHP5 Doctrine 2 document class from the given ClassMetadataInfo instance + * Generate a PHP5 Doctrine 2 document class from the given ClassMetadata instance * - * @param ClassMetadataInfo $metadata + * @param ClassMetadata $metadata * @return string $code */ - public function generateDocumentClass(ClassMetadataInfo $metadata) + public function generateDocumentClass(ClassMetadata $metadata) { $placeHolders = array( '', @@ -232,13 +232,13 @@ public function generateDocumentClass(ClassMetadataInfo $metadata) } /** - * Generate the updated code for the given ClassMetadataInfo and document at path + * Generate the updated code for the given ClassMetadata and document at path * - * @param ClassMetadataInfo $metadata + * @param ClassMetadata $metadata * @param string $path * @return string $code; */ - public function generateUpdatedDocumentClass(ClassMetadataInfo $metadata, $path) + public function generateUpdatedDocumentClass(ClassMetadata $metadata, $path) { $currentCode = file_get_contents($path); @@ -337,20 +337,20 @@ public function setBackupExisting($bool) $this->backupExisting = $bool; } - private function generateDocumentNamespace(ClassMetadataInfo $metadata) + private function generateDocumentNamespace(ClassMetadata $metadata) { if ($this->hasNamespace($metadata)) { return 'namespace ' . $this->getNamespace($metadata) . ';'; } } - private function generateDocumentClassName(ClassMetadataInfo $metadata) + private function generateDocumentClassName(ClassMetadata $metadata) { return 'class ' . $this->getClassName($metadata) . ($this->extendsClass() ? ' extends ' . $this->getClassToExtendName() : null); } - private function generateDocumentBody(ClassMetadataInfo $metadata) + private function generateDocumentBody(ClassMetadata $metadata) { $fieldMappingProperties = $this->generateDocumentFieldMappingProperties($metadata); $associationMappingProperties = $this->generateDocumentAssociationMappingProperties($metadata); @@ -380,7 +380,7 @@ private function generateDocumentBody(ClassMetadataInfo $metadata) return implode("\n", $code); } - private function generateDocumentConstructor(ClassMetadataInfo $metadata) + private function generateDocumentConstructor(ClassMetadata $metadata) { if ($this->hasMethod('__construct', $metadata)) { return ''; @@ -388,7 +388,7 @@ private function generateDocumentConstructor(ClassMetadataInfo $metadata) $collections = array(); foreach ($metadata->fieldMappings AS $mapping) { - if ($mapping['type'] === ClassMetadataInfo::MANY) { + if ($mapping['type'] === ClassMetadata::MANY) { $collections[] = '$this->' . $mapping['fieldName'] . ' = new \Doctrine\Common\Collections\ArrayCollection();'; } } @@ -436,7 +436,7 @@ private function parseTokensInDocumentFile($path) } } - private function hasProperty($property, ClassMetadataInfo $metadata) + private function hasProperty($property, ClassMetadata $metadata) { if ($this->extendsClass() || class_exists($metadata->name)) { // don't generate property if its already on the base class. @@ -459,7 +459,7 @@ private function hasProperty($property, ClassMetadataInfo $metadata) ); } - private function hasMethod($method, ClassMetadataInfo $metadata) + private function hasMethod($method, ClassMetadata $metadata) { if ($this->extendsClass() || class_exists($metadata->name)) { // don't generate method if its already on the base class. @@ -482,7 +482,7 @@ private function hasMethod($method, ClassMetadataInfo $metadata) ); } - private function hasNamespace(ClassMetadataInfo $metadata) + private function hasNamespace(ClassMetadata $metadata) { return strpos($metadata->name, '\\') ? true : false; } @@ -504,23 +504,23 @@ private function getClassToExtendName() return '\\' . $refl->getName(); } - private function getClassName(ClassMetadataInfo $metadata) + private function getClassName(ClassMetadata $metadata) { return ($pos = strrpos($metadata->name, '\\')) ? substr($metadata->name, $pos + 1, strlen($metadata->name)) : $metadata->name; } - private function getNamespace(ClassMetadataInfo $metadata) + private function getNamespace(ClassMetadata $metadata) { return substr($metadata->name, 0, strrpos($metadata->name, '\\')); } /** - * @param ClassMetadataInfo $metadata + * @param ClassMetadata $metadata * * @return array */ - protected function getTraits(ClassMetadataInfo $metadata) + protected function getTraits(ClassMetadata $metadata) { if ($metadata->reflClass !== null || class_exists($metadata->name)) { $reflClass = $metadata->reflClass === null ? new \ReflectionClass($metadata->name) : $metadata->reflClass; @@ -541,7 +541,7 @@ private function generateDocumentImports() } } - private function generateDocumentDocBlock(ClassMetadataInfo $metadata) + private function generateDocumentDocBlock(ClassMetadata $metadata) { $lines = array(); $lines[] = '/**'; @@ -619,23 +619,23 @@ private function generateDocumentDocBlock(ClassMetadataInfo $metadata) return implode("\n", $lines); } - private function generateInheritanceAnnotation(ClassMetadataInfo $metadata) + private function generateInheritanceAnnotation(ClassMetadata $metadata) { - if ($metadata->inheritanceType !== ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + if ($metadata->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) { return '@ODM\\InheritanceType("' . $this->getInheritanceTypeString($metadata->inheritanceType) . '")'; } } - private function generateDiscriminatorFieldAnnotation(ClassMetadataInfo $metadata) + private function generateDiscriminatorFieldAnnotation(ClassMetadata $metadata) { - if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION) { + if ($metadata->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION) { return '@ODM\\DiscriminatorField(name="' . $metadata->discriminatorField . '")'; } } - private function generateDiscriminatorMapAnnotation(ClassMetadataInfo $metadata) + private function generateDiscriminatorMapAnnotation(ClassMetadata $metadata) { - if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION) { + if ($metadata->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION) { $inheritanceClassMap = array(); foreach ($metadata->discriminatorMap as $type => $class) { @@ -646,25 +646,25 @@ private function generateDiscriminatorMapAnnotation(ClassMetadataInfo $metadata) } } - private function generateDefaultDiscriminatorValueAnnotation(ClassMetadataInfo $metadata) + private function generateDefaultDiscriminatorValueAnnotation(ClassMetadata $metadata) { - if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION && isset($metadata->defaultDiscriminatorValue)) { + if ($metadata->inheritanceType === ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION && isset($metadata->defaultDiscriminatorValue)) { return '@ODM\\DefaultDiscriminatorValue("' . $metadata->defaultDiscriminatorValue . '")'; } } - private function generateChangeTrackingPolicyAnnotation(ClassMetadataInfo $metadata) + private function generateChangeTrackingPolicyAnnotation(ClassMetadata $metadata) { return '@ODM\\ChangeTrackingPolicy("' . $this->getChangeTrackingPolicyString($metadata->changeTrackingPolicy) . '")'; } - private function generateDocumentStubMethods(ClassMetadataInfo $metadata) + private function generateDocumentStubMethods(ClassMetadata $metadata) { $methods = array(); foreach ($metadata->fieldMappings as $fieldMapping) { if (isset($fieldMapping['id'])) { - if ($metadata->generatorType == ClassMetadataInfo::GENERATOR_TYPE_NONE) { + if ($metadata->generatorType == ClassMetadata::GENERATOR_TYPE_NONE) { if ($code = $this->generateDocumentStubMethod($metadata, 'set', $fieldMapping['fieldName'], $fieldMapping['type'])) { $methods[] = $code; } @@ -679,7 +679,7 @@ private function generateDocumentStubMethods(ClassMetadataInfo $metadata) if ($code = $code = $this->generateDocumentStubMethod($metadata, 'get', $fieldMapping['fieldName'], $fieldMapping['type'])) { $methods[] = $code; } - } elseif ($fieldMapping['type'] === ClassMetadataInfo::ONE) { + } elseif ($fieldMapping['type'] === ClassMetadata::ONE) { $nullable = $this->isAssociationNullable($fieldMapping) ? 'null' : null; if ($code = $this->generateDocumentStubMethod($metadata, 'set', $fieldMapping['fieldName'], isset($fieldMapping['targetDocument']) ? $fieldMapping['targetDocument'] : null, $nullable)) { $methods[] = $code; @@ -687,7 +687,7 @@ private function generateDocumentStubMethods(ClassMetadataInfo $metadata) if ($code = $this->generateDocumentStubMethod($metadata, 'get', $fieldMapping['fieldName'], isset($fieldMapping['targetDocument']) ? $fieldMapping['targetDocument'] : null)) { $methods[] = $code; } - } elseif ($fieldMapping['type'] === ClassMetadataInfo::MANY) { + } elseif ($fieldMapping['type'] === ClassMetadata::MANY) { if ($code = $this->generateDocumentStubMethod($metadata, 'add', $fieldMapping['fieldName'], isset($fieldMapping['targetDocument']) ? $fieldMapping['targetDocument'] : null)) { $methods[] = $code; } @@ -713,7 +713,7 @@ protected function isAssociationNullable($fieldMapping) return isset($fieldMapping['nullable']) && $fieldMapping['nullable']; } - private function generateDocumentLifecycleCallbackMethods(ClassMetadataInfo $metadata) + private function generateDocumentLifecycleCallbackMethods(ClassMetadata $metadata) { if (empty($metadata->lifecycleCallbacks)) { return ''; @@ -732,7 +732,7 @@ private function generateDocumentLifecycleCallbackMethods(ClassMetadataInfo $met return implode("\n\n", $methods); } - private function generateDocumentAssociationMappingProperties(ClassMetadataInfo $metadata) + private function generateDocumentAssociationMappingProperties(ClassMetadata $metadata) { $lines = array(); @@ -747,13 +747,13 @@ private function generateDocumentAssociationMappingProperties(ClassMetadataInfo $lines[] = $this->generateAssociationMappingPropertyDocBlock($fieldMapping); $lines[] = $this->spaces . 'protected $' . $fieldMapping['fieldName'] - . ($fieldMapping['type'] === ClassMetadataInfo::MANY ? ' = array()' : null) . ";\n"; + . ($fieldMapping['type'] === ClassMetadata::MANY ? ' = array()' : null) . ";\n"; } return implode("\n", $lines); } - private function generateDocumentFieldMappingProperties(ClassMetadataInfo $metadata) + private function generateDocumentFieldMappingProperties(ClassMetadata $metadata) { $lines = array(); @@ -774,7 +774,7 @@ private function generateDocumentFieldMappingProperties(ClassMetadataInfo $metad return implode("\n", $lines); } - private function generateDocumentStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null) + private function generateDocumentStubMethod(ClassMetadata $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null) { // Add/remove methods should use the singular form of the field name $formattedFieldName = in_array($type, array('add', 'remove')) @@ -815,7 +815,7 @@ private function generateDocumentStubMethod(ClassMetadataInfo $metadata, $type, return $this->prefixCodeWithSpaces($method); } - private function generateLifecycleCallbackMethod($name, $methodName, ClassMetadataInfo $metadata) + private function generateLifecycleCallbackMethod($name, $methodName, ClassMetadata $metadata) { if ($this->hasMethod($methodName, $metadata)) { return; @@ -846,16 +846,16 @@ private function generateAssociationMappingPropertyDocBlock(array $fieldMapping) $type = null; switch ($fieldMapping['association']) { - case ClassMetadataInfo::EMBED_ONE: + case ClassMetadata::EMBED_ONE: $type = 'EmbedOne'; break; - case ClassMetadataInfo::EMBED_MANY: + case ClassMetadata::EMBED_MANY: $type = 'EmbedMany'; break; - case ClassMetadataInfo::REFERENCE_ONE: + case ClassMetadata::REFERENCE_ONE: $type = 'ReferenceOne'; break; - case ClassMetadataInfo::REFERENCE_MANY: + case ClassMetadata::REFERENCE_MANY: $type = 'ReferenceMany'; break; } @@ -885,19 +885,19 @@ private function generateAssociationMappingPropertyDocBlock(array $fieldMapping) return implode("\n", $lines); } - private function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadataInfo $metadata) + private function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadata $metadata) { $lines = array(); $lines[] = $this->spaces . '/**'; if (isset($fieldMapping['id']) && $fieldMapping['id']) { - $fieldMapping['strategy'] = isset($fieldMapping['strategy']) ? $fieldMapping['strategy'] : ClassMetadataInfo::GENERATOR_TYPE_AUTO; - if ($fieldMapping['strategy'] === ClassMetadataInfo::GENERATOR_TYPE_AUTO) { + $fieldMapping['strategy'] = isset($fieldMapping['strategy']) ? $fieldMapping['strategy'] : ClassMetadata::GENERATOR_TYPE_AUTO; + if ($fieldMapping['strategy'] === ClassMetadata::GENERATOR_TYPE_AUTO) { $lines[] = $this->spaces . ' * @var MongoId $' . $fieldMapping['fieldName']; - } elseif ($fieldMapping['strategy'] === ClassMetadataInfo::GENERATOR_TYPE_INCREMENT) { + } elseif ($fieldMapping['strategy'] === ClassMetadata::GENERATOR_TYPE_INCREMENT) { $lines[] = $this->spaces . ' * @var integer $' . $fieldMapping['fieldName']; - } elseif ($fieldMapping['strategy'] === ClassMetadataInfo::GENERATOR_TYPE_UUID) { + } elseif ($fieldMapping['strategy'] === ClassMetadata::GENERATOR_TYPE_UUID) { $lines[] = $this->spaces . ' * @var string $' . $fieldMapping['fieldName']; - } elseif ($fieldMapping['strategy'] === ClassMetadataInfo::GENERATOR_TYPE_NONE) { + } elseif ($fieldMapping['strategy'] === ClassMetadata::GENERATOR_TYPE_NONE) { $lines[] = $this->spaces . ' * @var $' . $fieldMapping['fieldName']; } else { $lines[] = $this->spaces . ' * @var $' . $fieldMapping['fieldName']; @@ -961,13 +961,13 @@ private function prefixCodeWithSpaces($code, $num = 1) private function getInheritanceTypeString($type) { switch ($type) { - case ClassMetadataInfo::INHERITANCE_TYPE_NONE: + case ClassMetadata::INHERITANCE_TYPE_NONE: return 'NONE'; - case ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION: + case ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION: return 'SINGLE_COLLECTION'; - case ClassMetadataInfo::INHERITANCE_TYPE_COLLECTION_PER_CLASS: + case ClassMetadata::INHERITANCE_TYPE_COLLECTION_PER_CLASS: return 'COLLECTION_PER_CLASS'; default: @@ -978,13 +978,13 @@ private function getInheritanceTypeString($type) private function getChangeTrackingPolicyString($policy) { switch ($policy) { - case ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT: + case ClassMetadata::CHANGETRACKING_DEFERRED_IMPLICIT: return 'DEFERRED_IMPLICIT'; - case ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT: + case ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT: return 'DEFERRED_EXPLICIT'; - case ClassMetadataInfo::CHANGETRACKING_NOTIFY: + case ClassMetadata::CHANGETRACKING_NOTIFY: return 'NOTIFY'; default: @@ -995,22 +995,22 @@ private function getChangeTrackingPolicyString($policy) private function getIdGeneratorTypeString($type) { switch ($type) { - case ClassMetadataInfo::GENERATOR_TYPE_AUTO: + case ClassMetadata::GENERATOR_TYPE_AUTO: return 'AUTO'; - case ClassMetadataInfo::GENERATOR_TYPE_INCREMENT: + case ClassMetadata::GENERATOR_TYPE_INCREMENT: return 'INCREMENT'; - case ClassMetadataInfo::GENERATOR_TYPE_UUID: + case ClassMetadata::GENERATOR_TYPE_UUID: return 'UUID'; - case ClassMetadataInfo::GENERATOR_TYPE_ALNUM: + case ClassMetadata::GENERATOR_TYPE_ALNUM: return 'ALNUM'; - case ClassMetadataInfo::GENERATOR_TYPE_CUSTOM: + case ClassMetadata::GENERATOR_TYPE_CUSTOM: return 'CUSTOM'; - case ClassMetadataInfo::GENERATOR_TYPE_NONE: + case ClassMetadata::GENERATOR_TYPE_NONE: return 'NONE'; default: diff --git a/lib/Doctrine/ODM/MongoDB/UnitOfWork.php b/lib/Doctrine/ODM/MongoDB/UnitOfWork.php index e9b27170b4..9dc1901601 100644 --- a/lib/Doctrine/ODM/MongoDB/UnitOfWork.php +++ b/lib/Doctrine/ODM/MongoDB/UnitOfWork.php @@ -1894,7 +1894,7 @@ private function doMerge($document, array &$visited, $prevManagedCopy = null, $a } elseif ( ! $assoc2['isCascadeMerge']) { if ($this->getDocumentState($other) === self::STATE_DETACHED) { $targetDocument = isset($assoc2['targetDocument']) ? $assoc2['targetDocument'] : get_class($other); - /* @var $targetClass \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo */ + /* @var $targetClass ClassMetadata */ $targetClass = $this->dm->getClassMetadata($targetDocument); $relatedId = $targetClass->getIdentifierObject($other); diff --git a/lib/Doctrine/ODM/MongoDB/Utility/CollectionHelper.php b/lib/Doctrine/ODM/MongoDB/Utility/CollectionHelper.php index 14b1c3bb55..e063ea8c2a 100644 --- a/lib/Doctrine/ODM/MongoDB/Utility/CollectionHelper.php +++ b/lib/Doctrine/ODM/MongoDB/Utility/CollectionHelper.php @@ -18,7 +18,7 @@ */ namespace Doctrine\ODM\MongoDB\Utility; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; /** * Utility class used to unify checks on how collection strategies should behave. @@ -28,7 +28,7 @@ */ class CollectionHelper { - const DEFAULT_STRATEGY = ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL; + const DEFAULT_STRATEGY = ClassMetadata::STORAGE_STRATEGY_PUSH_ALL; /** * Returns whether update query must be included in query updating owning document. @@ -38,7 +38,7 @@ class CollectionHelper */ public static function isAtomic($strategy) { - return $strategy === ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET || $strategy === ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET_ARRAY; + return $strategy === ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET || $strategy === ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET_ARRAY; } /** @@ -49,7 +49,7 @@ public static function isAtomic($strategy) */ public static function isHash($strategy) { - return $strategy === ClassMetadataInfo::STORAGE_STRATEGY_SET || $strategy === ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET; + return $strategy === ClassMetadata::STORAGE_STRATEGY_SET || $strategy === ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET; } /** @@ -60,7 +60,7 @@ public static function isHash($strategy) */ public static function isList($strategy) { - return $strategy !== ClassMetadataInfo::STORAGE_STRATEGY_SET && $strategy !== ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET; + return $strategy !== ClassMetadata::STORAGE_STRATEGY_SET && $strategy !== ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET; } /** @@ -74,10 +74,10 @@ public static function usesSet($strategy) return in_array( $strategy, [ - ClassMetadataInfo::STORAGE_STRATEGY_SET, - ClassMetadataInfo::STORAGE_STRATEGY_SET_ARRAY, - ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET, - ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET_ARRAY + ClassMetadata::STORAGE_STRATEGY_SET, + ClassMetadata::STORAGE_STRATEGY_SET_ARRAY, + ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET, + ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET_ARRAY ] ); } diff --git a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php index 370dd3f00f..ec13a27ee4 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php @@ -2,7 +2,7 @@ namespace Doctrine\ODM\MongoDB\Tests; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Doctrine\ODM\MongoDB\Tests\Mocks\DocumentManagerMock; use Documents\CmsPhonenumber; @@ -141,21 +141,21 @@ public function testAffectedByErrorIfClosedException($methodName) public function testGetDocumentCollectionAppliesClassMetadataSlaveOkay() { - $cm1 = new ClassMetadataInfo('a'); + $cm1 = new ClassMetadata(TestClassA::class); $cm1->collection = 'a'; - $cm2 = new ClassMetadataInfo('b'); + $cm2 = new ClassMetadata(TestClassB::class); $cm2->collection = 'b'; $cm2->slaveOkay = true; - $cm3 = new ClassMetadataInfo('c'); + $cm3 = new ClassMetadata(TestClassC::class); $cm3->collection = 'c'; $cm3->slaveOkay = false; $map = array( - array('a', $cm1), - array('b', $cm2), - array('c', $cm3), + array(TestClassA::class, $cm1), + array(TestClassB::class, $cm2), + array(TestClassC::class, $cm3), ); $metadataFactory = $this->getMockClassMetadataFactory(); @@ -180,14 +180,14 @@ public function testGetDocumentCollectionAppliesClassMetadataSlaveOkay() $dm = new DocumentManagerMock(); $dm->metadataFactory = $metadataFactory; $dm->documentCollections = array( - 'a' => $coll1, - 'b' => $coll2, - 'c' => $coll3, + TestClassA::class => $coll1, + TestClassB::class => $coll2, + TestClassC::class => $coll3, ); - $dm->getDocumentCollection('a'); - $dm->getDocumentCollection('b'); - $dm->getDocumentCollection('c'); + $dm->getDocumentCollection(TestClassA::class); + $dm->getDocumentCollection(TestClassB::class); + $dm->getDocumentCollection(TestClassC::class); } /** @@ -197,7 +197,7 @@ public function testGetDocumentCollectionAppliesClassMetadataSlaveOkay() public function testCannotCreateDbRefWithoutId() { $d = new \Documents\User(); - $this->dm->createReference($d, ['storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF]); + $this->dm->createReference($d, ['storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF]); } public function testCreateDbRefWithNonNullEmptyId() @@ -206,7 +206,7 @@ public function testCreateDbRefWithNonNullEmptyId() $phonenumber->phonenumber = 0; $this->dm->persist($phonenumber); - $dbRef = $this->dm->createReference($phonenumber, ['storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF, 'targetDocument' => CmsPhonenumber::class]); + $dbRef = $this->dm->createReference($phonenumber, ['storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, 'targetDocument' => CmsPhonenumber::class]); $this->assertSame(array('$ref' => 'CmsPhonenumber', '$id' => 0), $dbRef); } @@ -261,6 +261,18 @@ private function getMockCollection() } } +class TestClassA +{ +} + +class TestClassB +{ +} + +class TestClassC +{ +} + /** @ODM\Document */ class WrongSimpleRefDocument { diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php index 7e590424fc..ad5faa56cd 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php @@ -5,7 +5,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Configuration; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\PersistentCollection; use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; use Documents\File; @@ -33,7 +33,7 @@ public function testLeadingBackslashIsRemoved() */ public function testCollectionClassHasToImplementCommonInterface() { - $cm = new ClassMetadataInfo('stdClass'); + $cm = new ClassMetadata('stdClass'); $cm->mapField(array( 'fieldName' => 'assoc', diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/NestedCollectionsTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/NestedCollectionsTest.php index 70b8d66616..dfb8a6a49f 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Functional/NestedCollectionsTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/NestedCollectionsTest.php @@ -3,7 +3,7 @@ namespace Doctrine\ODM\MongoDB\Tests\Functional; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Documents\Phonebook; use Documents\Phonenumber; @@ -64,12 +64,12 @@ public function testStrategy($field) public function provideStrategy() { return array( - array(ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET), - array(ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET_ARRAY), - array(ClassMetadataInfo::STORAGE_STRATEGY_SET), - array(ClassMetadataInfo::STORAGE_STRATEGY_SET_ARRAY), - array(ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL), - array(ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET), + array(ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET), + array(ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET_ARRAY), + array(ClassMetadata::STORAGE_STRATEGY_SET), + array(ClassMetadata::STORAGE_STRATEGY_SET_ARRAY), + array(ClassMetadata::STORAGE_STRATEGY_PUSH_ALL), + array(ClassMetadata::STORAGE_STRATEGY_ADD_TO_SET), ); } } diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php index 3050a0dd9e..05d6be3400 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php @@ -4,7 +4,6 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Doctrine\ODM\MongoDB\Proxy\Proxy; use Doctrine\ODM\MongoDB\Query\Query; use Documents\Account; @@ -450,7 +449,7 @@ public function testPrimeReferencesInFindAndModifyResult() $this->dm->persist($group); $this->dm->flush(); - $groupDBRef = $this->dm->createReference($group, ['storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF, 'targetDocument' => Group::class]); + $groupDBRef = $this->dm->createReference($group, ['storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, 'targetDocument' => Group::class]); $this->dm->clear(); diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH1275Test.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH1275Test.php index 9a16e918af..39e8447630 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH1275Test.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH1275Test.php @@ -4,7 +4,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; class GH1275Test extends \Doctrine\ODM\MongoDB\Tests\BaseTest { @@ -133,12 +133,12 @@ public function testResortAtomicCollections() public static function getCollectionStrategies() { return array( - 'testResortWithStrategyAddToSet' => array(ClassMetadataInfo::STORAGE_STRATEGY_ADD_TO_SET), - 'testResortWithStrategySet' => array(ClassMetadataInfo::STORAGE_STRATEGY_SET), - 'testResortWithStrategySetArray' => array(ClassMetadataInfo::STORAGE_STRATEGY_SET_ARRAY), - 'testResortWithStrategyPushAll' => array(ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL), - 'testResortWithStrategyAtomicSet' => array(ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET), - 'testResortWithStrategyAtomicSetArray' => array(ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET_ARRAY), + 'testResortWithStrategyAddToSet' => array(ClassMetadata::STORAGE_STRATEGY_ADD_TO_SET), + 'testResortWithStrategySet' => array(ClassMetadata::STORAGE_STRATEGY_SET), + 'testResortWithStrategySetArray' => array(ClassMetadata::STORAGE_STRATEGY_SET_ARRAY), + 'testResortWithStrategyPushAll' => array(ClassMetadata::STORAGE_STRATEGY_PUSH_ALL), + 'testResortWithStrategyAtomicSet' => array(ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET), + 'testResortWithStrategyAtomicSetArray' => array(ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET_ARRAY), ); } diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataInfoTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataInfoTest.php deleted file mode 100644 index 12518a6d19..0000000000 --- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataInfoTest.php +++ /dev/null @@ -1,533 +0,0 @@ -assertNull($cm->slaveOkay); - } - - public function testDefaultDiscriminatorField() - { - $cm = new ClassMetadataInfo('stdClass'); - - $cm->mapField(array( - 'fieldName' => 'assoc', - 'reference' => true, - 'type' => 'one', - )); - - $cm->mapField(array( - 'fieldName' => 'assocWithTargetDocument', - 'reference' => true, - 'type' => 'one', - 'targetDocument' => 'stdClass', - )); - - $cm->mapField(array( - 'fieldName' => 'assocWithDiscriminatorField', - 'reference' => true, - 'type' => 'one', - 'discriminatorField' => 'type', - )); - - $mapping = $cm->getFieldMapping('assoc'); - - $this->assertEquals( - ClassMetadataInfo::DEFAULT_DISCRIMINATOR_FIELD, $mapping['discriminatorField'], - 'Default discriminator field is set for associations without targetDocument and discriminatorField options' - ); - - $mapping = $cm->getFieldMapping('assocWithTargetDocument'); - - $this->assertArrayNotHasKey( - 'discriminatorField', $mapping, - 'Default discriminator field is not set for associations with targetDocument option' - ); - - $mapping = $cm->getFieldMapping('assocWithDiscriminatorField'); - - $this->assertEquals( - 'type', $mapping['discriminatorField'], - 'Default discriminator field is not set for associations with discriminatorField option' - ); - } - - public function testGetFieldValue() - { - $document = new Album('ten'); - $metadata = $this->dm->getClassMetadata('Documents\Album'); - - $this->assertEquals($document->getName(), $metadata->getFieldValue($document, 'name')); - } - - public function testGetFieldValueInitializesProxy() - { - $document = new Album('ten'); - $this->dm->persist($document); - $this->dm->flush(); - $this->dm->clear(); - - $proxy = $this->dm->getReference('Documents\Album', $document->getId()); - $metadata = $this->dm->getClassMetadata('Documents\Album'); - - $this->assertEquals($document->getName(), $metadata->getFieldValue($proxy, 'name')); - $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); - $this->assertTrue($proxy->__isInitialized()); - } - - public function testGetFieldValueOfIdentifierDoesNotInitializeProxy() - { - $document = new Album('ten'); - $this->dm->persist($document); - $this->dm->flush(); - $this->dm->clear(); - - $proxy = $this->dm->getReference('Documents\Album', $document->getId()); - $metadata = $this->dm->getClassMetadata('Documents\Album'); - - $this->assertEquals($document->getId(), $metadata->getFieldValue($proxy, 'id')); - $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); - $this->assertFalse($proxy->__isInitialized()); - } - - public function testSetFieldValue() - { - $document = new Album('ten'); - $metadata = $this->dm->getClassMetadata('Documents\Album'); - - $metadata->setFieldValue($document, 'name', 'nevermind'); - - $this->assertEquals('nevermind', $document->getName()); - } - - public function testSetFieldValueWithProxy() - { - $document = new Album('ten'); - $this->dm->persist($document); - $this->dm->flush(); - $this->dm->clear(); - - $proxy = $this->dm->getReference('Documents\Album', $document->getId()); - $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); - - $metadata = $this->dm->getClassMetadata('Documents\Album'); - $metadata->setFieldValue($proxy, 'name', 'nevermind'); - - $this->dm->flush(); - $this->dm->clear(); - - $proxy = $this->dm->getReference('Documents\Album', $document->getId()); - $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); - - $this->assertEquals('nevermind', $proxy->getName()); - } - - public function testSetCustomRepositoryClass() - { - $cm = new ClassMetadataInfo('Doctrine\ODM\MongoDB\Tests\Mapping\ClassMetadataInfoTest'); - $cm->namespace = 'Doctrine\ODM\MongoDB\Tests\Mapping'; - - $cm->setCustomRepositoryClass('TestCustomRepositoryClass'); - - $this->assertEquals('Doctrine\ODM\MongoDB\Tests\Mapping\TestCustomRepositoryClass', $cm->customRepositoryClassName); - - $cm->setCustomRepositoryClass('Doctrine\ODM\MongoDB\Tests\Mapping\TestCustomRepositoryClass'); - - $this->assertEquals('Doctrine\ODM\MongoDB\Tests\Mapping\TestCustomRepositoryClass', $cm->customRepositoryClassName); - } - - public function testEmbeddedAssociationsAlwaysCascade() - { - $class = $this->dm->getClassMetadata(__NAMESPACE__ . '\EmbeddedAssociationsCascadeTest'); - - $this->assertTrue($class->fieldMappings['address']['isCascadeRemove']); - $this->assertTrue($class->fieldMappings['address']['isCascadePersist']); - $this->assertTrue($class->fieldMappings['address']['isCascadeRefresh']); - $this->assertTrue($class->fieldMappings['address']['isCascadeMerge']); - $this->assertTrue($class->fieldMappings['address']['isCascadeDetach']); - - $this->assertTrue($class->fieldMappings['addresses']['isCascadeRemove']); - $this->assertTrue($class->fieldMappings['addresses']['isCascadePersist']); - $this->assertTrue($class->fieldMappings['addresses']['isCascadeRefresh']); - $this->assertTrue($class->fieldMappings['addresses']['isCascadeMerge']); - $this->assertTrue($class->fieldMappings['addresses']['isCascadeDetach']); - } - - /** - * @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', - )); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Expected document class "Documents\User"; found: "stdClass" - */ - public function testInvokeLifecycleCallbacksShouldRequireInstanceOfClass() - { - $class = $this->dm->getClassMetadata('\Documents\User'); - $document = new \stdClass(); - - $this->assertInstanceOf('\stdClass', $document); - - $class->invokeLifecycleCallbacks(Events::prePersist, $document); - } - - public function testInvokeLifecycleCallbacksAllowsInstanceOfClass() - { - $class = $this->dm->getClassMetadata('\Documents\User'); - $document = new Specialuser(); - - $this->assertInstanceOf('\Documents\SpecialUser', $document); - - $class->invokeLifecycleCallbacks(Events::prePersist, $document); - } - - public function testInvokeLifecycleCallbacksShouldAllowProxyOfExactClass() - { - $document = new User(); - $this->dm->persist($document); - $this->dm->flush(); - $this->dm->clear(); - - $class = $this->dm->getClassMetadata('\Documents\User'); - $proxy = $this->dm->getReference('\Documents\User', $document->getId()); - - $this->assertInstanceOf('\Documents\User', $proxy); - - $class->invokeLifecycleCallbacks(Events::prePersist, $proxy); - } - - /** - * @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, - )); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage Target document must be specified for simple reference: stdClass::assoc - */ - public function testSimpleAsStringReferenceRequiresTargetDocument() - { - $cm = new ClassMetadataInfo('stdClass'); - - $cm->mapField(array( - 'fieldName' => 'assoc', - 'reference' => true, - 'type' => 'one', - 'simple' => 'true', - )); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage Target document must be specified for simple reference: stdClass::assoc - */ - public function testStoreAsIdReferenceRequiresTargetDocument() - { - $cm = new ClassMetadataInfo('stdClass'); - - $cm->mapField(array( - 'fieldName' => 'assoc', - 'reference' => true, - 'type' => 'one', - 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_ID, - )); - } - - /** - * @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' => ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET, - )); - } - - public function testDefaultStorageStrategyOfEmbeddedDocumentFields() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->isEmbeddedDocument = true; - - $mapping = $cm->mapField(array( - 'fieldName' => 'many', - 'type' => 'many' - )); - - self::assertEquals(CollectionHelper::DEFAULT_STRATEGY, $mapping['strategy']); - } - - /** - * @dataProvider provideOwningAndInversedRefsNeedTargetDocument - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - */ - public function testOwningAndInversedRefsNeedTargetDocument($config) - { - $config = array_merge($config, array( - 'fieldName' => 'many', - 'reference' => true, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_ATOMIC_SET, - )); - - $cm = new ClassMetadataInfo('stdClass'); - $cm->isEmbeddedDocument = true; - $cm->mapField($config); - } - - public function provideOwningAndInversedRefsNeedTargetDocument() - { - return array( - array(array('type' => 'one', 'mappedBy' => 'post')), - array(array('type' => 'one', 'inversedBy' => 'post')), - array(array('type' => 'many', 'mappedBy' => 'post')), - array(array('type' => 'many', 'inversedBy' => 'post')), - ); - } - - public function testAddInheritedAssociationMapping() - { - $cm = new ClassMetadataInfo('stdClass'); - - $mapping = array( - 'fieldName' => 'assoc', - 'reference' => true, - 'type' => 'one', - 'simple' => true, - ); - - $cm->addInheritedAssociationMapping($mapping); - - $expected = array( - 'assoc' => $mapping, - ); - - $this->assertEquals($expected, $cm->associationMappings); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage stdClass::id was declared an identifier and must stay this way. - */ - public function testIdFieldsTypeMustNotBeOverridden() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->setIdentifier('id'); - $cm->mapField(array( - 'fieldName' => 'id', - 'type' => 'string' - )); - } - - /** - * @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' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, - 'type' => 'many', - 'sort' => array('foo' => 1) - )); - } - - public function testIncrementTypeAutomaticallyAssumesIncrementStrategy() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->mapField([ - 'fieldName' => 'incrementField', - 'type' => 'increment', - ]); - - $mapping = $cm->fieldMappings['incrementField']; - $this->assertSame(ClassMetadataInfo::STORAGE_STRATEGY_INCREMENT, $mapping['strategy']); - } - - public function testSetShardKeyForClassWithoutInheritance() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->setShardKey(array('id' => 'asc')); - - $shardKey = $cm->getShardKey(); - - $this->assertEquals(array('id' => 1), $shardKey['keys']); - } - - public function testSetShardKeyForClassWithSingleCollectionInheritance() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->inheritanceType = ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION; - $cm->setShardKey(array('id' => 'asc')); - - $shardKey = $cm->getShardKey(); - - $this->assertEquals(array('id' => 1), $shardKey['keys']); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage Shard key overriding in subclass is forbidden for single collection inheritance - */ - public function testSetShardKeyForClassWithSingleCollectionInheritanceWhichAlreadyHasIt() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->setShardKey(array('id' => 'asc')); - $cm->inheritanceType = ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION; - - $cm->setShardKey(array('foo' => 'asc')); - } - - public function testSetShardKeyForClassWithCollPerClassInheritance() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->inheritanceType = ClassMetadataInfo::INHERITANCE_TYPE_COLLECTION_PER_CLASS; - $cm->setShardKey(array('id' => 'asc')); - - $shardKey = $cm->getShardKey(); - - $this->assertEquals(array('id' => 1), $shardKey['keys']); - } - - public function testIsNotShardedIfThereIsNoShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - - $this->assertFalse($cm->isSharded()); - } - - public function testIsShardedIfThereIsAShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->setShardKey(array('id' => 'asc')); - - $this->assertTrue($cm->isSharded()); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage Embedded document can't have shard key: stdClass - */ - public function testEmbeddedDocumentCantHaveShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->isEmbeddedDocument = true; - $cm->setShardKey(array('id' => 'asc')); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage Only fields using the SET strategy can be used in the shard key - */ - public function testNoIncrementFieldsAllowedInShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->mapField([ - 'fieldName' => 'inc', - 'type' => 'int', - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_INCREMENT, - ]); - $cm->setShardKey(array('inc' => 1)); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage No multikey indexes are allowed in the shard key - */ - public function testNoCollectionsInShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->mapField([ - 'fieldName' => 'collection', - 'type' => 'collection' - ]); - $cm->setShardKey(array('collection' => 1)); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage No multikey indexes are allowed in the shard key - */ - public function testNoEmbedManyInShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->mapManyEmbedded(['fieldName' => 'embedMany']); - $cm->setShardKey(array('embedMany' => 1)); - } - - /** - * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException - * @expectedExceptionMessage No multikey indexes are allowed in the shard key - */ - public function testNoReferenceManyInShardKey() - { - $cm = new ClassMetadataInfo('stdClass'); - $cm->mapManyEmbedded(['fieldName' => 'referenceMany']); - $cm->setShardKey(array('referenceMany' => 1)); - } -} - -class TestCustomRepositoryClass extends DocumentRepository -{ -} - -class EmbedWithCascadeTest -{ - public $address; -} - -/** @ODM\Document */ -class EmbeddedAssociationsCascadeTest -{ - /** @ODM\Id */ - public $id; - - /** @ODM\EmbedOne(targetDocument="Documents\Address") */ - public $address; - - /** @ODM\EmbedOne(targetDocument="Documents\Address") */ - public $addresses; -} diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php index d5ecf13882..a0cf628492 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php @@ -2,12 +2,511 @@ namespace Doctrine\ODM\MongoDB\Tests\Mapping; +use Doctrine\ODM\MongoDB\DocumentRepository; +use Doctrine\ODM\MongoDB\Events; +use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\MappingException; +use Doctrine\ODM\MongoDB\Utility\CollectionHelper; +use Documents\Album; use Documents\CmsUser; +use Documents\SpecialUser; +use Documents\User; +use InvalidArgumentException; class ClassMetadataTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest { + public function testSlaveOkayDefault() + { + $cm = new ClassMetadata(TestDocument::class); + + $this->assertNull($cm->slaveOkay); + } + + public function testDefaultDiscriminatorField() + { + $cm = new ClassMetadata(TestDocument::class); + + $cm->mapField(array( + 'fieldName' => 'assoc', + 'reference' => true, + 'type' => 'one', + )); + + $cm->mapField(array( + 'fieldName' => 'assocWithTargetDocument', + 'reference' => true, + 'type' => 'one', + 'targetDocument' => TestDocument::class, + )); + + $cm->mapField(array( + 'fieldName' => 'assocWithDiscriminatorField', + 'reference' => true, + 'type' => 'one', + 'discriminatorField' => 'type', + )); + + $mapping = $cm->getFieldMapping('assoc'); + + $this->assertEquals( + ClassMetadata::DEFAULT_DISCRIMINATOR_FIELD, $mapping['discriminatorField'], + 'Default discriminator field is set for associations without targetDocument and discriminatorField options' + ); + + $mapping = $cm->getFieldMapping('assocWithTargetDocument'); + + $this->assertArrayNotHasKey( + 'discriminatorField', $mapping, + 'Default discriminator field is not set for associations with targetDocument option' + ); + + $mapping = $cm->getFieldMapping('assocWithDiscriminatorField'); + + $this->assertEquals( + 'type', $mapping['discriminatorField'], + 'Default discriminator field is not set for associations with discriminatorField option' + ); + } + + public function testGetFieldValue() + { + $document = new Album('ten'); + $metadata = $this->dm->getClassMetadata('Documents\Album'); + + $this->assertEquals($document->getName(), $metadata->getFieldValue($document, 'name')); + } + + public function testGetFieldValueInitializesProxy() + { + $document = new Album('ten'); + $this->dm->persist($document); + $this->dm->flush(); + $this->dm->clear(); + + $proxy = $this->dm->getReference('Documents\Album', $document->getId()); + $metadata = $this->dm->getClassMetadata('Documents\Album'); + + $this->assertEquals($document->getName(), $metadata->getFieldValue($proxy, 'name')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); + $this->assertTrue($proxy->__isInitialized()); + } + + public function testGetFieldValueOfIdentifierDoesNotInitializeProxy() + { + $document = new Album('ten'); + $this->dm->persist($document); + $this->dm->flush(); + $this->dm->clear(); + + $proxy = $this->dm->getReference('Documents\Album', $document->getId()); + $metadata = $this->dm->getClassMetadata('Documents\Album'); + + $this->assertEquals($document->getId(), $metadata->getFieldValue($proxy, 'id')); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); + $this->assertFalse($proxy->__isInitialized()); + } + + public function testSetFieldValue() + { + $document = new Album('ten'); + $metadata = $this->dm->getClassMetadata('Documents\Album'); + + $metadata->setFieldValue($document, 'name', 'nevermind'); + + $this->assertEquals('nevermind', $document->getName()); + } + + public function testSetFieldValueWithProxy() + { + $document = new Album('ten'); + $this->dm->persist($document); + $this->dm->flush(); + $this->dm->clear(); + + $proxy = $this->dm->getReference('Documents\Album', $document->getId()); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); + + $metadata = $this->dm->getClassMetadata('Documents\Album'); + $metadata->setFieldValue($proxy, 'name', 'nevermind'); + + $this->dm->flush(); + $this->dm->clear(); + + $proxy = $this->dm->getReference('Documents\Album', $document->getId()); + $this->assertInstanceOf('Doctrine\ODM\MongoDB\Proxy\Proxy', $proxy); + + $this->assertEquals('nevermind', $proxy->getName()); + } + + public function testSetCustomRepositoryClass() + { + $cm = new ClassMetadata('Doctrine\ODM\MongoDB\Tests\Mapping\ClassMetadataTest'); + $cm->namespace = 'Doctrine\ODM\MongoDB\Tests\Mapping'; + + $cm->setCustomRepositoryClass('TestCustomRepositoryClass'); + + $this->assertEquals('Doctrine\ODM\MongoDB\Tests\Mapping\TestCustomRepositoryClass', $cm->customRepositoryClassName); + + $cm->setCustomRepositoryClass('Doctrine\ODM\MongoDB\Tests\Mapping\TestCustomRepositoryClass'); + + $this->assertEquals('Doctrine\ODM\MongoDB\Tests\Mapping\TestCustomRepositoryClass', $cm->customRepositoryClassName); + } + + public function testEmbeddedAssociationsAlwaysCascade() + { + $class = $this->dm->getClassMetadata(__NAMESPACE__ . '\EmbeddedAssociationsCascadeTest'); + + $this->assertTrue($class->fieldMappings['address']['isCascadeRemove']); + $this->assertTrue($class->fieldMappings['address']['isCascadePersist']); + $this->assertTrue($class->fieldMappings['address']['isCascadeRefresh']); + $this->assertTrue($class->fieldMappings['address']['isCascadeMerge']); + $this->assertTrue($class->fieldMappings['address']['isCascadeDetach']); + + $this->assertTrue($class->fieldMappings['addresses']['isCascadeRemove']); + $this->assertTrue($class->fieldMappings['addresses']['isCascadePersist']); + $this->assertTrue($class->fieldMappings['addresses']['isCascadeRefresh']); + $this->assertTrue($class->fieldMappings['addresses']['isCascadeMerge']); + $this->assertTrue($class->fieldMappings['addresses']['isCascadeDetach']); + } + + /** + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + * @expectedExceptionMessage Cascade on Doctrine\ODM\MongoDB\Tests\Mapping\EmbedWithCascadeTest::address is not allowed. + */ + public function testEmbedWithCascadeThrowsMappingException() + { + $class = new ClassMetadata(__NAMESPACE__ . '\EmbedWithCascadeTest'); + $class->mapOneEmbedded(array( + 'fieldName' => 'address', + 'targetDocument' => 'Documents\Address', + 'cascade' => 'all', + )); + } + + public function testInvokeLifecycleCallbacksShouldRequireInstanceOfClass() + { + $class = $this->dm->getClassMetadata(User::class); + $document = new TestDocument(); + + $this->assertInstanceOf(TestDocument::class, $document); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf('Expected document class "%s"; found: "%s"', User::class, TestDocument::class)); + + $class->invokeLifecycleCallbacks(Events::prePersist, $document); + } + + public function testInvokeLifecycleCallbacksAllowsInstanceOfClass() + { + $class = $this->dm->getClassMetadata('\Documents\User'); + $document = new Specialuser(); + + $this->assertInstanceOf('\Documents\SpecialUser', $document); + + $class->invokeLifecycleCallbacks(Events::prePersist, $document); + } + + public function testInvokeLifecycleCallbacksShouldAllowProxyOfExactClass() + { + $document = new User(); + $this->dm->persist($document); + $this->dm->flush(); + $this->dm->clear(); + + $class = $this->dm->getClassMetadata('\Documents\User'); + $proxy = $this->dm->getReference('\Documents\User', $document->getId()); + + $this->assertInstanceOf('\Documents\User', $proxy); + + $class->invokeLifecycleCallbacks(Events::prePersist, $proxy); + } + + public function testSimpleReferenceRequiresTargetDocument() + { + $cm = new ClassMetadata(TestDocument::class); + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('Target document must be specified for simple reference: %s::assoc', TestDocument::class)); + + $cm->mapField(array( + 'fieldName' => 'assoc', + 'reference' => true, + 'type' => 'one', + 'simple' => true, + )); + } + + public function testSimpleAsStringReferenceRequiresTargetDocument() + { + $cm = new ClassMetadata(TestDocument::class); + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('Target document must be specified for simple reference: %s::assoc', TestDocument::class)); + + $cm->mapField(array( + 'fieldName' => 'assoc', + 'reference' => true, + 'type' => 'one', + 'simple' => 'true', + )); + } + + public function testStoreAsIdReferenceRequiresTargetDocument() + { + $cm = new ClassMetadata(TestDocument::class); + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('Target document must be specified for simple reference: %s::assoc', TestDocument::class)); + + $cm->mapField(array( + 'fieldName' => 'assoc', + 'reference' => true, + 'type' => 'one', + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_ID, + )); + } + + public function testAtomicCollectionUpdateUsageInEmbeddedDocument() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->isEmbeddedDocument = true; + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('atomicSet collection strategy can be used only in top level document, used in %s::many', TestDocument::class)); + + $cm->mapField(array( + 'fieldName' => 'many', + 'reference' => true, + 'type' => 'many', + 'strategy' => ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET, + )); + } + + public function testDefaultStorageStrategyOfEmbeddedDocumentFields() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->isEmbeddedDocument = true; + + $mapping = $cm->mapField(array( + 'fieldName' => 'many', + 'type' => 'many' + )); + + self::assertEquals(CollectionHelper::DEFAULT_STRATEGY, $mapping['strategy']); + } + + /** + * @dataProvider provideOwningAndInversedRefsNeedTargetDocument + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + */ + public function testOwningAndInversedRefsNeedTargetDocument($config) + { + $config = array_merge($config, array( + 'fieldName' => 'many', + 'reference' => true, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET, + )); + + $cm = new ClassMetadata(TestDocument::class); + $cm->isEmbeddedDocument = true; + $cm->mapField($config); + } + + public function provideOwningAndInversedRefsNeedTargetDocument() + { + return array( + array(array('type' => 'one', 'mappedBy' => 'post')), + array(array('type' => 'one', 'inversedBy' => 'post')), + array(array('type' => 'many', 'mappedBy' => 'post')), + array(array('type' => 'many', 'inversedBy' => 'post')), + ); + } + + public function testAddInheritedAssociationMapping() + { + $cm = new ClassMetadata(TestDocument::class); + + $mapping = array( + 'fieldName' => 'assoc', + 'reference' => true, + 'type' => 'one', + 'simple' => true, + ); + + $cm->addInheritedAssociationMapping($mapping); + + $expected = array( + 'assoc' => $mapping, + ); + + $this->assertEquals($expected, $cm->associationMappings); + } + + public function testIdFieldsTypeMustNotBeOverridden() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->setIdentifier('id'); + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('%s::id was declared an identifier and must stay this way.', TestDocument::class)); + + $cm->mapField(array( + 'fieldName' => 'id', + 'type' => 'string' + )); + } + + public function testReferenceManySortMustNotBeUsedWithNonSetCollectionStrategy() + { + $cm = new ClassMetadata(TestDocument::class); + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('ReferenceMany\'s sort can not be used with addToSet and pushAll strategies, pushAll used in %s::ref', TestDocument::class)); + + $cm->mapField(array( + 'fieldName' => 'ref', + 'reference' => true, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_PUSH_ALL, + 'type' => 'many', + 'sort' => array('foo' => 1) + )); + } + + public function testIncrementTypeAutomaticallyAssumesIncrementStrategy() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->mapField([ + 'fieldName' => 'incrementField', + 'type' => 'increment', + ]); + + $mapping = $cm->fieldMappings['incrementField']; + $this->assertSame(ClassMetadata::STORAGE_STRATEGY_INCREMENT, $mapping['strategy']); + } + + public function testSetShardKeyForClassWithoutInheritance() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->setShardKey(array('id' => 'asc')); + + $shardKey = $cm->getShardKey(); + + $this->assertEquals(array('id' => 1), $shardKey['keys']); + } + + public function testSetShardKeyForClassWithSingleCollectionInheritance() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->inheritanceType = ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION; + $cm->setShardKey(array('id' => 'asc')); + + $shardKey = $cm->getShardKey(); + + $this->assertEquals(array('id' => 1), $shardKey['keys']); + } + + /** + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + * @expectedExceptionMessage Shard key overriding in subclass is forbidden for single collection inheritance + */ + public function testSetShardKeyForClassWithSingleCollectionInheritanceWhichAlreadyHasIt() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->setShardKey(array('id' => 'asc')); + $cm->inheritanceType = ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION; + + $cm->setShardKey(array('foo' => 'asc')); + } + + public function testSetShardKeyForClassWithCollPerClassInheritance() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->inheritanceType = ClassMetadata::INHERITANCE_TYPE_COLLECTION_PER_CLASS; + $cm->setShardKey(array('id' => 'asc')); + + $shardKey = $cm->getShardKey(); + + $this->assertEquals(array('id' => 1), $shardKey['keys']); + } + + public function testIsNotShardedIfThereIsNoShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + + $this->assertFalse($cm->isSharded()); + } + + public function testIsShardedIfThereIsAShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->setShardKey(array('id' => 'asc')); + + $this->assertTrue($cm->isSharded()); + } + + public function testEmbeddedDocumentCantHaveShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->isEmbeddedDocument = true; + + $this->expectException(MappingException::class); + $this->expectExceptionMessage(sprintf('Embedded document can\'t have shard key: %s', TestDocument::class)); + + $cm->setShardKey(array('id' => 'asc')); + } + + /** + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + * @expectedExceptionMessage Only fields using the SET strategy can be used in the shard key + */ + public function testNoIncrementFieldsAllowedInShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->mapField([ + 'fieldName' => 'inc', + 'type' => 'int', + 'strategy' => ClassMetadata::STORAGE_STRATEGY_INCREMENT, + ]); + $cm->setShardKey(array('inc' => 1)); + } + + /** + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + * @expectedExceptionMessage No multikey indexes are allowed in the shard key + */ + public function testNoCollectionsInShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->mapField([ + 'fieldName' => 'collection', + 'type' => 'collection' + ]); + $cm->setShardKey(array('collection' => 1)); + } + + /** + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + * @expectedExceptionMessage No multikey indexes are allowed in the shard key + */ + public function testNoEmbedManyInShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->mapManyEmbedded(['fieldName' => 'embedMany']); + $cm->setShardKey(array('embedMany' => 1)); + } + + /** + * @expectedException \Doctrine\ODM\MongoDB\Mapping\MappingException + * @expectedExceptionMessage No multikey indexes are allowed in the shard key + */ + public function testNoReferenceManyInShardKey() + { + $cm = new ClassMetadata(TestDocument::class); + $cm->mapManyEmbedded(['fieldName' => 'referenceMany']); + $cm->setShardKey(array('referenceMany' => 1)); + } + public function testClassMetadataInstanceSerialization() { $cm = new ClassMetadata('Documents\CmsUser'); @@ -68,11 +567,11 @@ public function testClassMetadataInstanceSerialization() public function testOwningSideAndInverseSide() { - $cm = new ClassMetadataInfo('Documents\User'); + $cm = new ClassMetadata('Documents\User'); $cm->mapManyReference(array('fieldName' => 'articles', 'targetDocument' => 'Documents\Article', 'inversedBy' => 'user')); $this->assertTrue($cm->fieldMappings['articles']['isOwningSide']); - $cm = new ClassMetadataInfo('Documents\Article'); + $cm = new ClassMetadata('Documents\Article'); $cm->mapOneReference(array('fieldName' => 'user', 'targetDocument' => 'Documents\User', 'mappedBy' => 'articles')); $this->assertTrue($cm->fieldMappings['user']['isInverseSide']); } @@ -153,7 +652,7 @@ public function testSetSubClassesInGlobalNamespace() public function testDuplicateFieldMapping() { $cm = new ClassMetadata('Documents\CmsUser'); - $a1 = array('reference' => true, 'type' => 'many', 'fieldName' => 'name', 'targetDocument' => 'stdClass'); + $a1 = array('reference' => true, 'type' => 'many', 'fieldName' => 'name', 'targetDocument' => TestDocument::class); $a2 = array('type' => 'string', 'fieldName' => 'name'); $cm->mapField($a1); @@ -240,3 +739,48 @@ public static function dataProviderMetadataClasses() ]; } } + +class TestDocument +{ + public $assoc; + + public $assocWithTargetDocument; + + public $assocWithDiscriminatorField; + + public $many; + + public $incrementField; + + public $inc; + + public $collection; + + public $embedMany; + + public $referenceMany; + + public $articles; +} + +class TestCustomRepositoryClass extends DocumentRepository +{ +} + +class EmbedWithCascadeTest +{ + public $address; +} + +/** @ODM\Document */ +class EmbeddedAssociationsCascadeTest +{ + /** @ODM\Id */ + public $id; + + /** @ODM\EmbedOne(targetDocument="Documents\Address") */ + public $address; + + /** @ODM\EmbedOne(targetDocument="Documents\Address") */ + public $addresses; +} diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php index 37faca4aed..81b66ddfcb 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php @@ -3,7 +3,6 @@ namespace Doctrine\ODM\MongoDB\Tests\Mapping\Driver; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use TestDocuments\PrimedCollectionDocument; use PHPUnit\Framework\TestCase; @@ -63,7 +62,7 @@ public function testDriver() 'nullable' => false, 'unique' => true, 'sparse' => true, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['username']); $this->assertEquals(array( @@ -85,7 +84,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['createdAt']); $this->assertEquals(array( @@ -100,7 +99,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['tags']); $this->assertEquals(array( @@ -119,7 +118,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['address']); $this->assertEquals(array( @@ -138,7 +137,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_PUSH_ALL, ), $classMetadata->fieldMappings['phonenumbers']); $this->assertEquals(array( @@ -147,7 +146,7 @@ public function testDriver() 'name' => 'profile', 'type' => 'one', 'reference' => true, - 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_ID, + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_ID, 'simple' => true, 'targetDocument' => 'Documents\Profile', 'collectionClass' => null, @@ -160,7 +159,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, 'inversedBy' => null, 'mappedBy' => null, 'repositoryMethod' => null, @@ -176,7 +175,7 @@ public function testDriver() 'name' => 'account', 'type' => 'one', 'reference' => true, - 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, 'simple' => false, 'targetDocument' => 'Documents\Account', 'collectionClass' => null, @@ -189,7 +188,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, 'inversedBy' => null, 'mappedBy' => null, 'repositoryMethod' => null, @@ -205,7 +204,7 @@ public function testDriver() 'name' => 'groups', 'type' => 'many', 'reference' => true, - 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, 'simple' => false, 'targetDocument' => 'Documents\Group', 'collectionClass' => null, @@ -218,7 +217,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_PUSH_ALL, 'inversedBy' => null, 'mappedBy' => null, 'repositoryMethod' => null, @@ -258,7 +257,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['name']); $classMetadata = new ClassMetadata('TestDocuments\QueryResultDocument'); @@ -276,7 +275,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['name']); $this->assertEquals(array( @@ -291,7 +290,7 @@ public function testDriver() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_SET, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_SET, ), $classMetadata->fieldMappings['count']); } @@ -343,7 +342,7 @@ public function testCollectionPrimers() 'name' => 'references', 'type' => 'many', 'reference' => true, - 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, 'simple' => false, 'targetDocument' => PrimedCollectionDocument::class, 'collectionClass' => null, @@ -356,7 +355,7 @@ public function testCollectionPrimers() 'isInverseSide' => false, 'isOwningSide' => true, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_PUSH_ALL, 'inversedBy' => null, 'mappedBy' => null, 'repositoryMethod' => null, @@ -372,7 +371,7 @@ public function testCollectionPrimers() 'name' => 'inverseMappedBy', 'type' => 'many', 'reference' => true, - 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, 'simple' => false, 'targetDocument' => PrimedCollectionDocument::class, 'collectionClass' => null, @@ -385,7 +384,7 @@ public function testCollectionPrimers() 'isInverseSide' => true, 'isOwningSide' => false, 'nullable' => false, - 'strategy' => ClassMetadataInfo::STORAGE_STRATEGY_PUSH_ALL, + 'strategy' => ClassMetadata::STORAGE_STRATEGY_PUSH_ALL, 'inversedBy' => null, 'mappedBy' => 'references', 'repositoryMethod' => null, diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/XmlDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/XmlDriverTest.php index b04fd3334d..bcd4a4a1bd 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/XmlDriverTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/XmlDriverTest.php @@ -2,9 +2,8 @@ namespace Doctrine\ODM\MongoDB\Tests\Mapping\Driver; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; -use Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; +use Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver; use TestDocuments\UserCustomIdGenerator; use TestDocuments\UserCustomIdGeneratorWithIdField; @@ -58,11 +57,11 @@ public function testDriverShouldParseNonStringAttributes() $this->assertFalse($classMetadata->slaveOkay); $profileMapping = $classMetadata->fieldMappings['profile']; - $this->assertSame(ClassMetadataInfo::REFERENCE_STORE_AS_ID, $profileMapping['storeAs']); + $this->assertSame(ClassMetadata::REFERENCE_STORE_AS_ID, $profileMapping['storeAs']); $this->assertTrue($profileMapping['orphanRemoval']); $profileMapping = $classMetadata->fieldMappings['groups']; - $this->assertSame(ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB, $profileMapping['storeAs']); + $this->assertSame(ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB, $profileMapping['storeAs']); $this->assertFalse($profileMapping['orphanRemoval']); $this->assertSame(0, $profileMapping['limit']); $this->assertSame(2, $profileMapping['skip']); diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php index ace15b9cd1..fc059ea2d9 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php @@ -2,7 +2,7 @@ namespace Doctrine\ODM\MongoDB\Tests\Mapping; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Mapping\Driver\XmlDriver; class XmlMappingDriverTest extends AbstractMappingDriverTest @@ -14,7 +14,7 @@ protected function _loadDriver() public function testSetShardKeyOptionsByAttributes() { - $class = new ClassMetadataInfo('doc'); + $class = new ClassMetadata(XmlTestDocument::class); $driver = $this->_loadDriver(); $element = new \SimpleXmlElement(''); @@ -31,7 +31,7 @@ public function testSetShardKeyOptionsByAttributes() public function testGetAssociationCollectionClass() { - $class = new ClassMetadataInfo('doc'); + $class = new ClassMetadata(XmlTestDocument::class); $driver = $this->_loadDriver(); $element = new \SimpleXmlElement(''); @@ -43,3 +43,8 @@ public function testGetAssociationCollectionClass() $this->assertEquals('Doctrine\\ODM\\MongoDB\\Tests\\Mapping\\PhonenumberCollection', $class->getAssociationCollectionClass('phonenumbers')); } } + +class XmlTestDocument +{ + private $phonenumbers = []; +} diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Query/ExprTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Query/ExprTest.php index 56c22a0421..bf7c12deb9 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Query/ExprTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Query/ExprTest.php @@ -2,7 +2,7 @@ namespace Doctrine\ODM\MongoDB\Tests\Query; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Query\Expr; class ExprTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest @@ -206,7 +206,7 @@ public function testReferencesUsesMinimalKeys() ->will($this->returnValue($expected)); $class->expects($this->once()) ->method('getFieldMapping') - ->will($this->returnValue(array('targetDocument' => 'Foo', 'name' => 'foo', 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB))); + ->will($this->returnValue(array('targetDocument' => 'Foo', 'name' => 'foo', 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB))); $expr = new Expr($dm); $expr->setClassMetadata($class); @@ -239,7 +239,7 @@ public function testReferencesUsesAllKeys() ->will($this->returnValue($expected)); $class->expects($this->once()) ->method('getFieldMapping') - ->will($this->returnValue(array('name' => 'foo', 'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB))); + ->will($this->returnValue(array('name' => 'foo', 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF_WITH_DB))); $expr = new Expr($dm); $expr->setClassMetadata($class); @@ -272,7 +272,7 @@ public function testReferencesUsesSomeKeys() ->will($this->returnValue($expected)); $class->expects($this->once()) ->method('getFieldMapping') - ->will($this->returnValue(array('storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF, 'name' => 'foo'))); + ->will($this->returnValue(array('storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, 'name' => 'foo'))); $expr = new Expr($dm); $expr->setClassMetadata($class); diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Tools/DocumentGeneratorTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Tools/DocumentGeneratorTest.php index 89691c1ec6..cdaec8e0d1 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Tools/DocumentGeneratorTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Tools/DocumentGeneratorTest.php @@ -3,7 +3,7 @@ namespace Doctrine\ODM\MongoDB\Tests\Tools; use Doctrine\ODM\MongoDB\Tools\DocumentGenerator; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; class DocumentGeneratorTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest { @@ -39,7 +39,9 @@ public function tearDown() public function generateBookDocumentFixture() { - $metadata = new ClassMetadataInfo($this->namespace . '\DocumentGeneratorBook'); + $metadata = new ClassMetadata(DocumentGeneratorBook::class); + $metadata->name = $this->namespace . '\\DocumentGeneratorBook'; + $metadata->rootDocumentName = $this->namespace . '\\DocumentGeneratorBook'; $metadata->namespace = $this->namespace; $metadata->customRepositoryClassName = $this->namespace . '\DocumentGeneratorBookRepository'; @@ -47,18 +49,18 @@ public function generateBookDocumentFixture() $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->mapOneReference(array('fieldName' => 'author', 'targetDocument' => DocumentGeneratorAuthor::class)); $metadata->mapManyReference(array( 'fieldName' => 'comments', - 'targetDocument' => 'Doctrine\ODM\MongoDB\Tests\Tools\DocumentGeneratorComment' + 'targetDocument' => DocumentGeneratorComment::class )); $metadata->mapManyReference(array( 'fieldName' => 'searches', - 'targetDocument' => 'Doctrine\ODM\MongoDB\Tests\Tools\DocumentGeneratorSearch' + 'targetDocument' => DocumentGeneratorSearch::class )); $metadata->addLifecycleCallback('loading', 'postLoad'); $metadata->addLifecycleCallback('willBeRemoved', 'preRemove'); - $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_CUSTOM); + $metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM); $this->generator->writeDocumentClass($metadata, $this->tmpDir); @@ -66,7 +68,7 @@ public function generateBookDocumentFixture() } /** - * @param ClassMetadataInfo $metadata + * @param ClassMetadata $metadata * @return DocumentGeneratorBook */ public function newInstance($metadata) @@ -163,7 +165,7 @@ public function testLoadMetadata() $book = $this->newInstance($metadata); - $cm = new \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo($metadata->name); + $cm = new \Doctrine\ODM\MongoDB\Mapping\ClassMetadata($metadata->name); $reader = new \Doctrine\Common\Annotations\AnnotationReader(); $driver = new \Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver($reader); $driver->loadMetadataForClass($cm->name, $cm); @@ -181,7 +183,7 @@ public function testLoadPrefixedMetadata() $book = $this->newInstance($metadata); - $cm = new \Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo($metadata->name); + $cm = new \Doctrine\ODM\MongoDB\Mapping\ClassMetadata($metadata->name); $reader = new \Doctrine\Common\Annotations\AnnotationReader(); $driver = new \Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver($reader); $driver->loadMetadataForClass($cm->name, $cm); @@ -296,5 +298,15 @@ public function testMethodsAndPropertiesAreNotDuplicatedInChildClasses() } class DocumentGeneratorAuthor {} +class DocumentGeneratorBook +{ + public $id; + public $name; + public $status; + public $author; + public $comments; + public $searches; + public $test; +} class DocumentGeneratorComment {} class DocumentGeneratorSearch {} diff --git a/tests/Documents/Article.php b/tests/Documents/Article.php index 7ca4317125..05a55ab706 100644 --- a/tests/Documents/Article.php +++ b/tests/Documents/Article.php @@ -24,6 +24,8 @@ class Article /** @ODM\Field(type="collection") */ private $tags = array(); + private $user; + public function getId() { return $this->id; diff --git a/tests/Documents/User.php b/tests/Documents/User.php index b421fecbb2..8a1de4fd4b 100644 --- a/tests/Documents/User.php +++ b/tests/Documents/User.php @@ -86,6 +86,8 @@ class User extends BaseDocument /** @ODM\ReferenceMany(targetDocument="Documents\ReferenceUser", mappedBy="referencedUsers") */ protected $embeddedReferenceManyInverse; + protected $articles = array(); + /** @ODM\Field(type="collection") */ private $logs = array();