diff --git a/doctrine-mongo-mapping.xsd b/doctrine-mongo-mapping.xsd
index db193485b8..57a60acd86 100644
--- a/doctrine-mongo-mapping.xsd
+++ b/doctrine-mongo-mapping.xsd
@@ -109,10 +109,10 @@
+
-
@@ -154,6 +154,7 @@
+
@@ -165,7 +166,6 @@
-
diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php
index f40879852d..85653d2f96 100644
--- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php
+++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php
@@ -2058,6 +2058,24 @@ public function getAssociationTargetClass($assocName)
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}
*/
diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php
index 14ab346b72..82e4408a33 100644
--- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php
+++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php
@@ -244,11 +244,12 @@ private function addEmbedMapping(ClassMetadataInfo $class, $embed, $type)
$attributes = $embed->attributes();
$defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY;
$mapping = array(
- 'type' => $type,
- 'embedded' => true,
- 'targetDocument' => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null,
- 'name' => (string) $attributes['field'],
- 'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : $defaultStrategy,
+ 'type' => $type,
+ 'embedded' => true,
+ 'targetDocument' => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null,
+ 'collectionClass' => isset($attributes['collection-class']) ? (string) $attributes['collection-class'] : null,
+ 'name' => (string) $attributes['field'],
+ 'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : $defaultStrategy,
);
if (isset($attributes['fieldName'])) {
$mapping['fieldName'] = (string) $attributes['fieldName'];
@@ -291,6 +292,7 @@ private function addReferenceMapping(ClassMetadataInfo $class, $reference, $type
'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,
'targetDocument' => isset($attributes['target-document']) ? (string) $attributes['target-document'] : null,
+ 'collectionClass' => isset($attributes['collection-class']) ? (string) $attributes['collection-class'] : null,
'name' => (string) $attributes['field'],
'strategy' => isset($attributes['strategy']) ? (string) $attributes['strategy'] : $defaultStrategy,
'inversedBy' => isset($attributes['inversed-by']) ? (string) $attributes['inversed-by'] : null,
diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php
index 77cf4d375c..95fd1fdaab 100644
--- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php
+++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/YamlDriver.php
@@ -242,11 +242,12 @@ private function addMappingFromEmbed(ClassMetadataInfo $class, $fieldName, $embe
{
$defaultStrategy = $type == 'one' ? ClassMetadataInfo::STORAGE_STRATEGY_SET : CollectionHelper::DEFAULT_STRATEGY;
$mapping = array(
- 'type' => $type,
- 'embedded' => true,
- 'targetDocument' => isset($embed['targetDocument']) ? $embed['targetDocument'] : null,
- 'fieldName' => $fieldName,
- 'strategy' => isset($embed['strategy']) ? (string) $embed['strategy'] : $defaultStrategy,
+ 'type' => $type,
+ 'embedded' => true,
+ 'targetDocument' => isset($embed['targetDocument']) ? $embed['targetDocument'] : null,
+ 'collectionClass' => isset($embed['collectionClass']) ? $embed['collectionClass'] : null,
+ 'fieldName' => $fieldName,
+ 'strategy' => isset($embed['strategy']) ? (string) $embed['strategy'] : $defaultStrategy,
);
if (isset($embed['name'])) {
$mapping['name'] = $embed['name'];
@@ -274,6 +275,7 @@ private function addMappingFromReference(ClassMetadataInfo $class, $fieldName, $
'simple' => isset($reference['simple']) ? (boolean) $reference['simple'] : false, // deprecated
'storeAs' => isset($reference['storeAs']) ? (string) $reference['storeAs'] : ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB,
'targetDocument' => isset($reference['targetDocument']) ? $reference['targetDocument'] : null,
+ 'collectionClass' => isset($reference['collectionClass']) ? $reference['collectionClass'] : null,
'fieldName' => $fieldName,
'strategy' => isset($reference['strategy']) ? (string) $reference['strategy'] : $defaultStrategy,
'inversedBy' => isset($reference['inversedBy']) ? (string) $reference['inversedBy'] : null,
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/AbstractMappingDriverTest.php
index 5a81b391d0..1e04fa144c 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/AbstractMappingDriverTest.php
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/AbstractMappingDriverTest.php
@@ -405,7 +405,7 @@ class AbstractMappingDriverUser
public $address;
/**
- * @ODM\ReferenceMany(targetDocument="Phonenumber", cascade={"persist"}, discriminatorField="discr", discriminatorMap={"home"="HomePhonenumber", "work"="WorkPhonenumber"}, defaultDiscriminatorValue="home")
+ * @ODM\ReferenceMany(targetDocument="Phonenumber", collectionClass="PhonenumberCollection", cascade={"persist"}, discriminatorField="discr", discriminatorMap={"home"="HomePhonenumber", "work"="WorkPhonenumber"}, defaultDiscriminatorValue="home")
*/
public $phonenumbers;
@@ -415,7 +415,7 @@ class AbstractMappingDriverUser
public $groups;
/**
- * @ODM\ReferenceMany(targetDocument="Phonenumber", name="more_phone_numbers")
+ * @ODM\ReferenceMany(targetDocument="Phonenumber", collectionClass="PhonenumberCollection", name="more_phone_numbers")
*/
public $morePhoneNumbers;
@@ -509,6 +509,7 @@ public static function loadMetadata(ClassMetadata $metadata)
$metadata->mapManyReference(array(
'fieldName' => 'phonenumbers',
'targetDocument' => 'Doctrine\\ODM\\MongoDB\\Tests\\Mapping\\Phonenumber',
+ 'collectionClass' => 'Doctrine\\ODM\\MongoDB\\Tests\\Mapping\\PhonenumberCollection',
'cascade' => array(1 => 'persist'),
'discriminatorField' => 'discr',
'discriminatorMap' => array(
@@ -521,6 +522,7 @@ public static function loadMetadata(ClassMetadata $metadata)
'fieldName' => 'morePhoneNumbers',
'name' => 'more_phone_numbers',
'targetDocument' => 'Doctrine\\ODM\\MongoDB\\Tests\\Mapping\\Phonenumber',
+ 'collectionClass' => 'Doctrine\\ODM\\MongoDB\\Tests\\Mapping\\PhonenumberCollection',
));
$metadata->mapManyReference(array(
'fieldName' => 'groups',
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php
index 63305c7e8e..1bc1095d65 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTest.php
@@ -106,6 +106,7 @@ public function testDriver()
'type' => 'one',
'embedded' => true,
'targetDocument' => 'Documents\Address',
+ 'collectionClass' => null,
'isCascadeDetach' => true,
'isCascadeMerge' => true,
'isCascadePersist' => true,
@@ -124,6 +125,7 @@ public function testDriver()
'type' => 'many',
'embedded' => true,
'targetDocument' => 'Documents\Phonenumber',
+ 'collectionClass' => null,
'isCascadeDetach' => true,
'isCascadeMerge' => true,
'isCascadePersist' => true,
@@ -144,6 +146,7 @@ public function testDriver()
'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_ID,
'simple' => true,
'targetDocument' => 'Documents\Profile',
+ 'collectionClass' => null,
'cascade' => array('remove', 'persist', 'refresh', 'merge', 'detach'),
'isCascadeDetach' => true,
'isCascadeMerge' => true,
@@ -171,6 +174,7 @@ public function testDriver()
'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB,
'simple' => false,
'targetDocument' => 'Documents\Account',
+ 'collectionClass' => null,
'cascade' => array('remove', 'persist', 'refresh', 'merge', 'detach'),
'isCascadeDetach' => true,
'isCascadeMerge' => true,
@@ -198,6 +202,7 @@ public function testDriver()
'storeAs' => ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB,
'simple' => false,
'targetDocument' => 'Documents\Group',
+ 'collectionClass' => null,
'cascade' => array('remove', 'persist', 'refresh', 'merge', 'detach'),
'isCascadeDetach' => true,
'isCascadeMerge' => true,
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php
index 89865d2b4c..ace15b9cd1 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/XmlMappingDriverTest.php
@@ -28,4 +28,18 @@ public function testSetShardKeyOptionsByAttributes()
$this->assertSame(array('unique' => true, 'numInitialChunks' => 4096), $shardKey['options']);
$this->assertSame(array('_id' => 1), $shardKey['keys']);
}
-}
\ No newline at end of file
+
+ public function testGetAssociationCollectionClass()
+ {
+ $class = new ClassMetadataInfo('doc');
+ $driver = $this->_loadDriver();
+ $element = new \SimpleXmlElement('');
+
+ /** @uses XmlDriver::setShardKey */
+ $m = new \ReflectionMethod(get_class($driver), 'addReferenceMapping');
+ $m->setAccessible(true);
+ $m->invoke($driver, $class, $element, 'many');
+
+ $this->assertEquals('Doctrine\\ODM\\MongoDB\\Tests\\Mapping\\PhonenumberCollection', $class->getAssociationCollectionClass('phonenumbers'));
+ }
+}
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/YamlMappingDriverTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/YamlMappingDriverTest.php
index c351682e25..ab5e998034 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/YamlMappingDriverTest.php
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/YamlMappingDriverTest.php
@@ -31,12 +31,23 @@ public function testAlternateRelationshipMappingSyntaxShouldSetDefaults()
}
foreach (array('embeddedPhonenumber', 'otherPhonenumbers') as $embeddedField) {
- foreach (array('strategy', 'targetDocument') as $key) {
+ foreach (array('strategy', 'targetDocument', 'collectionClass') as $key) {
$this->assertArrayHasKey($key, $class->fieldMappings[$embeddedField]);
}
}
}
+ public function testGetAssociationCollectionClass()
+ {
+ $className = __NAMESPACE__.'\AbstractMappingDriverUser';
+ $mappingDriver = new YamlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'yaml');
+
+ $class = new ClassMetadata($className);
+ $mappingDriver->loadMetadataForClass($className, $class);
+ $this->assertEquals('Doctrine\ODM\MongoDB\Tests\Mapping\PhonenumberCollection', $class->getAssociationCollectionClass('phonenumbers'));
+ $this->assertEquals('Doctrine\ODM\MongoDB\Tests\Mapping\PhonenumberCollection', $class->getAssociationCollectionClass('otherPhonenumbers'));
+ }
+
public function testFieldLevelIndexSyntaxWithBooleanValues()
{
$className = __NAMESPACE__.'\AbstractMappingDriverAlternateUser';
@@ -70,3 +81,8 @@ class AbstractMappingDriverAlternateUser
public $embeddedPhonenumber;
public $otherPhonenumbers;
}
+
+class PhonenumberCollection extends \Doctrine\Common\Collections\ArrayCollection
+{
+
+}
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/xml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.xml b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/xml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.xml
index 679414acab..e3676e991c 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/xml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.xml
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/xml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.xml
@@ -41,7 +41,7 @@
-
+
@@ -61,7 +61,7 @@
-
+
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/yaml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.yml b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/yaml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.yml
index f0a0b80a4b..6df9f3211a 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/yaml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.yml
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/yaml/Doctrine.ODM.MongoDB.Tests.Mapping.AbstractMappingDriverUser.dcm.yml
@@ -67,6 +67,7 @@ Doctrine\ODM\MongoDB\Tests\Mapping\AbstractMappingDriverUser:
referenceMany:
phonenumbers:
targetDocument: Phonenumber
+ collectionClass: PhonenumberCollection
cascade: [ persist ]
discriminatorField: discr
discriminatorMap:
@@ -86,6 +87,7 @@ Doctrine\ODM\MongoDB\Tests\Mapping\AbstractMappingDriverUser:
embedMany:
otherPhonenumbers:
targetDocument: Phonenumber
+ collectionClass: PhonenumberCollection
discriminatorField: discr
discriminatorMap:
home: HomePhonenumber