diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 38188b472c8..8cfc73daf8f 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -377,7 +377,12 @@ private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $pare private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass): void { foreach ($parentClass->associationMappings as $field => $mapping) { - if ($parentClass->isMappedSuperclass) { + if (! isset($mapping['declared'])) { + $mapping['declared'] = $parentClass->name; + } + + $declaredInParent = $mapping['declared'] === $parentClass->name; + if ($parentClass->isMappedSuperclass && $declaredInParent) { if ($mapping['type'] & ClassMetadata::TO_MANY && ! $mapping['isOwningSide']) { throw MappingException::illegalToManyAssociationOnMappedSuperclass($parentClass->name, $field); } @@ -390,10 +395,6 @@ private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $p $mapping['inherited'] = $parentClass->name; } - if (! isset($mapping['declared'])) { - $mapping['declared'] = $parentClass->name; - } - $subClass->addInheritedAssociationMapping($mapping); } } diff --git a/tests/Doctrine/Tests/Models/JoinedInheritanceTypeWithAssociation/InvalidToManyOnMappedSuperclass/ChildMappedSuperclass.php b/tests/Doctrine/Tests/Models/JoinedInheritanceTypeWithAssociation/InvalidToManyOnMappedSuperclass/ChildMappedSuperclass.php new file mode 100644 index 00000000000..ce439b35253 --- /dev/null +++ b/tests/Doctrine/Tests/Models/JoinedInheritanceTypeWithAssociation/InvalidToManyOnMappedSuperclass/ChildMappedSuperclass.php @@ -0,0 +1,21 @@ +getMetadataFor($cm1->name); } + public function testGetMetadataForJoinedSuperclassWithToManyAssociationAndChildMappedSuperclass(): void + { + $cmf = new ClassMetadataFactory(); + $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/JoinedInheritanceType/']); + $em = $this->createEntityManager($driver); + $cmf->setEntityManager($em); + + $rootMetadata = $cmf->getMetadataFor(RootEntity::class); + $childMetadata = $cmf->getMetadataFor(ValidToManyOnRoot\ChildMappedSuperclass::class); + $grandchildMetadata = $cmf->getMetadataFor(ValidToManyOnRoot\GrandchildEntity::class); + + self::assertTrue($rootMetadata->hasAssociation('toManyAssociation')); + self::assertTrue($childMetadata->hasAssociation('toManyAssociation')); + self::assertTrue($grandchildMetadata->hasAssociation('toManyAssociation')); + } + + public function testThrowsExceptionForToManyOnGrandparentMappedSuperclass(): void + { + $cmf = new ClassMetadataFactory(); + $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/JoinedInheritanceType/']); + $em = $this->createEntityManager($driver); + $cmf->setEntityManager($em); + + $rootMetadata = $cmf->getMetadataFor(RootEntity::class); + self::expectException(MappingException::class); + $mappedSuperclass1Metadata = $cmf->getMetadataFor(InvalidToManyOnMappedSuperclass\ChildMappedSuperclass::class); + $mappedSuperclass2Metadata = $cmf->getMetadataFor(InvalidToManyOnMappedSuperclass\GrandchildMappedSuperclass::class); + $grandchildMetadata = $cmf->getMetadataFor(InvalidToManyOnMappedSuperclass\GreatGrandchildEntity::class); + } + + public function testInheritedNotSetForToOneOnGrandparentMappedSuperclass(): void + { + $cmf = new ClassMetadataFactory(); + $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/JoinedInheritanceType/']); + $em = $this->createEntityManager($driver); + $cmf->setEntityManager($em); + + $grandchildMetadata = $cmf->getMetadataFor(ToOneOnMappedSuperclass\GreatGrandchildEntity::class); + self::assertFalse($grandchildMetadata->isInheritedAssociation('toOneAssociation')); + } + public function testHasGetMetadataNamespaceSeparatorIsNotNormalized(): void { require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';