From 30fdf8dd1b57c4fbb9b04368a63167024746efcb Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Wed, 14 Dec 2011 16:28:01 -0200 Subject: [PATCH 01/10] added support for @AssociationOverride --- .../ORM/Mapping/AssociationOverride.php | 56 +++++ .../ORM/Mapping/AssociationOverrides.php | 41 ++++ .../ORM/Mapping/Driver/AnnotationDriver.php | 103 ++++++---- .../Mapping/Driver/DoctrineAnnotations.php | 4 +- lib/Doctrine/ORM/Mapping/JoinTable.php | 2 +- .../Tests/Models/DDC964/DDC964Address.php | 123 +++++++++++ .../Tests/Models/DDC964/DDC964Admin.php | 27 +++ .../Tests/Models/DDC964/DDC964Group.php | 70 +++++++ .../Tests/Models/DDC964/DDC964Guest.php | 14 ++ .../Tests/Models/DDC964/DDC964User.php | 108 ++++++++++ .../ORM/Functional/Ticket/DDC964Test.php | 193 ++++++++++++++++++ 11 files changed, 704 insertions(+), 37 deletions(-) create mode 100644 lib/Doctrine/ORM/Mapping/AssociationOverride.php create mode 100644 lib/Doctrine/ORM/Mapping/AssociationOverrides.php create mode 100644 tests/Doctrine/Tests/Models/DDC964/DDC964Address.php create mode 100644 tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php create mode 100644 tests/Doctrine/Tests/Models/DDC964/DDC964Group.php create mode 100644 tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php create mode 100644 tests/Doctrine/Tests/Models/DDC964/DDC964User.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php diff --git a/lib/Doctrine/ORM/Mapping/AssociationOverride.php b/lib/Doctrine/ORM/Mapping/AssociationOverride.php new file mode 100644 index 000000000..cd149760b --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/AssociationOverride.php @@ -0,0 +1,56 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * This annotation is used to override association mapping of property for an entity relationship. + * + * @author Fabio B. Silva + * @since 2.2 + * + * @Annotation + * @Target({"PROPERTY","ANNOTATION"}) + */ +final class AssociationOverride implements Annotation +{ + + /** + * The name of the relationship property whose mapping is being overridden + * + * @var string + */ + public $name; + + /** + * The join column that is being mapped to the persistent attribute. + * + * @var array<\Doctrine\ORM\Mapping\JoinColumn> + */ + public $joinColumns; + + + /** + * The join table that maps the relationship. + * + * @var \Doctrine\ORM\Mapping\JoinTable + */ + public $joinTable; + +} diff --git a/lib/Doctrine/ORM/Mapping/AssociationOverrides.php b/lib/Doctrine/ORM/Mapping/AssociationOverrides.php new file mode 100644 index 000000000..6cc0d9a41 --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/AssociationOverrides.php @@ -0,0 +1,41 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * This annotation is used to override association mappings of relationship properties. + * + * @author Fabio B. Silva + * @since 2.2 + * + * @Annotation + * @Target("CLASS") + */ +final class AssociationOverrides implements Annotation +{ + + /** + * Mapping overrides of relationship properties + * + * @var array<\Doctrine\ORM\Mapping\AssociationOverride> + */ + public $value; + +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 6a89131fe..eae6083f8 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -23,7 +23,8 @@ use Doctrine\Common\Cache\ArrayCache, Doctrine\Common\Annotations\AnnotationReader, Doctrine\Common\Annotations\AnnotationRegistry, Doctrine\ORM\Mapping\ClassMetadataInfo, - Doctrine\ORM\Mapping\MappingException; + Doctrine\ORM\Mapping\MappingException, + Doctrine\ORM\Mapping\JoinColumn; /** * The AnnotationDriver reads the mapping metadata from docblock annotations. @@ -275,6 +276,43 @@ class AnnotationDriver implements Driver } } + $associationOverrides = array(); + // Evaluate AssociationOverrides annotation + if (isset($classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'])) { + $associationOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides']; + + foreach ($associationOverridesAnnot->value as $associationOverride) { + // Check for JoinColummn/JoinColumns annotations + if ($associationOverride->joinColumns) { + $joinColumns = array(); + foreach ($associationOverride->joinColumns as $joinColumn) { + $joinColumns[] = $this->joinColumnToArray($joinColumn); + } + $associationOverrides[$associationOverride->name]['joinColumns'] = $joinColumns; + } + + // Check for JoinTable annotations + if ($associationOverride->joinTable) { + $joinTable = null; + $joinTableAnnot = $associationOverride->joinTable; + $joinTable = array( + 'name' => $joinTableAnnot->name, + 'schema' => $joinTableAnnot->schema + ); + + foreach ($joinTableAnnot->joinColumns as $joinColumn) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + $associationOverrides[$associationOverride->name]['joinTable'] = $joinTable; + } + } + } + // Evaluate InheritanceType annotation if (isset($classAnnotations['Doctrine\ORM\Mapping\InheritanceType'])) { $inheritanceTypeAnnot = $classAnnotations['Doctrine\ORM\Mapping\InheritanceType']; @@ -325,25 +363,13 @@ class AnnotationDriver implements Driver // Check for JoinColummn/JoinColumns annotations $joinColumns = array(); - if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) { - $joinColumns[] = array( - 'name' => $joinColumnAnnot->name, - 'referencedColumnName' => $joinColumnAnnot->referencedColumnName, - 'unique' => $joinColumnAnnot->unique, - 'nullable' => $joinColumnAnnot->nullable, - 'onDelete' => $joinColumnAnnot->onDelete, - 'columnDefinition' => $joinColumnAnnot->columnDefinition, - ); + if (isset($associationOverrides[$property->name]['joinColumns'])) { + $joinColumns = $associationOverrides[$property->name]['joinColumns']; + } else if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) { + $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot); } else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) { foreach ($joinColumnsAnnot->value as $joinColumn) { - $joinColumns[] = array( - 'name' => $joinColumn->name, - 'referencedColumnName' => $joinColumn->referencedColumnName, - 'unique' => $joinColumn->unique, - 'nullable' => $joinColumn->nullable, - 'onDelete' => $joinColumn->onDelete, - 'columnDefinition' => $joinColumn->columnDefinition, - ); + $joinColumns[] = $this->joinColumnToArray($joinColumn); } } @@ -440,32 +466,20 @@ class AnnotationDriver implements Driver } else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) { $joinTable = array(); - if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) { + if (isset($associationOverrides[$property->name]['joinTable'])) { + $joinTable = $associationOverrides[$property->name]['joinTable']; + } else if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) { $joinTable = array( 'name' => $joinTableAnnot->name, 'schema' => $joinTableAnnot->schema ); foreach ($joinTableAnnot->joinColumns as $joinColumn) { - $joinTable['joinColumns'][] = array( - 'name' => $joinColumn->name, - 'referencedColumnName' => $joinColumn->referencedColumnName, - 'unique' => $joinColumn->unique, - 'nullable' => $joinColumn->nullable, - 'onDelete' => $joinColumn->onDelete, - 'columnDefinition' => $joinColumn->columnDefinition, - ); + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); } foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { - $joinTable['inverseJoinColumns'][] = array( - 'name' => $joinColumn->name, - 'referencedColumnName' => $joinColumn->referencedColumnName, - 'unique' => $joinColumn->unique, - 'nullable' => $joinColumn->nullable, - 'onDelete' => $joinColumn->onDelete, - 'columnDefinition' => $joinColumn->columnDefinition, - ); + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); } } @@ -635,6 +649,25 @@ class AnnotationDriver implements Driver return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode); } + + /** + * Parse the given JoinColumn as array + * + * @param JoinColumn $joinColumn + * @return array + */ + private function joinColumnToArray(JoinColumn $joinColumn) + { + return array( + 'name' => $joinColumn->name, + 'unique' => $joinColumn->unique, + 'nullable' => $joinColumn->nullable, + 'onDelete' => $joinColumn->onDelete, + 'columnDefinition' => $joinColumn->columnDefinition, + 'referencedColumnName' => $joinColumn->referencedColumnName, + ); + } + /** * Factory method for the Annotation Driver * diff --git a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php index 46fa1551b..cb911e522 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php +++ b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php @@ -59,4 +59,6 @@ require_once __DIR__.'/../EntityResult.php'; require_once __DIR__.'/../NamedNativeQuery.php'; require_once __DIR__.'/../NamedNativeQueries.php'; require_once __DIR__.'/../SqlResultSetMapping.php'; -require_once __DIR__.'/../SqlResultSetMappings.php'; \ No newline at end of file +require_once __DIR__.'/../SqlResultSetMappings.php'; +require_once __DIR__.'/../AssociationOverride.php'; +require_once __DIR__.'/../AssociationOverrides.php'; \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/JoinTable.php b/lib/Doctrine/ORM/Mapping/JoinTable.php index 9ff9d4511..31625ed8f 100644 --- a/lib/Doctrine/ORM/Mapping/JoinTable.php +++ b/lib/Doctrine/ORM/Mapping/JoinTable.php @@ -21,7 +21,7 @@ namespace Doctrine\ORM\Mapping; /** * @Annotation - * @Target("PROPERTY") + * @Target({"PROPERTY","ANNOTATION"}) */ final class JoinTable implements Annotation { diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964Address.php b/tests/Doctrine/Tests/Models/DDC964/DDC964Address.php new file mode 100644 index 000000000..f5edaf857 --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964Address.php @@ -0,0 +1,123 @@ +zip = $zip; + $this->country = $country; + $this->city = $city; + $this->street = $street; + } + + /** + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * @return string + */ + public function getCountry() + { + return $this->country; + } + + /** + * @param string $country + */ + public function setCountry($country) + { + $this->country = $country; + } + + /** + * @return string + */ + public function getZip() + { + return $this->zip; + } + + /** + * @param string $zip + */ + public function setZip($zip) + { + $this->zip = $zip; + } + + /** + * @return string + */ + public function getCity() + { + return $this->city; + } + + /** + * @param string $city + */ + public function setCity($city) + { + $this->city = $city; + } + + /** + * @return string + */ + public function getStreet() + { + return $this->street; + } + + /** + * @param string $street + */ + public function setStreet($street) + { + $this->street = $street; + } + +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php b/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php new file mode 100644 index 000000000..509297cd9 --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php @@ -0,0 +1,27 @@ +name = $name; + $this->users = new ArrayCollection(); + } + + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param DDC964User $user + */ + public function addUser(DDC964User $user) + { + $this->users[] = $user; + } + + /** + * @return ArrayCollection + */ + public function getUsers() + { + return $this->users; + } + +} + diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php b/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php new file mode 100644 index 000000000..8cd2c6446 --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php @@ -0,0 +1,14 @@ +name = $name; + $this->groups = new ArrayCollection; + } + + /** + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @param DDC964Group $group + */ + public function addGroup(DDC964Group $group) + { + $this->groups->add($group); + $group->addUser($this); + } + + /** + * @return ArrayCollection + */ + public function getGroups() + { + return $this->groups; + } + + /** + * @return DDC964Address + */ + public function getAddress() + { + return $this->address; + } + + /** + * @param DDC964Address $address + */ + public function setAddress(DDC964Address $address) + { + $this->address = $address; + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php new file mode 100644 index 000000000..b250d97f7 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php @@ -0,0 +1,193 @@ +_em->getClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Admin'); + $guestMetadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Guest'); + + + // assert groups association mappings + $this->assertArrayHasKey('groups', $guestMetadata->associationMappings); + $this->assertArrayHasKey('groups', $adminMetadata->associationMappings); + + $guestGroups = $guestMetadata->associationMappings['groups']; + $adminGroups = $adminMetadata->associationMappings['groups']; + + $this->assertEquals('ddc964_users_groups', $guestGroups['joinTable']['name']); + $this->assertEquals('user_id', $guestGroups['joinTable']['joinColumns'][0]['name']); + $this->assertEquals('group_id', $guestGroups['joinTable']['inverseJoinColumns'][0]['name']); + + $this->assertEquals(array('user_id'=>'id'), $guestGroups['relationToSourceKeyColumns']); + $this->assertEquals(array('group_id'=>'id'), $guestGroups['relationToTargetKeyColumns']); + $this->assertEquals(array('user_id','group_id'), $guestGroups['joinTableColumns']); + + + $this->assertEquals('ddc964_users_admingroups', $adminGroups['joinTable']['name']); + $this->assertEquals('adminuser_id', $adminGroups['joinTable']['joinColumns'][0]['name']); + $this->assertEquals('admingroup_id', $adminGroups['joinTable']['inverseJoinColumns'][0]['name']); + + $this->assertEquals(array('adminuser_id'=>'id'), $adminGroups['relationToSourceKeyColumns']); + $this->assertEquals(array('admingroup_id'=>'id'), $adminGroups['relationToTargetKeyColumns']); + $this->assertEquals(array('adminuser_id','admingroup_id'), $adminGroups['joinTableColumns']); + + + // assert address association mappings + $this->assertArrayHasKey('address', $guestMetadata->associationMappings); + $this->assertArrayHasKey('address', $adminMetadata->associationMappings); + + $guestAddress = $guestMetadata->associationMappings['address']; + $adminAddress = $adminMetadata->associationMappings['address']; + + $this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']); + $this->assertEquals(array('address_id'=>'id'), $guestAddress['sourceToTargetKeyColumns']); + $this->assertEquals(array('address_id'=>'address_id'), $guestAddress['joinColumnFieldNames']); + $this->assertEquals(array('id'=>'address_id'), $guestAddress['targetToSourceKeyColumns']); + + + $this->assertEquals('adminaddress_id', $adminAddress['joinColumns'][0]['name']); + $this->assertEquals(array('adminaddress_id'=>'id'), $adminAddress['sourceToTargetKeyColumns']); + $this->assertEquals(array('adminaddress_id'=>'adminaddress_id'), $adminAddress['joinColumnFieldNames']); + $this->assertEquals(array('id'=>'adminaddress_id'), $adminAddress['targetToSourceKeyColumns']); + } + + public function testShouldCreateAndRetrieveOverriddenAssociation() + { + list($admin1,$admin2, $guest1,$guest2) = $this->loadFixtures(); + + $this->_em->clear(); + + $this->assertNotNull($admin1->getId()); + $this->assertNotNull($admin2->getId()); + + $this->assertNotNull($guest1->getId()); + $this->assertNotNull($guest1->getId()); + + + $adminCount = $this->_em + ->createQuery('SELECT COUNT(a) FROM ' . self::NS . '\DDC964Admin a') + ->getSingleScalarResult(); + + $guestCount = $this->_em + ->createQuery('SELECT COUNT(g) FROM ' . self::NS . '\DDC964Guest g') + ->getSingleScalarResult(); + + + $this->assertEquals(2, $adminCount); + $this->assertEquals(2, $guestCount); + + + $admin1 = $this->_em->find(self::NS . '\DDC964Admin', $admin1->getId()); + $admin2 = $this->_em->find(self::NS . '\DDC964Admin', $admin2->getId()); + + $guest1 = $this->_em->find(self::NS . '\DDC964Guest', $guest1->getId()); + $guest2 = $this->_em->find(self::NS . '\DDC964Guest', $guest2->getId()); + + + $this->assertUser($admin1, self::NS . '\DDC964Admin', '11111-111', 2); + $this->assertUser($admin2, self::NS . '\DDC964Admin', '22222-222', 2); + + $this->assertUser($guest1, self::NS . '\DDC964Guest', '33333-333', 2); + $this->assertUser($guest2, self::NS . '\DDC964Guest', '44444-444', 1); + } + + + /** + * @param DDC964User $user + * @param string $addressZip + * @param integer $groups + */ + private function assertUser(DDC964User $user, $className, $addressZip, $groups) + { + $this->assertInstanceOf($className, $user); + $this->assertInstanceOf(self::NS . '\DDC964User', $user); + $this->assertInstanceOf(self::NS . '\DDC964Address', $user->getAddress()); + $this->assertEquals($addressZip, $user->getAddress()->getZip()); + $this->assertEquals($groups, $user->getGroups()->count()); + } + + private function createSchemaDDC964() + { + try { + + $this->_schemaTool->createSchema(array( + $this->_em->getClassMetadata(self::NS . '\DDC964Address'), + $this->_em->getClassMetadata(self::NS . '\DDC964Group'), + $this->_em->getClassMetadata(self::NS . '\DDC964Guest'), + $this->_em->getClassMetadata(self::NS . '\DDC964Admin'), + )); + } catch (\Exception $exc) { + + } + } + + /** + * @return array + */ + private function loadFixtures() + { + $this->createSchemaDDC964(); + + $group1 = new DDC964Group('Foo Admin Group'); + $group2 = new DDC964Group('Bar Admin Group'); + $group3 = new DDC964Group('Foo Guest Group'); + $group4 = new DDC964Group('Bar Guest Group'); + + $this->_em->persist($group1); + $this->_em->persist($group2); + $this->_em->persist($group3); + $this->_em->persist($group4); + + $this->_em->flush(); + + + $admin1 = new DDC964Admin('Admin 1'); + $admin2 = new DDC964Admin('Admin 2'); + $guest1 = new DDC964Guest('Guest 1'); + $guest2 = new DDC964Guest('Guest 2'); + + + $admin1->setAddress(new DDC964Address('11111-111', 'Some Country', 'Some City', 'Some Street')); + $admin2->setAddress(new DDC964Address('22222-222', 'Some Country', 'Some City', 'Some Street')); + $guest1->setAddress(new DDC964Address('33333-333', 'Some Country', 'Some City', 'Some Street')); + $guest2->setAddress(new DDC964Address('44444-444', 'Some Country', 'Some City', 'Some Street')); + + + $admin1->addGroup($group1); + $admin1->addGroup($group2); + $admin2->addGroup($group1); + $admin2->addGroup($group2); + + $guest1->addGroup($group3); + $guest1->addGroup($group4); + $guest2->addGroup($group2); + + $this->_em->persist($admin1); + $this->_em->persist($admin2); + $this->_em->persist($guest1); + $this->_em->persist($guest2); + + $this->_em->flush(); + + return array($admin1,$admin2, $guest1,$guest2); + } + +} \ No newline at end of file From 9e010cbd34276c03e6aa33162f4de925a383fcaf Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Thu, 2 Feb 2012 00:57:39 -0200 Subject: [PATCH 02/10] added xml/yml drivers --- .../ORM/Mapping/ClassMetadataInfo.php | 48 +++++ .../ORM/Mapping/Driver/AnnotationDriver.php | 51 ++++- lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php | 58 +++++- .../ORM/Mapping/Driver/YamlDriver.php | 67 +++++- lib/Doctrine/ORM/Mapping/MappingException.php | 11 + .../Tests/Models/DDC964/DDC964Admin.php | 20 ++ .../Tests/Models/DDC964/DDC964Guest.php | 4 +- .../Tests/Models/DDC964/DDC964User.php | 41 ++++ .../ORM/Functional/Ticket/DDC964Test.php | 193 ------------------ .../ORM/Mapping/AbstractMappingDriverTest.php | 92 ++++++++- .../Tests/ORM/Mapping/ClassMetadataTest.php | 14 ++ ...ctrine.Tests.Models.DDC964.DDC964Admin.php | 21 ++ ...ctrine.Tests.Models.DDC964.DDC964Guest.php | 1 + ...octrine.Tests.Models.DDC964.DDC964User.php | 41 ++++ ...ne.Tests.Models.DDC964.DDC964Admin.dcm.xml | 27 +++ ...ne.Tests.Models.DDC964.DDC964Guest.dcm.xml | 10 + ...ine.Tests.Models.DDC964.DDC964User.dcm.xml | 39 ++++ ...ne.Tests.Models.DDC964.DDC964Admin.dcm.yml | 17 ++ ...ne.Tests.Models.DDC964.DDC964Guest.dcm.yml | 2 + ...ine.Tests.Models.DDC964.DDC964User.dcm.yml | 30 +++ 20 files changed, 566 insertions(+), 221 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Admin.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964User.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.xml create mode 100644 tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml create mode 100644 tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml create mode 100644 tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.yml create mode 100644 tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml create mode 100644 tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 1f3b00dbf..d42c4e9f5 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -477,6 +477,11 @@ class ClassMetadataInfo implements ClassMetadata */ public $associationMappings = array(); + /** + * @var array + */ + public $overrideAssociationMappings = array(); + /** * READ-ONLY: Flag indicating whether the identifier/primary key of the class is composite. * @@ -1802,6 +1807,49 @@ class ClassMetadataInfo implements ClassMetadata $this->inheritanceType = $type; } + /** + * @param string $fieldName + */ + public function setAssociationOverride($fieldName, $overrideMapping) + { + if (!isset($this->associationMappings[$fieldName])) { + throw MappingException::invalidOverrideFieldName($this->name, $fieldName); + } + + $mapping = $this->associationMappings[$fieldName]; + + if (isset($overrideMapping['joinColumns'])) { + $mapping['joinColumns'] = $overrideMapping['joinColumns']; + } + + if (isset($overrideMapping['joinTable'])) { + $mapping['joinTable'] = $overrideMapping['joinTable']; + } + + $mapping['joinColumnFieldNames'] = null; + $mapping['joinTableColumns'] = null; + $mapping['sourceToTargetKeyColumns'] = null; + $mapping['relationToSourceKeyColumns'] = null; + $mapping['relationToTargetKeyColumns'] = null; + + switch ($mapping['type']) { + case self::ONE_TO_ONE: + $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); + break; + case self::ONE_TO_MANY: + $mapping = $this->_validateAndCompleteOneToManyMapping($mapping); + break; + case self::MANY_TO_ONE: + $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); + break; + case self::MANY_TO_MANY: + $mapping = $this->_validateAndCompleteManyToManyMapping($mapping); + break; + } + + $this->associationMappings[$fieldName] = $mapping; + } + /** * Checks whether a mapped field is inherited from an entity superclass. * diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index eae6083f8..053342cf8 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -363,9 +363,7 @@ class AnnotationDriver implements Driver // Check for JoinColummn/JoinColumns annotations $joinColumns = array(); - if (isset($associationOverrides[$property->name]['joinColumns'])) { - $joinColumns = $associationOverrides[$property->name]['joinColumns']; - } else if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) { + if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) { $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot); } else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) { foreach ($joinColumnsAnnot->value as $joinColumn) { @@ -466,9 +464,7 @@ class AnnotationDriver implements Driver } else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) { $joinTable = array(); - if (isset($associationOverrides[$property->name]['joinTable'])) { - $joinTable = $associationOverrides[$property->name]['joinTable']; - } else if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) { + if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) { $joinTable = array( 'name' => $joinTableAnnot->name, 'schema' => $joinTableAnnot->schema @@ -500,6 +496,47 @@ class AnnotationDriver implements Driver } } + // Evaluate AssociationOverrides annotation + if (isset($classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'])) { + $associationOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides']; + + foreach ($associationOverridesAnnot->value as $associationOverride) { + $override = array(); + $fieldName = $associationOverride->name; + + // Check for JoinColummn/JoinColumns annotations + if ($associationOverride->joinColumns) { + $joinColumns = array(); + foreach ($associationOverride->joinColumns as $joinColumn) { + $joinColumns[] = $this->joinColumnToArray($joinColumn); + } + $override['joinColumns'] = $joinColumns; + } + + // Check for JoinTable annotations + if ($associationOverride->joinTable) { + $joinTable = null; + $joinTableAnnot = $associationOverride->joinTable; + $joinTable = array( + 'name' => $joinTableAnnot->name, + 'schema' => $joinTableAnnot->schema + ); + + foreach ($joinTableAnnot->joinColumns as $joinColumn) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + $override['joinTable'] = $joinTable; + } + + $metadata->setAssociationOverride($fieldName, $override); + } + } + // Evaluate @HasLifecycleCallbacks annotation if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) { foreach ($class->getMethods() as $method) { @@ -667,7 +704,7 @@ class AnnotationDriver implements Driver 'referencedColumnName' => $joinColumn->referencedColumnName, ); } - + /** * Factory method for the Annotation Driver * diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php index 005dc44d1..12c50e4a3 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php @@ -353,10 +353,10 @@ class XmlDriver extends AbstractFileDriver $joinColumns = array(); if (isset($oneToOneElement->{'join-column'})) { - $joinColumns[] = $this->_getJoinColumnMapping($oneToOneElement->{'join-column'}); + $joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'}); } else if (isset($oneToOneElement->{'join-columns'})) { foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement); + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); } } @@ -437,10 +437,10 @@ class XmlDriver extends AbstractFileDriver $joinColumns = array(); if (isset($manyToOneElement->{'join-column'})) { - $joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement->{'join-column'}); + $joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'}); } else if (isset($manyToOneElement->{'join-columns'})) { foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement); + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); } } @@ -487,11 +487,11 @@ class XmlDriver extends AbstractFileDriver } foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinTable['joinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement); + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); } foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) { - $joinTable['inverseJoinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement); + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); } $mapping['joinTable'] = $joinTable; @@ -519,6 +519,50 @@ class XmlDriver extends AbstractFileDriver } } + // Evaluate association-overrides + if (isset($xmlRoot->{'association-overrides'})) { + foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $associationOverrideElement) { + $fieldName = (string) $associationOverrideElement['name']; + $override = array(); + + // Check for join-columns + if (isset($associationOverrideElement->{'join-columns'})) { + $joinColumns = array(); + foreach ($associationOverrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + $override['joinColumns'] = $joinColumns; + } + + // Check for join-table + if ($associationOverrideElement->{'join-table'}) { + $joinTable = null; + $joinTableElement = $associationOverrideElement->{'join-table'}; + + $joinTable = array( + 'name' => (string) $joinTableElement['name'], + 'schema' => (string) $joinTableElement['schema'] + ); + + if (isset($joinTableElement->{'join-columns'})) { + foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + } + + if (isset($joinTableElement->{'inverse-join-columns'})) { + foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + } + + $override['joinTable'] = $joinTable; + } + + $metadata->setAssociationOverride($fieldName, $override); + } + } + // Evaluate if (isset($xmlRoot->{'lifecycle-callbacks'})) { foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) { @@ -563,7 +607,7 @@ class XmlDriver extends AbstractFileDriver * @param $joinColumnElement The XML element. * @return array The mapping array. */ - private function _getJoinColumnMapping(SimpleXMLElement $joinColumnElement) + private function joinColumnToArray(SimpleXMLElement $joinColumnElement) { $joinColumn = array( 'name' => (string)$joinColumnElement['name'], diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index d602ed975..97b219f6a 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -356,14 +356,14 @@ class YamlDriver extends AbstractFileDriver $joinColumns = array(); if (isset($oneToOneElement['joinColumn'])) { - $joinColumns[] = $this->_getJoinColumnMapping($oneToOneElement['joinColumn']); + $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']); } else if (isset($oneToOneElement['joinColumns'])) { foreach ($oneToOneElement['joinColumns'] as $name => $joinColumnElement) { if (!isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } - $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement); + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); } } @@ -438,14 +438,14 @@ class YamlDriver extends AbstractFileDriver $joinColumns = array(); if (isset($manyToOneElement['joinColumn'])) { - $joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement['joinColumn']); + $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']); } else if (isset($manyToOneElement['joinColumns'])) { foreach ($manyToOneElement['joinColumns'] as $name => $joinColumnElement) { if (!isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } - $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement); + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); } } @@ -489,7 +489,7 @@ class YamlDriver extends AbstractFileDriver $joinColumnElement['name'] = $name; } - $joinTable['joinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement); + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); } foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { @@ -497,7 +497,7 @@ class YamlDriver extends AbstractFileDriver $joinColumnElement['name'] = $name; } - $joinTable['inverseJoinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement); + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); } $mapping['joinTable'] = $joinTable; @@ -527,6 +527,59 @@ class YamlDriver extends AbstractFileDriver } } + // Evaluate association-overrides + if (isset($element['associationOverride'])) { + + foreach ($element['associationOverride'] as $fieldName => $associationOverride) { + $override = array(); + + // Check for join-columns + if (isset($associationOverride['joinColumn'])) { + $joinColumns = array(); + foreach ($associationOverride['joinColumn'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + $override['joinColumns'] = $joinColumns; + } + + // Check for join-table + if (isset($associationOverride['joinTable'])) { + + $joinTableElement = $associationOverride['joinTable']; + $joinTable = array( + 'name' => $joinTableElement['name'] + ); + + if (isset($joinTableElement['schema'])) { + $joinTable['schema'] = $joinTableElement['schema']; + } + + foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + + foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + + $override['joinTable'] = $joinTable; + } + + $metadata->setAssociationOverride($fieldName, $override); + } + } + // Evaluate lifeCycleCallbacks if (isset($element['lifecycleCallbacks'])) { foreach ($element['lifecycleCallbacks'] as $type => $methods) { @@ -544,7 +597,7 @@ class YamlDriver extends AbstractFileDriver * @param $joinColumnElement The array join column element * @return array The mapping array. */ - private function _getJoinColumnMapping($joinColumnElement) + private function joinColumnToArray($joinColumnElement) { $joinColumn = array(); if (isset($joinColumnElement['referencedColumnName'])) { diff --git a/lib/Doctrine/ORM/Mapping/MappingException.php b/lib/Doctrine/ORM/Mapping/MappingException.php index 5c3ed8ef2..f88109f0c 100644 --- a/lib/Doctrine/ORM/Mapping/MappingException.php +++ b/lib/Doctrine/ORM/Mapping/MappingException.php @@ -83,6 +83,17 @@ class MappingException extends \Doctrine\ORM\ORMException return new self("Invalid mapping file '$fileName' for class '$entityName'."); } + /** + * Exception for invalid property name override. + * + * @param string $className The entity's name + * @param string $fieldName + */ + public static function invalidOverrideFieldName($className, $fieldName) + { + return new self("Invalid field override named '$fieldName' for class '$className'."); + } + public static function mappingNotFound($className, $fieldName) { return new self("No mapping found for field '$fieldName' on class '$className'."); diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php b/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php index 509297cd9..e22b973de 100644 --- a/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964Admin.php @@ -23,5 +23,25 @@ use Doctrine\Common\Collections\ArrayCollection; */ class DDC964Admin extends DDC964User { + public static function loadMetadata($metadata) + { + $metadata->setAssociationOverride('address',array( + 'joinColumns'=>array(array( + 'name' => 'adminaddress_id', + 'referencedColumnName' => 'id', + )) + )); + $metadata->setAssociationOverride('groups',array( + 'joinTable' => array( + 'name' => 'ddc964_users_admingroups', + 'joinColumns' => array(array( + 'name' => 'adminuser_id', + )), + 'inverseJoinColumns' =>array (array ( + 'name' => 'admingroup_id', + )) + ) + )); + } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php b/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php index 8cd2c6446..71654a12b 100644 --- a/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php @@ -9,6 +9,8 @@ use Doctrine\Common\Collections\ArrayCollection; */ class DDC964Guest extends DDC964User { + public static function loadMetadata($metadata) + { - + } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964User.php b/tests/Doctrine/Tests/Models/DDC964/DDC964User.php index e3657359b..07947e57f 100644 --- a/tests/Doctrine/Tests/Models/DDC964/DDC964User.php +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964User.php @@ -105,4 +105,45 @@ class DDC964User { $this->address = $address; } + + public static function loadMetadata($metadata) + { + $metadata->mapField(array( + 'id' => true, + 'fieldName' => 'id', + 'type' => 'integer', + 'columnName' => 'id', + )); + $metadata->mapField(array( + 'fieldName' => 'name', + 'type' => 'string', + )); + + $metadata->mapManyToOne(array( + 'fieldName' => 'address', + 'targetEntity' => 'DDC964Address', + 'cascade' => array('persist','merge'), + 'joinColumn' => array('name'=>'address_id', 'referencedColumnMame'=>'id'), + )); + + $metadata->mapManyToMany(array( + 'fieldName' => 'groups', + 'targetEntity' => 'DDC964Group', + 'inversedBy' => 'users', + 'cascade' => array('persist','merge','detach'), + 'joinTable' => array( + 'name' => 'ddc964_users_groups', + 'joinColumns' => array(array( + 'name'=>'user_id', + 'referencedColumnName'=>'id', + )), + 'inverseJoinColumns'=>array(array( + 'name'=>'group_id', + 'referencedColumnName'=>'id', + )) + ) + )); + + $metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadataInfo::GENERATOR_TYPE_AUTO); + } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php deleted file mode 100644 index b250d97f7..000000000 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC964Test.php +++ /dev/null @@ -1,193 +0,0 @@ -_em->getClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Admin'); - $guestMetadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Guest'); - - - // assert groups association mappings - $this->assertArrayHasKey('groups', $guestMetadata->associationMappings); - $this->assertArrayHasKey('groups', $adminMetadata->associationMappings); - - $guestGroups = $guestMetadata->associationMappings['groups']; - $adminGroups = $adminMetadata->associationMappings['groups']; - - $this->assertEquals('ddc964_users_groups', $guestGroups['joinTable']['name']); - $this->assertEquals('user_id', $guestGroups['joinTable']['joinColumns'][0]['name']); - $this->assertEquals('group_id', $guestGroups['joinTable']['inverseJoinColumns'][0]['name']); - - $this->assertEquals(array('user_id'=>'id'), $guestGroups['relationToSourceKeyColumns']); - $this->assertEquals(array('group_id'=>'id'), $guestGroups['relationToTargetKeyColumns']); - $this->assertEquals(array('user_id','group_id'), $guestGroups['joinTableColumns']); - - - $this->assertEquals('ddc964_users_admingroups', $adminGroups['joinTable']['name']); - $this->assertEquals('adminuser_id', $adminGroups['joinTable']['joinColumns'][0]['name']); - $this->assertEquals('admingroup_id', $adminGroups['joinTable']['inverseJoinColumns'][0]['name']); - - $this->assertEquals(array('adminuser_id'=>'id'), $adminGroups['relationToSourceKeyColumns']); - $this->assertEquals(array('admingroup_id'=>'id'), $adminGroups['relationToTargetKeyColumns']); - $this->assertEquals(array('adminuser_id','admingroup_id'), $adminGroups['joinTableColumns']); - - - // assert address association mappings - $this->assertArrayHasKey('address', $guestMetadata->associationMappings); - $this->assertArrayHasKey('address', $adminMetadata->associationMappings); - - $guestAddress = $guestMetadata->associationMappings['address']; - $adminAddress = $adminMetadata->associationMappings['address']; - - $this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']); - $this->assertEquals(array('address_id'=>'id'), $guestAddress['sourceToTargetKeyColumns']); - $this->assertEquals(array('address_id'=>'address_id'), $guestAddress['joinColumnFieldNames']); - $this->assertEquals(array('id'=>'address_id'), $guestAddress['targetToSourceKeyColumns']); - - - $this->assertEquals('adminaddress_id', $adminAddress['joinColumns'][0]['name']); - $this->assertEquals(array('adminaddress_id'=>'id'), $adminAddress['sourceToTargetKeyColumns']); - $this->assertEquals(array('adminaddress_id'=>'adminaddress_id'), $adminAddress['joinColumnFieldNames']); - $this->assertEquals(array('id'=>'adminaddress_id'), $adminAddress['targetToSourceKeyColumns']); - } - - public function testShouldCreateAndRetrieveOverriddenAssociation() - { - list($admin1,$admin2, $guest1,$guest2) = $this->loadFixtures(); - - $this->_em->clear(); - - $this->assertNotNull($admin1->getId()); - $this->assertNotNull($admin2->getId()); - - $this->assertNotNull($guest1->getId()); - $this->assertNotNull($guest1->getId()); - - - $adminCount = $this->_em - ->createQuery('SELECT COUNT(a) FROM ' . self::NS . '\DDC964Admin a') - ->getSingleScalarResult(); - - $guestCount = $this->_em - ->createQuery('SELECT COUNT(g) FROM ' . self::NS . '\DDC964Guest g') - ->getSingleScalarResult(); - - - $this->assertEquals(2, $adminCount); - $this->assertEquals(2, $guestCount); - - - $admin1 = $this->_em->find(self::NS . '\DDC964Admin', $admin1->getId()); - $admin2 = $this->_em->find(self::NS . '\DDC964Admin', $admin2->getId()); - - $guest1 = $this->_em->find(self::NS . '\DDC964Guest', $guest1->getId()); - $guest2 = $this->_em->find(self::NS . '\DDC964Guest', $guest2->getId()); - - - $this->assertUser($admin1, self::NS . '\DDC964Admin', '11111-111', 2); - $this->assertUser($admin2, self::NS . '\DDC964Admin', '22222-222', 2); - - $this->assertUser($guest1, self::NS . '\DDC964Guest', '33333-333', 2); - $this->assertUser($guest2, self::NS . '\DDC964Guest', '44444-444', 1); - } - - - /** - * @param DDC964User $user - * @param string $addressZip - * @param integer $groups - */ - private function assertUser(DDC964User $user, $className, $addressZip, $groups) - { - $this->assertInstanceOf($className, $user); - $this->assertInstanceOf(self::NS . '\DDC964User', $user); - $this->assertInstanceOf(self::NS . '\DDC964Address', $user->getAddress()); - $this->assertEquals($addressZip, $user->getAddress()->getZip()); - $this->assertEquals($groups, $user->getGroups()->count()); - } - - private function createSchemaDDC964() - { - try { - - $this->_schemaTool->createSchema(array( - $this->_em->getClassMetadata(self::NS . '\DDC964Address'), - $this->_em->getClassMetadata(self::NS . '\DDC964Group'), - $this->_em->getClassMetadata(self::NS . '\DDC964Guest'), - $this->_em->getClassMetadata(self::NS . '\DDC964Admin'), - )); - } catch (\Exception $exc) { - - } - } - - /** - * @return array - */ - private function loadFixtures() - { - $this->createSchemaDDC964(); - - $group1 = new DDC964Group('Foo Admin Group'); - $group2 = new DDC964Group('Bar Admin Group'); - $group3 = new DDC964Group('Foo Guest Group'); - $group4 = new DDC964Group('Bar Guest Group'); - - $this->_em->persist($group1); - $this->_em->persist($group2); - $this->_em->persist($group3); - $this->_em->persist($group4); - - $this->_em->flush(); - - - $admin1 = new DDC964Admin('Admin 1'); - $admin2 = new DDC964Admin('Admin 2'); - $guest1 = new DDC964Guest('Guest 1'); - $guest2 = new DDC964Guest('Guest 2'); - - - $admin1->setAddress(new DDC964Address('11111-111', 'Some Country', 'Some City', 'Some Street')); - $admin2->setAddress(new DDC964Address('22222-222', 'Some Country', 'Some City', 'Some Street')); - $guest1->setAddress(new DDC964Address('33333-333', 'Some Country', 'Some City', 'Some Street')); - $guest2->setAddress(new DDC964Address('44444-444', 'Some Country', 'Some City', 'Some Street')); - - - $admin1->addGroup($group1); - $admin1->addGroup($group2); - $admin2->addGroup($group1); - $admin2->addGroup($group2); - - $guest1->addGroup($group3); - $guest1->addGroup($group4); - $guest2->addGroup($group2); - - $this->_em->persist($admin1); - $this->_em->persist($admin2); - $this->_em->persist($guest1); - $this->_em->persist($guest2); - - $this->_em->flush(); - - return array($admin1,$admin2, $guest1,$guest2); - } - -} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php index 0efb3aca2..9e1cbde2d 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php @@ -376,11 +376,8 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase */ public function testDefaultFieldType() { - $em = $this->_getTestEntityManager(); - $factory = $this->createClassMetadataFactory($em); - - - $class = $factory->getMetadataFor('Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType'); + $factory = $this->createClassMetadataFactory(); + $class = $factory->getMetadataFor('Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType'); $this->assertArrayHasKey('id', $class->fieldMappings); @@ -417,7 +414,6 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase */ public function testIdentifierColumnDefinition() { - $class = $this->createClassMetadata(__NAMESPACE__ . '\DDC1170Entity'); @@ -491,6 +487,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase } /** +<<<<<<< HEAD * @group DDC-1663 */ public function testNamedNativeQuery() @@ -613,6 +610,89 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase $this->assertEquals(array('name'=>'name','column'=>'name'), $mapping['entities'][0]['fields'][1]); $this->assertEquals($personMetadata->name, $mapping['entities'][0]['entityClass']); } + + /* + * @group DDC-964 + */ + public function testAssociationOverridesMapping() + { + + $factory = $this->createClassMetadataFactory(); + $adminMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Admin'); + $guestMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Guest'); + + + // assert groups association mappings + $this->assertArrayHasKey('groups', $guestMetadata->associationMappings); + $this->assertArrayHasKey('groups', $adminMetadata->associationMappings); + + $guestGroups = $guestMetadata->associationMappings['groups']; + $adminGroups = $adminMetadata->associationMappings['groups']; + + // assert not override attributes + $this->assertEquals($guestGroups['fieldName'], $adminGroups['fieldName']); + $this->assertEquals($guestGroups['type'], $adminGroups['type']); + $this->assertEquals($guestGroups['mappedBy'], $adminGroups['mappedBy']); + $this->assertEquals($guestGroups['inversedBy'], $adminGroups['inversedBy']); + $this->assertEquals($guestGroups['isOwningSide'], $adminGroups['isOwningSide']); + $this->assertEquals($guestGroups['fetch'], $adminGroups['fetch']); + $this->assertEquals($guestGroups['isCascadeRemove'], $adminGroups['isCascadeRemove']); + $this->assertEquals($guestGroups['isCascadePersist'], $adminGroups['isCascadePersist']); + $this->assertEquals($guestGroups['isCascadeRefresh'], $adminGroups['isCascadeRefresh']); + $this->assertEquals($guestGroups['isCascadeMerge'], $adminGroups['isCascadeMerge']); + $this->assertEquals($guestGroups['isCascadeDetach'], $adminGroups['isCascadeDetach']); + + // assert not override attributes + $this->assertEquals('ddc964_users_groups', $guestGroups['joinTable']['name']); + $this->assertEquals('user_id', $guestGroups['joinTable']['joinColumns'][0]['name']); + $this->assertEquals('group_id', $guestGroups['joinTable']['inverseJoinColumns'][0]['name']); + + $this->assertEquals(array('user_id'=>'id'), $guestGroups['relationToSourceKeyColumns']); + $this->assertEquals(array('group_id'=>'id'), $guestGroups['relationToTargetKeyColumns']); + $this->assertEquals(array('user_id','group_id'), $guestGroups['joinTableColumns']); + + + $this->assertEquals('ddc964_users_admingroups', $adminGroups['joinTable']['name']); + $this->assertEquals('adminuser_id', $adminGroups['joinTable']['joinColumns'][0]['name']); + $this->assertEquals('admingroup_id', $adminGroups['joinTable']['inverseJoinColumns'][0]['name']); + + $this->assertEquals(array('adminuser_id'=>'id'), $adminGroups['relationToSourceKeyColumns']); + $this->assertEquals(array('admingroup_id'=>'id'), $adminGroups['relationToTargetKeyColumns']); + $this->assertEquals(array('adminuser_id','admingroup_id'), $adminGroups['joinTableColumns']); + + + // assert address association mappings + $this->assertArrayHasKey('address', $guestMetadata->associationMappings); + $this->assertArrayHasKey('address', $adminMetadata->associationMappings); + + $guestAddress = $guestMetadata->associationMappings['address']; + $adminAddress = $adminMetadata->associationMappings['address']; + + // assert not override attributes + $this->assertEquals($guestAddress['fieldName'], $adminAddress['fieldName']); + $this->assertEquals($guestAddress['type'], $adminAddress['type']); + $this->assertEquals($guestAddress['mappedBy'], $adminAddress['mappedBy']); + $this->assertEquals($guestAddress['inversedBy'], $adminAddress['inversedBy']); + $this->assertEquals($guestAddress['isOwningSide'], $adminAddress['isOwningSide']); + $this->assertEquals($guestAddress['fetch'], $adminAddress['fetch']); + $this->assertEquals($guestAddress['isCascadeRemove'], $adminAddress['isCascadeRemove']); + $this->assertEquals($guestAddress['isCascadePersist'], $adminAddress['isCascadePersist']); + $this->assertEquals($guestAddress['isCascadeRefresh'], $adminAddress['isCascadeRefresh']); + $this->assertEquals($guestAddress['isCascadeMerge'], $adminAddress['isCascadeMerge']); + $this->assertEquals($guestAddress['isCascadeDetach'], $adminAddress['isCascadeDetach']); + + // assert override + $this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']); + $this->assertEquals(array('address_id'=>'id'), $guestAddress['sourceToTargetKeyColumns']); + $this->assertEquals(array('address_id'=>'address_id'), $guestAddress['joinColumnFieldNames']); + $this->assertEquals(array('id'=>'address_id'), $guestAddress['targetToSourceKeyColumns']); + + + $this->assertEquals('adminaddress_id', $adminAddress['joinColumns'][0]['name']); + $this->assertEquals(array('adminaddress_id'=>'id'), $adminAddress['sourceToTargetKeyColumns']); + $this->assertEquals(array('adminaddress_id'=>'adminaddress_id'), $adminAddress['joinColumnFieldNames']); + $this->assertEquals(array('id'=>'adminaddress_id'), $adminAddress['targetToSourceKeyColumns']); + } } /** diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php index fd6afe960..61d13f596 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php @@ -932,6 +932,20 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $this->setExpectedException("Doctrine\ORM\Mapping\MappingException", "Invalid cascade option(s) specified: 'invalid'. Only 'remove', 'persist', 'refresh', 'merge' and 'detach' are allowed."); $cm->mapManyToOne(array('fieldName' => 'address', 'targetEntity' => 'UnknownClass', 'cascade' => array('invalid'))); + } + + /** + * @group DDC-964 + * @expectedException Doctrine\ORM\Mapping\MappingException + * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Admin + */ + public function testInvalidPropertyOverrideNameException() + { + $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Admin'); + $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->mapManyToOne(array('fieldName' => 'address', 'targetEntity' => 'DDC964Address')); + + $cm->setAssociationOverride('invalidPropertyName', array()); } } diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Admin.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Admin.php new file mode 100644 index 000000000..bb8920e76 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Admin.php @@ -0,0 +1,21 @@ +setAssociationOverride('address',array( + 'joinColumns'=>array(array( + 'name' => 'adminaddress_id', + 'referencedColumnName' => 'id', + )) +)); + +$metadata->setAssociationOverride('groups',array( + 'joinTable' => array ( + 'name' => 'ddc964_users_admingroups', + 'joinColumns' => array(array( + 'name' => 'adminuser_id', + )), + + 'inverseJoinColumns' =>array (array ( + 'name' => 'admingroup_id', + )) + ) +)); \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php new file mode 100644 index 000000000..b3d9bbc7f --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php @@ -0,0 +1 @@ +mapField(array( + 'id' => true, + 'fieldName' => 'id', + 'type' => 'integer', + 'columnName' => 'id', +)); +$metadata->mapField(array( + 'fieldName' => 'name', + 'type' => 'string', +)); + +$metadata->mapManyToOne(array( + 'fieldName' => 'address', + 'targetEntity' => 'DDC964Address', + 'cascade' => array('persist','merge'), + 'joinColumn' => array('name'=>'address_id', 'referencedColumnMame'=>'id'), +)); + +$metadata->mapManyToMany(array( + 'fieldName' => 'groups', + 'targetEntity' => 'DDC964Group', + 'inversedBy' => 'users', + 'cascade' => array('persist','merge','detach'), + 'joinTable' => array( + 'name' => 'ddc964_users_groups', + 'joinColumns' => array(array( + 'name'=>'user_id', + 'referencedColumnName'=>'id', + )), + 'inverseJoinColumns'=>array(array( + 'name'=>'group_id', + 'referencedColumnName'=>'id', + )) + ) +)); + +$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.xml new file mode 100644 index 000000000..f4bb4ebce --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml new file mode 100644 index 000000000..d3d61d81e --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml new file mode 100644 index 000000000..47333f18e --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.yml new file mode 100644 index 000000000..0b8051d96 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Admin.dcm.yml @@ -0,0 +1,17 @@ +Doctrine\Tests\Models\DDC964\DDC964Admin: + type: entity + associationOverride: + address: + joinColumn: + adminaddress_id: + name: adminaddress_id + referencedColumnName: id + groups: + joinTable: + name: ddc964_users_admingroups + joinColumns: + adminuser_id: + referencedColumnName: id + inverseJoinColumns: + admingroup_id: + referencedColumnName: id \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml new file mode 100644 index 000000000..7bfae82ff --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml @@ -0,0 +1,2 @@ +Doctrine\Tests\Models\DDC964\DDC964Guest: + type: entity \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml new file mode 100644 index 000000000..5f91b4053 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml @@ -0,0 +1,30 @@ +Doctrine\Tests\Models\DDC964\DDC964User: + type: mappedSuperclass + id: + id: + type: integer + unsigned: true + generator: + strategy: AUTO + fields: + name: + type: string + manyToOne: + address: + targetEntity: DDC964Address + joinColumn: + name: address_id + referencedColumnName: id + cascade: [ persist, merge ] + manyToMany: + groups: + targetEntity: DDC964Group + joinTable: + name: ddc964_users_groups + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + group_id: + referencedColumnName: id + cascade: [ persist, merge, detach ] \ No newline at end of file From 3085c52f95772afb7cce7ad8c964faf1853fbaaf Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Thu, 2 Feb 2012 21:11:15 -0200 Subject: [PATCH 03/10] fix docblock and remove white spaces --- lib/Doctrine/ORM/Mapping/AssociationOverride.php | 4 ++-- lib/Doctrine/ORM/Mapping/AssociationOverrides.php | 2 +- lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php | 12 +++++------- lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php | 6 +++--- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/Doctrine/ORM/Mapping/AssociationOverride.php b/lib/Doctrine/ORM/Mapping/AssociationOverride.php index cd149760b..f9f7f4912 100644 --- a/lib/Doctrine/ORM/Mapping/AssociationOverride.php +++ b/lib/Doctrine/ORM/Mapping/AssociationOverride.php @@ -23,10 +23,10 @@ namespace Doctrine\ORM\Mapping; * This annotation is used to override association mapping of property for an entity relationship. * * @author Fabio B. Silva - * @since 2.2 + * @since 2.3 * * @Annotation - * @Target({"PROPERTY","ANNOTATION"}) + * @Target("ANNOTATION") */ final class AssociationOverride implements Annotation { diff --git a/lib/Doctrine/ORM/Mapping/AssociationOverrides.php b/lib/Doctrine/ORM/Mapping/AssociationOverrides.php index 6cc0d9a41..b46f47f85 100644 --- a/lib/Doctrine/ORM/Mapping/AssociationOverrides.php +++ b/lib/Doctrine/ORM/Mapping/AssociationOverrides.php @@ -23,7 +23,7 @@ namespace Doctrine\ORM\Mapping; * This annotation is used to override association mappings of relationship properties. * * @author Fabio B. Silva - * @since 2.2 + * @since 2.3 * * @Annotation * @Target("CLASS") diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index d42c4e9f5..5d63afda6 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -477,11 +477,6 @@ class ClassMetadataInfo implements ClassMetadata */ public $associationMappings = array(); - /** - * @var array - */ - public $overrideAssociationMappings = array(); - /** * READ-ONLY: Flag indicating whether the identifier/primary key of the class is composite. * @@ -576,7 +571,7 @@ class ClassMetadataInfo implements ClassMetadata /** * NamingStrategy determining the default column and table names * - * @var \Doctrine\ORM\NamingStrategy + * @var Doctrine\ORM\Mapping\NamingStrategy */ protected $namingStrategy; @@ -1808,9 +1803,12 @@ class ClassMetadataInfo implements ClassMetadata } /** + * Sets the association to override association mapping of property for an entity relationship. + * * @param string $fieldName + * @param array $overrideMapping */ - public function setAssociationOverride($fieldName, $overrideMapping) + public function setAssociationOverride($fieldName, array $overrideMapping) { if (!isset($this->associationMappings[$fieldName])) { throw MappingException::invalidOverrideFieldName($this->name, $fieldName); diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index 97b219f6a..d7ec9af70 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -527,13 +527,13 @@ class YamlDriver extends AbstractFileDriver } } - // Evaluate association-overrides + // Evaluate associationOverride if (isset($element['associationOverride'])) { foreach ($element['associationOverride'] as $fieldName => $associationOverride) { $override = array(); - // Check for join-columns + // Check for joinColumn if (isset($associationOverride['joinColumn'])) { $joinColumns = array(); foreach ($associationOverride['joinColumn'] as $name => $joinColumnElement) { @@ -545,7 +545,7 @@ class YamlDriver extends AbstractFileDriver $override['joinColumns'] = $joinColumns; } - // Check for join-table + // Check for joinTable if (isset($associationOverride['joinTable'])) { $joinTableElement = $associationOverride['joinTable']; From 2f6775016558ce7dd1247ce7be5a558f0c212e2f Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Thu, 2 Feb 2012 22:39:34 -0200 Subject: [PATCH 04/10] added tags on doctrine-mapping.xsd --- doctrine-mapping.xsd | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd index 80da4eb93..a51f4906d 100644 --- a/doctrine-mapping.xsd +++ b/doctrine-mapping.xsd @@ -145,6 +145,7 @@ + @@ -483,4 +484,20 @@ + + + + + + + + + + + + + + + + From 4df3c753216d144859dd71b8f8021a01881728d1 Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Mon, 12 Mar 2012 10:02:22 -0300 Subject: [PATCH 05/10] added missing '\' --- lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 5d63afda6..b439573ac 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -571,7 +571,7 @@ class ClassMetadataInfo implements ClassMetadata /** * NamingStrategy determining the default column and table names * - * @var Doctrine\ORM\Mapping\NamingStrategy + * @var \Doctrine\ORM\Mapping\NamingStrategy */ protected $namingStrategy; From 85790f0752faa9522a47134f1948a94d6b9819ec Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sat, 14 Apr 2012 02:10:44 -0300 Subject: [PATCH 06/10] support for attribute override --- doctrine-mapping.xsd | 16 ++ .../ORM/Mapping/ClassMetadataInfo.php | 50 ++++++- lib/Doctrine/ORM/Mapping/Column.php | 2 +- .../ORM/Mapping/Driver/AnnotationDriver.php | 75 +++++++--- .../Mapping/Driver/DoctrineAnnotations.php | 5 +- lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php | 132 ++++++++++------- .../ORM/Mapping/Driver/YamlDriver.php | 138 +++++++++++------- lib/Doctrine/ORM/Mapping/MappingException.php | 11 ++ .../Tests/Models/DDC964/DDC964Guest.php | 28 ++++ .../Tests/Models/DDC964/DDC964User.php | 16 +- .../ORM/Mapping/AbstractMappingDriverTest.php | 40 +++++ .../Tests/ORM/Mapping/ClassMetadataTest.php | 30 +++- ...ctrine.Tests.Models.DDC964.DDC964Guest.php | 12 ++ ...octrine.Tests.Models.DDC964.DDC964User.php | 11 +- ...ne.Tests.Models.DDC964.DDC964Guest.dcm.xml | 8 + ...ine.Tests.Models.DDC964.DDC964User.dcm.xml | 4 +- ...ne.Tests.Models.DDC964.DDC964Guest.dcm.yml | 13 +- ...ine.Tests.Models.DDC964.DDC964User.dcm.yml | 7 +- 18 files changed, 449 insertions(+), 149 deletions(-) diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd index a51f4906d..e8b2e26b2 100644 --- a/doctrine-mapping.xsd +++ b/doctrine-mapping.xsd @@ -146,6 +146,7 @@ + @@ -500,4 +501,19 @@ + + + + + + + + + + + + + + + diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index b439573ac..81acb8021 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -1238,7 +1238,7 @@ class ClassMetadataInfo implements ClassMetadata $mapping['isOwningSide'] = true; // assume owning side until we hit mappedBy // unset optional indexBy attribute if its empty - if (!isset($mapping['indexBy']) || !$mapping['indexBy']) { + if ( ! isset($mapping['indexBy']) || !$mapping['indexBy']) { unset($mapping['indexBy']); } @@ -1364,7 +1364,7 @@ class ClassMetadataInfo implements ClassMetadata foreach ($mapping['joinColumns'] as $key => &$joinColumn) { if ($mapping['type'] === self::ONE_TO_ONE && ! $this->isInheritanceTypeSingleTable()) { if (count($mapping['joinColumns']) == 1) { - if (! isset($mapping['id']) || ! $mapping['id']) { + if ( ! isset($mapping['id']) || ! $mapping['id']) { $joinColumn['unique'] = true; } } else { @@ -1383,7 +1383,7 @@ class ClassMetadataInfo implements ClassMetadata } if ($uniqueContraintColumns) { - if (!$this->table) { + if ( ! $this->table) { throw new \RuntimeException("ClassMetadataInfo::setTable() has to be called before defining a one to one relationship."); } $this->table['uniqueConstraints'][$mapping['fieldName']."_uniq"] = array( @@ -1810,7 +1810,7 @@ class ClassMetadataInfo implements ClassMetadata */ public function setAssociationOverride($fieldName, array $overrideMapping) { - if (!isset($this->associationMappings[$fieldName])) { + if ( ! isset($this->associationMappings[$fieldName])) { throw MappingException::invalidOverrideFieldName($this->name, $fieldName); } @@ -1848,6 +1848,44 @@ class ClassMetadataInfo implements ClassMetadata $this->associationMappings[$fieldName] = $mapping; } + /** + * Sets the override for a mapped field. + * + * @param string $fieldName + * @param array $mapping + */ + public function setAttributeOverride($fieldName, array $overrideMapping) + { + if ( ! isset($this->fieldMappings[$fieldName])) { + throw MappingException::invalidOverrideFieldName($this->name, $fieldName); + } + + $mapping = $this->fieldMappings[$fieldName]; + + if (isset($mapping['id'])) { + $overrideMapping['id'] = $mapping['id']; + } + + if ( ! isset($overrideMapping['type']) || $overrideMapping['type'] === null) { + $overrideMapping['type'] = $mapping['type']; + } + + if ( ! isset($overrideMapping['fieldName']) || $overrideMapping['fieldName'] === null) { + $overrideMapping['fieldName'] = $mapping['fieldName']; + } + + if ($overrideMapping['type'] !== $mapping['type']) { + throw MappingException::invalidOverrideFieldType($this->name, $fieldName); + } + + unset($this->fieldMappings[$fieldName]); + unset($this->fieldNames[$mapping['columnName']]); + unset($this->columnNames[$mapping['fieldName']]); + $this->_validateAndCompleteFieldMapping($overrideMapping); + + $this->fieldMappings[$fieldName] = $overrideMapping; + } + /** * Checks whether a mapped field is inherited from an entity superclass. * @@ -2408,7 +2446,7 @@ class ClassMetadataInfo implements ClassMetadata */ public function getSingleAssociationJoinColumnName($fieldName) { - if (!$this->isAssociationWithSingleJoinColumn($fieldName)) { + if ( ! $this->isAssociationWithSingleJoinColumn($fieldName)) { throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName); } return $this->associationMappings[$fieldName]['joinColumns'][0]['name']; @@ -2422,7 +2460,7 @@ class ClassMetadataInfo implements ClassMetadata */ public function getSingleAssociationReferencedJoinColumnName($fieldName) { - if (!$this->isAssociationWithSingleJoinColumn($fieldName)) { + if ( ! $this->isAssociationWithSingleJoinColumn($fieldName)) { throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName); } return $this->associationMappings[$fieldName]['joinColumns'][0]['referencedColumnName']; diff --git a/lib/Doctrine/ORM/Mapping/Column.php b/lib/Doctrine/ORM/Mapping/Column.php index 5f7dd7f64..d1c85509b 100644 --- a/lib/Doctrine/ORM/Mapping/Column.php +++ b/lib/Doctrine/ORM/Mapping/Column.php @@ -21,7 +21,7 @@ namespace Doctrine\ORM\Mapping; /** * @Annotation - * @Target("PROPERTY") + * @Target({"PROPERTY","ANNOTATION"}) */ final class Column implements Annotation { diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 053342cf8..9885c43ec 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -24,7 +24,8 @@ use Doctrine\Common\Cache\ArrayCache, Doctrine\Common\Annotations\AnnotationRegistry, Doctrine\ORM\Mapping\ClassMetadataInfo, Doctrine\ORM\Mapping\MappingException, - Doctrine\ORM\Mapping\JoinColumn; + Doctrine\ORM\Mapping\JoinColumn, + Doctrine\ORM\Mapping\Column; /** * The AnnotationDriver reads the mapping metadata from docblock annotations. @@ -135,7 +136,7 @@ class AnnotationDriver implements Driver public function loadMetadataForClass($className, ClassMetadataInfo $metadata) { $class = $metadata->getReflectionClass(); - if (!$class) { + if ( ! $class) { // this happens when running annotation driver in combination with // static reflection services. This is not the nicest fix $class = new \ReflectionClass($metadata->name); @@ -261,12 +262,12 @@ class AnnotationDriver implements Driver if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) { $namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries']; - if (!is_array($namedQueriesAnnot->value)) { + if ( ! is_array($namedQueriesAnnot->value)) { throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); } foreach ($namedQueriesAnnot->value as $namedQuery) { - if (!($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) { + if ( ! ($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) { throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); } $metadata->addNamedQuery(array( @@ -378,23 +379,7 @@ class AnnotationDriver implements Driver throw MappingException::propertyTypeIsRequired($className, $property->getName()); } - $mapping['type'] = $columnAnnot->type; - $mapping['length'] = $columnAnnot->length; - $mapping['precision'] = $columnAnnot->precision; - $mapping['scale'] = $columnAnnot->scale; - $mapping['nullable'] = $columnAnnot->nullable; - $mapping['unique'] = $columnAnnot->unique; - if ($columnAnnot->options) { - $mapping['options'] = $columnAnnot->options; - } - - if (isset($columnAnnot->name)) { - $mapping['columnName'] = $columnAnnot->name; - } - - if (isset($columnAnnot->columnDefinition)) { - $mapping['columnDefinition'] = $columnAnnot->columnDefinition; - } + $mapping = $this->columnToArray($property->getName(), $columnAnnot); if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) { $mapping['id'] = true; @@ -537,6 +522,16 @@ class AnnotationDriver implements Driver } } + $attributeOverrides = array(); + // Evaluate AttributeOverrides annotation + if (isset($classAnnotations['Doctrine\ORM\Mapping\AttributeOverrides'])) { + $attributeOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AttributeOverrides']; + foreach ($attributeOverridesAnnot->value as $attributeOverrideAnnot) { + $attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column); + $metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride); + } + } + // Evaluate @HasLifecycleCallbacks annotation if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) { foreach ($class->getMethods() as $method) { @@ -625,7 +620,7 @@ class AnnotationDriver implements Driver return $this->_classNames; } - if (!$this->_paths) { + if ( ! $this->_paths) { throw MappingException::pathRequired(); } @@ -680,7 +675,7 @@ class AnnotationDriver implements Driver */ private function getFetchMode($className, $fetchMode) { - if(!defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) { + if( ! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) { throw MappingException::invalidFetchMode($className, $fetchMode); } @@ -705,6 +700,40 @@ class AnnotationDriver implements Driver ); } + /** + * Parse the given Column as array + * + * @param string $fieldName + * @param Column $column + * @return array + */ + private function columnToArray($fieldName, Column $column) + { + $mapping = array( + 'fieldName' => $fieldName, + 'type' => $column->type, + 'scale' => $column->scale, + 'length' => $column->length, + 'unique' => $column->unique, + 'nullable' => $column->nullable, + 'precision' => $column->precision + ); + + if ($column->options) { + $mapping['options'] = $column->options; + } + + if (isset($column->name)) { + $mapping['columnName'] = $column->name; + } + + if (isset($column->columnDefinition)) { + $mapping['columnDefinition'] = $column->columnDefinition; + } + + return $mapping; + } + /** * Factory method for the Annotation Driver * diff --git a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php index cb911e522..f5a1a32b5 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php +++ b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php @@ -61,4 +61,7 @@ require_once __DIR__.'/../NamedNativeQueries.php'; require_once __DIR__.'/../SqlResultSetMapping.php'; require_once __DIR__.'/../SqlResultSetMappings.php'; require_once __DIR__.'/../AssociationOverride.php'; -require_once __DIR__.'/../AssociationOverrides.php'; \ No newline at end of file +require_once __DIR__.'/../AssociationOverrides.php'; +require_once __DIR__.'/../AssociationOverrides.php'; +require_once __DIR__.'/../AttributeOverride.php'; +require_once __DIR__.'/../AttributeOverrides.php'; \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php index 12c50e4a3..bb2dcad99 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php @@ -50,7 +50,7 @@ class XmlDriver extends AbstractFileDriver public function loadMetadataForClass($className, ClassMetadataInfo $metadata) { $xmlRoot = $this->getElement($className); - + if ($xmlRoot->getName() == 'entity') { if (isset($xmlRoot['repository-class'])) { $metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']); @@ -224,51 +224,8 @@ class XmlDriver extends AbstractFileDriver // Evaluate mappings if (isset($xmlRoot->field)) { foreach ($xmlRoot->field as $fieldMapping) { - $mapping = array( - 'fieldName' => (string)$fieldMapping['name'], - ); - - if (isset($fieldMapping['type'])) { - $mapping['type'] = (string)$fieldMapping['type']; - } - - if (isset($fieldMapping['column'])) { - $mapping['columnName'] = (string)$fieldMapping['column']; - } - - if (isset($fieldMapping['length'])) { - $mapping['length'] = (int)$fieldMapping['length']; - } - - if (isset($fieldMapping['precision'])) { - $mapping['precision'] = (int)$fieldMapping['precision']; - } - - if (isset($fieldMapping['scale'])) { - $mapping['scale'] = (int)$fieldMapping['scale']; - } - - if (isset($fieldMapping['unique'])) { - $mapping['unique'] = ((string)$fieldMapping['unique'] == "false") ? false : true; - } - - if (isset($fieldMapping['nullable'])) { - $mapping['nullable'] = ((string)$fieldMapping['nullable'] == "false") ? false : true; - } - - if (isset($fieldMapping['version']) && $fieldMapping['version']) { - $metadata->setVersionMapping($mapping); - } - - if (isset($fieldMapping['column-definition'])) { - $mapping['columnDefinition'] = (string)$fieldMapping['column-definition']; - } - - if (isset($fieldMapping->options)) { - $mapping['options'] = $this->_parseOptions($fieldMapping->options->children()); - } - - $mappings[] = $mapping; + $mapping = $this->columnToArray($fieldMapping); + $metadata->mapField($mapping); } } @@ -293,6 +250,10 @@ class XmlDriver extends AbstractFileDriver $mapping['type'] = (string)$idElement['type']; } + if (isset($idElement['length'])) { + $mapping['length'] = (string)$idElement['length']; + } + if (isset($idElement['column'])) { $mapping['columnName'] = (string)$idElement['column']; } @@ -519,25 +480,37 @@ class XmlDriver extends AbstractFileDriver } } + // Evaluate association-overrides + if (isset($xmlRoot->{'attribute-overrides'})) { + foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} as $overrideElement) { + $fieldName = (string) $overrideElement['name']; + foreach ($overrideElement->field as $field) { + $mapping = $this->columnToArray($field); + $mapping['fieldName'] = $fieldName; + $metadata->setAttributeOverride($fieldName, $mapping); + } + } + } + // Evaluate association-overrides if (isset($xmlRoot->{'association-overrides'})) { - foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $associationOverrideElement) { - $fieldName = (string) $associationOverrideElement['name']; + foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $overrideElement) { + $fieldName = (string) $overrideElement['name']; $override = array(); // Check for join-columns - if (isset($associationOverrideElement->{'join-columns'})) { + if (isset($overrideElement->{'join-columns'})) { $joinColumns = array(); - foreach ($associationOverrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + foreach ($overrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { $joinColumns[] = $this->joinColumnToArray($joinColumnElement); } $override['joinColumns'] = $joinColumns; } // Check for join-table - if ($associationOverrideElement->{'join-table'}) { + if ($overrideElement->{'join-table'}) { $joinTable = null; - $joinTableElement = $associationOverrideElement->{'join-table'}; + $joinTableElement = $overrideElement->{'join-table'}; $joinTable = array( 'name' => (string) $joinTableElement['name'], @@ -633,6 +606,61 @@ class XmlDriver extends AbstractFileDriver return $joinColumn; } + /** + * Parse the given field as array + * + * @param SimpleXMLElement $fieldMapping + * @return array + */ + private function columnToArray(SimpleXMLElement $fieldMapping) + { + $mapping = array( + 'fieldName' => (string)$fieldMapping['name'], + ); + + if (isset($fieldMapping['type'])) { + $mapping['type'] = (string)$fieldMapping['type']; + } + + if (isset($fieldMapping['column'])) { + $mapping['columnName'] = (string)$fieldMapping['column']; + } + + if (isset($fieldMapping['length'])) { + $mapping['length'] = (int)$fieldMapping['length']; + } + + if (isset($fieldMapping['precision'])) { + $mapping['precision'] = (int)$fieldMapping['precision']; + } + + if (isset($fieldMapping['scale'])) { + $mapping['scale'] = (int)$fieldMapping['scale']; + } + + if (isset($fieldMapping['unique'])) { + $mapping['unique'] = ((string)$fieldMapping['unique'] == "false") ? false : true; + } + + if (isset($fieldMapping['nullable'])) { + $mapping['nullable'] = ((string)$fieldMapping['nullable'] == "false") ? false : true; + } + + if (isset($fieldMapping['version']) && $fieldMapping['version']) { + $metadata->setVersionMapping($mapping); + } + + if (isset($fieldMapping['column-definition'])) { + $mapping['columnDefinition'] = (string)$fieldMapping['column-definition']; + } + + if (isset($fieldMapping->options)) { + $mapping['options'] = $this->_parseOptions($fieldMapping->options->children()); + } + + return $mapping; + } + /** * Gathers a list of cascade options found in the given cascade element. * diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index d7ec9af70..68ca0b29d 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -277,19 +277,7 @@ class YamlDriver extends AbstractFileDriver if (isset($element['fields'])) { foreach ($element['fields'] as $name => $fieldMapping) { - $mapping = array( - 'fieldName' => $name - ); - - if (isset($fieldMapping['type'])) { - $e = explode('(', $fieldMapping['type']); - $fieldMapping['type'] = $e[0]; - $mapping['type'] = $fieldMapping['type']; - - if (isset($e[1])) { - $fieldMapping['length'] = substr($e[1], 0, strlen($e[1]) - 1); - } - } + $mapping = $this->columnToArray($name, $fieldMapping); if (isset($fieldMapping['id'])) { $mapping['id'] = true; @@ -298,33 +286,6 @@ class YamlDriver extends AbstractFileDriver . strtoupper($fieldMapping['generator']['strategy']))); } } - if (isset($fieldMapping['column'])) { - $mapping['columnName'] = $fieldMapping['column']; - } - if (isset($fieldMapping['length'])) { - $mapping['length'] = $fieldMapping['length']; - } - if (isset($fieldMapping['precision'])) { - $mapping['precision'] = $fieldMapping['precision']; - } - if (isset($fieldMapping['scale'])) { - $mapping['scale'] = $fieldMapping['scale']; - } - if (isset($fieldMapping['unique'])) { - $mapping['unique'] = (bool)$fieldMapping['unique']; - } - if (isset($fieldMapping['options'])) { - $mapping['options'] = $fieldMapping['options']; - } - if (isset($fieldMapping['nullable'])) { - $mapping['nullable'] = $fieldMapping['nullable']; - } - if (isset($fieldMapping['version']) && $fieldMapping['version']) { - $metadata->setVersionMapping($mapping); - } - if (isset($fieldMapping['columnDefinition'])) { - $mapping['columnDefinition'] = $fieldMapping['columnDefinition']; - } $metadata->mapField($mapping); } @@ -359,7 +320,7 @@ class YamlDriver extends AbstractFileDriver $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']); } else if (isset($oneToOneElement['joinColumns'])) { foreach ($oneToOneElement['joinColumns'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } @@ -441,7 +402,7 @@ class YamlDriver extends AbstractFileDriver $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']); } else if (isset($manyToOneElement['joinColumns'])) { foreach ($manyToOneElement['joinColumns'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } @@ -485,7 +446,7 @@ class YamlDriver extends AbstractFileDriver } foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } @@ -493,7 +454,7 @@ class YamlDriver extends AbstractFileDriver } foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } @@ -528,16 +489,16 @@ class YamlDriver extends AbstractFileDriver } // Evaluate associationOverride - if (isset($element['associationOverride'])) { + if (isset($element['associationOverride']) && is_array($element['associationOverride'])) { - foreach ($element['associationOverride'] as $fieldName => $associationOverride) { + foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) { $override = array(); // Check for joinColumn - if (isset($associationOverride['joinColumn'])) { + if (isset($associationOverrideElement['joinColumn'])) { $joinColumns = array(); - foreach ($associationOverride['joinColumn'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } $joinColumns[] = $this->joinColumnToArray($joinColumnElement); @@ -546,9 +507,9 @@ class YamlDriver extends AbstractFileDriver } // Check for joinTable - if (isset($associationOverride['joinTable'])) { + if (isset($associationOverrideElement['joinTable'])) { - $joinTableElement = $associationOverride['joinTable']; + $joinTableElement = $associationOverrideElement['joinTable']; $joinTable = array( 'name' => $joinTableElement['name'] ); @@ -558,7 +519,7 @@ class YamlDriver extends AbstractFileDriver } foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } @@ -566,7 +527,7 @@ class YamlDriver extends AbstractFileDriver } foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { - if (!isset($joinColumnElement['name'])) { + if ( ! isset($joinColumnElement['name'])) { $joinColumnElement['name'] = $name; } @@ -580,6 +541,15 @@ class YamlDriver extends AbstractFileDriver } } + // Evaluate associationOverride + if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) { + + foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) { + $mapping = $this->columnToArray($fieldName, $attributeOverrideElement); + $metadata->setAttributeOverride($fieldName, $mapping); + } + } + // Evaluate lifeCycleCallbacks if (isset($element['lifecycleCallbacks'])) { foreach ($element['lifecycleCallbacks'] as $type => $methods) { @@ -631,6 +601,68 @@ class YamlDriver extends AbstractFileDriver return $joinColumn; } + /** + * Parse the given column as array + * + * @param string $fieldName + * @param array $column + * @return array + */ + private function columnToArray($fieldName, $column) + { + $mapping = array( + 'fieldName' => $fieldName + ); + + if (isset($column['type'])) { + $params = explode('(', $column['type']); + $column['type'] = $params[0]; + $mapping['type'] = $column['type']; + + if (isset($params[1])) { + $column['length'] = substr($params[1], 0, strlen($params[1]) - 1); + } + } + + if (isset($column['column'])) { + $mapping['columnName'] = $column['column']; + } + + if (isset($column['length'])) { + $mapping['length'] = $column['length']; + } + + if (isset($column['precision'])) { + $mapping['precision'] = $column['precision']; + } + + if (isset($column['scale'])) { + $mapping['scale'] = $column['scale']; + } + + if (isset($column['unique'])) { + $mapping['unique'] = (bool)$column['unique']; + } + + if (isset($column['options'])) { + $mapping['options'] = $column['options']; + } + + if (isset($column['nullable'])) { + $mapping['nullable'] = $column['nullable']; + } + + if (isset($column['version']) && $column['version']) { + $metadata->setVersionMapping($mapping); + } + + if (isset($column['columnDefinition'])) { + $mapping['columnDefinition'] = $column['columnDefinition']; + } + + return $mapping; + } + /** * {@inheritdoc} */ diff --git a/lib/Doctrine/ORM/Mapping/MappingException.php b/lib/Doctrine/ORM/Mapping/MappingException.php index f88109f0c..dcf3a7da8 100644 --- a/lib/Doctrine/ORM/Mapping/MappingException.php +++ b/lib/Doctrine/ORM/Mapping/MappingException.php @@ -94,6 +94,17 @@ class MappingException extends \Doctrine\ORM\ORMException return new self("Invalid field override named '$fieldName' for class '$className'."); } + /** + * Exception for invalid property type override. + * + * @param string $className The entity's name + * @param string $fieldName + */ + public static function invalidOverrideFieldType($className, $fieldName) + { + return new self("The column type of attribute '$fieldName' on class '$className' could not be changed."); + } + public static function mappingNotFound($className, $fieldName) { return new self("No mapping found for field '$fieldName' on class '$className'."); diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php b/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php index 71654a12b..90501187c 100644 --- a/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964Guest.php @@ -6,11 +6,39 @@ use Doctrine\Common\Collections\ArrayCollection; /** * @Entity + * @AttributeOverrides({ + * @AttributeOverride(name="id", + * column=@Column( + * name = "guest_id", + * type = "integer", + length = 140 + * ) + * ), + * @AttributeOverride(name="name", + * column=@Column( + * name = "guest_name", + * nullable = false, + * unique = true, + length = 240 + * ) + * ) + * }) */ class DDC964Guest extends DDC964User { public static function loadMetadata($metadata) { + $metadata->setAttributeOverride('id', array( + 'columnName' => 'guest_id', + 'type' => 'integer', + 'length' => 140, + )); + $metadata->setAttributeOverride('name',array( + 'columnName' => 'guest_name', + 'nullable' => false, + 'unique' => true, + 'length' => 240, + )); } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964User.php b/tests/Doctrine/Tests/Models/DDC964/DDC964User.php index 07947e57f..608f42d96 100644 --- a/tests/Doctrine/Tests/Models/DDC964/DDC964User.php +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964User.php @@ -11,13 +11,14 @@ class DDC964User { /** + * @Id * @GeneratedValue - * @Id @Column(type="integer") + * @Column(type="integer", name="user_id", length=150) */ protected $id; /** - * @Column + * @Column(name="user_name", nullable=true, unique=false, length=250) */ protected $name; @@ -112,11 +113,16 @@ class DDC964User 'id' => true, 'fieldName' => 'id', 'type' => 'integer', - 'columnName' => 'id', + 'columnName' => 'user_id', + 'length' => 150, )); $metadata->mapField(array( - 'fieldName' => 'name', - 'type' => 'string', + 'fieldName' => 'name', + 'type' => 'string', + 'columnName'=> 'user_name', + 'nullable' => true, + 'unique' => false, + 'length' => 250, )); $metadata->mapManyToOne(array( diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php index 9e1cbde2d..e83a9dbc2 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php @@ -693,6 +693,46 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase $this->assertEquals(array('adminaddress_id'=>'adminaddress_id'), $adminAddress['joinColumnFieldNames']); $this->assertEquals(array('id'=>'adminaddress_id'), $adminAddress['targetToSourceKeyColumns']); } + + /** + * @group DDC-964 + */ + public function testAttributeOverridesMapping() + { + + $factory = $this->createClassMetadataFactory(); + $guestMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Guest'); + $adminMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Admin'); + + $this->assertTrue($adminMetadata->fieldMappings['id']['id']); + $this->assertEquals('id', $adminMetadata->fieldMappings['id']['fieldName']); + $this->assertEquals('user_id', $adminMetadata->fieldMappings['id']['columnName']); + $this->assertEquals(array('user_id'=>'id','user_name'=>'name'), $adminMetadata->fieldNames); + $this->assertEquals(array('id'=>'user_id','name'=>'user_name'), $adminMetadata->columnNames); + $this->assertEquals(150, $adminMetadata->fieldMappings['id']['length']); + + + $this->assertEquals('name', $adminMetadata->fieldMappings['name']['fieldName']); + $this->assertEquals('user_name', $adminMetadata->fieldMappings['name']['columnName']); + $this->assertEquals(250, $adminMetadata->fieldMappings['name']['length']); + $this->assertTrue($adminMetadata->fieldMappings['name']['nullable']); + $this->assertFalse($adminMetadata->fieldMappings['name']['unique']); + + + $this->assertTrue($guestMetadata->fieldMappings['id']['id']); + $this->assertEquals('guest_id', $guestMetadata->fieldMappings['id']['columnName']); + $this->assertEquals('id', $guestMetadata->fieldMappings['id']['fieldName']); + $this->assertEquals(array('guest_id'=>'id','guest_name'=>'name'), $guestMetadata->fieldNames); + $this->assertEquals(array('id'=>'guest_id','name'=>'guest_name'), $guestMetadata->columnNames); + $this->assertEquals(140, $guestMetadata->fieldMappings['id']['length']); + + $this->assertEquals('name', $guestMetadata->fieldMappings['name']['fieldName']); + $this->assertEquals('guest_name', $guestMetadata->fieldMappings['name']['columnName']); + $this->assertEquals(240, $guestMetadata->fieldMappings['name']['length']); + $this->assertFalse($guestMetadata->fieldMappings['name']['nullable']); + $this->assertTrue($guestMetadata->fieldMappings['name']['unique']); + } + } /** diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php index 61d13f596..26ae1b511 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php @@ -939,7 +939,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase * @expectedException Doctrine\ORM\Mapping\MappingException * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Admin */ - public function testInvalidPropertyOverrideNameException() + public function testInvalidPropertyAssociationOverrideNameException() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Admin'); $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); @@ -947,6 +947,34 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $cm->setAssociationOverride('invalidPropertyName', array()); } + + /** + * @group DDC-964 + * @expectedException Doctrine\ORM\Mapping\MappingException + * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Guest'. + */ + public function testInvalidPropertyAttributeOverrideNameException() + { + $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Guest'); + $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->mapField(array('fieldName' => 'name')); + + $cm->setAttributeOverride('invalidPropertyName', array()); + } + + /** + * @group DDC-964 + * @expectedException Doctrine\ORM\Mapping\MappingException + * @expectedExceptionMessage The column type of attribute 'name' on class 'Doctrine\Tests\Models\DDC964\DDC964Guest' could not be changed. + */ + public function testInvalidOverrideAttributeFieldTypeException() + { + $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Guest'); + $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->mapField(array('fieldName' => 'name', 'type'=>'string')); + + $cm->setAttributeOverride('name', array('type'=>'date')); + } } class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php index b3d9bbc7f..5094ecddf 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964Guest.php @@ -1 +1,13 @@ setAttributeOverride('id', array( + 'columnName' => 'guest_id', + 'type' => 'integer', + 'length' => 140, +)); + +$metadata->setAttributeOverride('name',array( + 'columnName' => 'guest_name', + 'nullable' => false, + 'unique' => true, + 'length' => 240, +)); \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964User.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964User.php index a3463d6f9..7b66deef0 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964User.php +++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.Models.DDC964.DDC964User.php @@ -6,11 +6,16 @@ $metadata->mapField(array( 'id' => true, 'fieldName' => 'id', 'type' => 'integer', - 'columnName' => 'id', + 'columnName' => 'user_id', + 'length' => 150, )); $metadata->mapField(array( - 'fieldName' => 'name', - 'type' => 'string', + 'fieldName' => 'name', + 'type' => 'string', + 'columnName'=> 'user_name', + 'nullable' => true, + 'unique' => false, + 'length' => 250, )); $metadata->mapManyToOne(array( diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml index d3d61d81e..561066f6b 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.xml @@ -5,6 +5,14 @@ http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> + + + + + + + + \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml index 47333f18e..68db74b48 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml @@ -5,11 +5,11 @@ http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - + - + diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml index 7bfae82ff..ec7936f4a 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml +++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964Guest.dcm.yml @@ -1,2 +1,13 @@ Doctrine\Tests\Models\DDC964\DDC964Guest: - type: entity \ No newline at end of file + type: entity + attributeOverride: + id: + column: guest_id + type: integer + length: 140 + name: + column: guest_name + type: string + length: 240 + nullable: false + unique: true \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml index 5f91b4053..3a9ebbf9d 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml +++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.yml @@ -3,12 +3,17 @@ Doctrine\Tests\Models\DDC964\DDC964User: id: id: type: integer - unsigned: true + column: user_id + length: 150 generator: strategy: AUTO fields: name: type: string + column: user_name + length: 250 + nullable: true + unique: false manyToOne: address: targetEntity: DDC964Address From f63cb95ef327d16a0e3aa6041e17cbc2eb8ee07b Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sat, 14 Apr 2012 02:16:35 -0300 Subject: [PATCH 07/10] add annotations --- .../ORM/Mapping/AttributeOverride.php | 47 +++++++++++++++++++ .../ORM/Mapping/AttributeOverrides.php | 41 ++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 lib/Doctrine/ORM/Mapping/AttributeOverride.php create mode 100644 lib/Doctrine/ORM/Mapping/AttributeOverrides.php diff --git a/lib/Doctrine/ORM/Mapping/AttributeOverride.php b/lib/Doctrine/ORM/Mapping/AttributeOverride.php new file mode 100644 index 000000000..33d31a803 --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/AttributeOverride.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Used to override the mapping of a property. + * + * @author Fabio B. Silva + * @since 2.2 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class AttributeOverride implements Annotation +{ + + /** + * The name of the property whose mapping is being overridden. + * + * @var string + */ + public $name; + + /** + * The name of the property whose mapping is being overridden. + * + * @var \Doctrine\ORM\Mapping\Column + */ + public $column; +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/AttributeOverrides.php b/lib/Doctrine/ORM/Mapping/AttributeOverrides.php new file mode 100644 index 000000000..6fcb00296 --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/AttributeOverrides.php @@ -0,0 +1,41 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Used to override mappings of multiple properties or fields. + * + * @author Fabio B. Silva + * @since 2.2 + * + * @Annotation + * @Target("CLASS") + */ +final class AttributeOverrides implements Annotation +{ + + /** + * One or more field or property mapping overrides. + * + * @var array<\Doctrine\ORM\Mapping\AttributeOverride> + */ + public $value; + +} \ No newline at end of file From 56fb1035de1a5c909027d860586f20b206e91704 Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sat, 14 Apr 2012 02:34:54 -0300 Subject: [PATCH 08/10] update docblock --- lib/Doctrine/ORM/Mapping/AttributeOverride.php | 6 +++--- lib/Doctrine/ORM/Mapping/AttributeOverrides.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Doctrine/ORM/Mapping/AttributeOverride.php b/lib/Doctrine/ORM/Mapping/AttributeOverride.php index 33d31a803..629509c5d 100644 --- a/lib/Doctrine/ORM/Mapping/AttributeOverride.php +++ b/lib/Doctrine/ORM/Mapping/AttributeOverride.php @@ -20,10 +20,10 @@ namespace Doctrine\ORM\Mapping; /** - * Used to override the mapping of a property. + * This annotation is used to override the mapping of a entity property. * * @author Fabio B. Silva - * @since 2.2 + * @since 2.3 * * @Annotation * @Target("ANNOTATION") @@ -39,7 +39,7 @@ final class AttributeOverride implements Annotation public $name; /** - * The name of the property whose mapping is being overridden. + * The column definition. * * @var \Doctrine\ORM\Mapping\Column */ diff --git a/lib/Doctrine/ORM/Mapping/AttributeOverrides.php b/lib/Doctrine/ORM/Mapping/AttributeOverrides.php index 6fcb00296..3693b22e7 100644 --- a/lib/Doctrine/ORM/Mapping/AttributeOverrides.php +++ b/lib/Doctrine/ORM/Mapping/AttributeOverrides.php @@ -20,10 +20,10 @@ namespace Doctrine\ORM\Mapping; /** - * Used to override mappings of multiple properties or fields. + * This annotation is used to override the mapping of a entity property. * * @author Fabio B. Silva - * @since 2.2 + * @since 2.3 * * @Annotation * @Target("CLASS") From 5c7d7c6f05c763c83bc22c19c5887b88bb4bb19c Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sat, 21 Apr 2012 01:53:34 -0300 Subject: [PATCH 09/10] remove duplicated 'require_once' --- lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php index f5a1a32b5..a9ad6f7bd 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php +++ b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php @@ -62,6 +62,5 @@ require_once __DIR__.'/../SqlResultSetMapping.php'; require_once __DIR__.'/../SqlResultSetMappings.php'; require_once __DIR__.'/../AssociationOverride.php'; require_once __DIR__.'/../AssociationOverrides.php'; -require_once __DIR__.'/../AssociationOverrides.php'; require_once __DIR__.'/../AttributeOverride.php'; require_once __DIR__.'/../AttributeOverrides.php'; \ No newline at end of file From fa140d8f594e11cc5ec45604350a3c97ebd6355d Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Sat, 21 Apr 2012 01:59:25 -0300 Subject: [PATCH 10/10] remove wrong conflit mark --- tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php index e83a9dbc2..7d44417c3 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php @@ -463,7 +463,6 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase } /** -<<<<<<< HEAD * @group DDC-889 * @expectedException Doctrine\ORM\Mapping\MappingException * @expectedExceptionMessage Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class. @@ -487,7 +486,6 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase } /** -<<<<<<< HEAD * @group DDC-1663 */ public function testNamedNativeQuery()