diff --git a/lib/Doctrine/ORM/Tools/SchemaValidator.php b/lib/Doctrine/ORM/Tools/SchemaValidator.php index df4138d5abe..ff38d458877 100644 --- a/lib/Doctrine/ORM/Tools/SchemaValidator.php +++ b/lib/Doctrine/ORM/Tools/SchemaValidator.php @@ -22,6 +22,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\DBAL\Types\Type; +use function count; /** * Performs strict validation of the mapping schema @@ -96,6 +97,12 @@ public function validateClass(ClassMetadataInfo $class) } } + if ($class->isEmbeddedClass && count($class->associationMappings) > 0) { + $ce[] = "Embeddable '" . $class->name . "' does not support associations"; + + return $ce; + } + foreach ($class->associationMappings as $fieldName => $assoc) { if (!class_exists($assoc['targetEntity']) || $cmf->isTransient($assoc['targetEntity'])) { $ce[] = "The target entity '" . $assoc['targetEntity'] . "' specified on " . $class->name . '#' . $fieldName . ' is unknown or not an entity.'; diff --git a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php index 682ee896d1a..76618d540a4 100644 --- a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php @@ -1,26 +1,26 @@ em = $this->_getTestEntityManager(); + $this->em = $this->_getTestEntityManager(); $this->validator = new SchemaValidator($this->em); } @@ -36,7 +36,7 @@ public function testCmsModelSet(string $path) self::assertEmpty($this->validator->validateMapping()); } - public function modelSetProvider(): array + public function modelSetProvider() : array { return [ 'cms' => [__DIR__ . '/../../Models/CMS'], @@ -61,7 +61,7 @@ public function testInvalidManyToManyJoinColumnSchema() $this->assertEquals( [ "The inverse join columns of the many-to-many table 'Entity1Entity2' have to contain to ALL identifier columns of the target entity 'Doctrine\Tests\ORM\Tools\InvalidEntity2', however 'key4' are missing.", - "The join columns of the many-to-many table 'Entity1Entity2' have to contain to ALL identifier columns of the source entity 'Doctrine\Tests\ORM\Tools\InvalidEntity1', however 'key2' are missing." + "The join columns of the many-to-many table 'Entity1Entity2' have to contain to ALL identifier columns of the source entity 'Doctrine\Tests\ORM\Tools\InvalidEntity1', however 'key2' are missing.", ], $ce ); @@ -80,7 +80,7 @@ public function testInvalidToOneJoinColumnSchema() $this->assertEquals( [ "The referenced column name 'id' has to be a primary key column on the target entity class 'Doctrine\Tests\ORM\Tools\InvalidEntity1'.", - "The join columns of the association 'assoc' have to match to ALL identifier columns of the target entity 'Doctrine\Tests\ORM\Tools\InvalidEntity1', however 'key1, key2' are missing." + "The join columns of the association 'assoc' have to match to ALL identifier columns of the target entity 'Doctrine\Tests\ORM\Tools\InvalidEntity1', however 'key1, key2' are missing.", ], $ce ); @@ -105,13 +105,15 @@ public function testValidOneToOneAsIdentifierSchema() public function testInvalidTripleAssociationAsKeyMapping() { $classThree = $this->em->getClassMetadata(DDC1649Three::class); - $ce = $this->validator->validateClass($classThree); + $ce = $this->validator->validateClass($classThree); $this->assertEquals( [ - "Cannot map association 'Doctrine\Tests\ORM\Tools\DDC1649Three#two as identifier, because the target entity 'Doctrine\Tests\ORM\Tools\DDC1649Two' also maps an association as identifier.", - "The referenced column name 'id' has to be a primary key column on the target entity class 'Doctrine\Tests\ORM\Tools\DDC1649Two'." - ], $ce); + "Cannot map association 'Doctrine\Tests\ORM\Tools\DDC1649Three#two as identifier, because the target entity 'Doctrine\Tests\ORM\Tools\DDC1649Two' also maps an association as identifier.", + "The referenced column name 'id' has to be a primary key column on the target entity class 'Doctrine\Tests\ORM\Tools\DDC1649Two'.", + ], + $ce + ); } /** @@ -120,13 +122,13 @@ public function testInvalidTripleAssociationAsKeyMapping() public function testInvalidBiDirectionalRelationMappingMissingInversedByAttribute() { $class = $this->em->getClassMetadata(DDC3274One::class); - $ce = $this->validator->validateClass($class); + $ce = $this->validator->validateClass($class); $this->assertEquals( [ - "The field Doctrine\Tests\ORM\Tools\DDC3274One#two is on the inverse side of a bi-directional " . - "relationship, but the specified mappedBy association on the target-entity " . - "Doctrine\Tests\ORM\Tools\DDC3274Two#one does not contain the required 'inversedBy=\"two\"' attribute." + 'The field Doctrine\Tests\ORM\Tools\DDC3274One#two is on the inverse side of a bi-directional ' . + 'relationship, but the specified mappedBy association on the target-entity ' . + "Doctrine\Tests\ORM\Tools\DDC3274Two#one does not contain the required 'inversedBy=\"two\"' attribute.", ], $ce ); @@ -138,12 +140,12 @@ public function testInvalidBiDirectionalRelationMappingMissingInversedByAttribut public function testInvalidOrderByInvalidField() { $class = $this->em->getClassMetadata(DDC3322One::class); - $ce = $this->validator->validateClass($class); + $ce = $this->validator->validateClass($class); $this->assertEquals( [ - "The association Doctrine\Tests\ORM\Tools\DDC3322One#invalidAssoc is ordered by a foreign field " . - "invalidField that is not a field on the target entity Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1." + 'The association Doctrine\Tests\ORM\Tools\DDC3322One#invalidAssoc is ordered by a foreign field ' . + 'invalidField that is not a field on the target entity Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1.', ], $ce ); @@ -155,12 +157,12 @@ public function testInvalidOrderByInvalidField() public function testInvalidOrderByCollectionValuedAssociation() { $class = $this->em->getClassMetadata(DDC3322Two::class); - $ce = $this->validator->validateClass($class); + $ce = $this->validator->validateClass($class); $this->assertEquals( [ - "The association Doctrine\Tests\ORM\Tools\DDC3322Two#invalidAssoc is ordered by a field oneToMany " . - "on Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1 that is a collection-valued association." + 'The association Doctrine\Tests\ORM\Tools\DDC3322Two#invalidAssoc is ordered by a field oneToMany ' . + 'on Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1 that is a collection-valued association.', ], $ce ); @@ -172,16 +174,30 @@ public function testInvalidOrderByCollectionValuedAssociation() public function testInvalidOrderByAssociationInverseSide() { $class = $this->em->getClassMetadata(DDC3322Three::class); - $ce = $this->validator->validateClass($class); + $ce = $this->validator->validateClass($class); $this->assertEquals( [ - "The association Doctrine\Tests\ORM\Tools\DDC3322Three#invalidAssoc is ordered by a field oneToOneInverse " . - "on Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1 that is the inverse side of an association." + 'The association Doctrine\Tests\ORM\Tools\DDC3322Three#invalidAssoc is ordered by a field oneToOneInverse ' . + 'on Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1 that is the inverse side of an association.', ], $ce ); } + + /** + * @group 8052 + */ + public function testInvalidAssociationInsideEmbeddable() + { + $class = $this->em->getClassMetadata(EmbeddableWithAssociation::class); + $ce = $this->validator->validateClass($class); + + $this->assertEquals( + ["Embeddable 'Doctrine\Tests\ORM\Tools\EmbeddableWithAssociation' does not support associations"], + $ce + ); + } } /** @@ -189,13 +205,9 @@ public function testInvalidOrderByAssociationInverseSide() */ class InvalidEntity1 { - /** - * @Id @Column - */ + /** @Id @Column */ protected $key1; - /** - * @Id @Column - */ + /** @Id @Column */ protected $key2; /** * @ManyToMany (targetEntity="InvalidEntity2") @@ -212,19 +224,13 @@ class InvalidEntity1 */ class InvalidEntity2 { - /** - * @Id @Column - */ + /** @Id @Column */ protected $key3; - /** - * @Id @Column - */ + /** @Id @Column */ protected $key4; - /** - * @ManyToOne(targetEntity="InvalidEntity1") - */ + /** @ManyToOne(targetEntity="InvalidEntity1") */ protected $assoc; } @@ -236,7 +242,6 @@ class DDC1587ValidEntity1 { /** * @var int - * * @Id @GeneratedValue * @Column(name="pk", type="integer") */ @@ -244,14 +249,12 @@ class DDC1587ValidEntity1 /** * @var string - * * @Column(name="name", type="string", length=32) */ private $name; /** * @var Identifier - * * @OneToOne(targetEntity="DDC1587ValidEntity2", cascade={"all"}, mappedBy="agent") * @JoinColumn(name="pk", referencedColumnName="pk_agent") */ @@ -266,7 +269,6 @@ class DDC1587ValidEntity2 { /** * @var DDC1587ValidEntity1 - * * @Id * @OneToOne(targetEntity="DDC1587ValidEntity1", inversedBy="identifier") * @JoinColumn(name="pk_agent", referencedColumnName="pk", nullable=false) @@ -275,7 +277,6 @@ class DDC1587ValidEntity2 /** * @var string - * * @Column(name="num", type="string", length=16, nullable=true) */ private $num; @@ -286,9 +287,7 @@ class DDC1587ValidEntity2 */ class DDC1649One { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ public $id; } @@ -316,14 +315,10 @@ class DDC1649Three */ class DDC3274One { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ private $id; - /** - * @OneToMany(targetEntity="DDC3274Two", mappedBy="one") - */ + /** @OneToMany(targetEntity="DDC3274Two", mappedBy="one") */ private $two; } @@ -344,59 +339,37 @@ class DDC3274Two */ class DDC3322ValidEntity1 { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ private $id; - /** - * @ManyToOne(targetEntity="DDC3322One", inversedBy="validAssoc") - */ + /** @ManyToOne(targetEntity="DDC3322One", inversedBy="validAssoc") */ private $oneValid; - /** - * @ManyToOne(targetEntity="DDC3322One", inversedBy="invalidAssoc") - */ + /** @ManyToOne(targetEntity="DDC3322One", inversedBy="invalidAssoc") */ private $oneInvalid; - /** - * @ManyToOne(targetEntity="DDC3322Two", inversedBy="validAssoc") - */ + /** @ManyToOne(targetEntity="DDC3322Two", inversedBy="validAssoc") */ private $twoValid; - /** - * @ManyToOne(targetEntity="DDC3322Two", inversedBy="invalidAssoc") - */ + /** @ManyToOne(targetEntity="DDC3322Two", inversedBy="invalidAssoc") */ private $twoInvalid; - /** - * @ManyToOne(targetEntity="DDC3322Three", inversedBy="validAssoc") - */ + /** @ManyToOne(targetEntity="DDC3322Three", inversedBy="validAssoc") */ private $threeValid; - /** - * @ManyToOne(targetEntity="DDC3322Three", inversedBy="invalidAssoc") - */ + /** @ManyToOne(targetEntity="DDC3322Three", inversedBy="invalidAssoc") */ private $threeInvalid; - /** - * @OneToMany(targetEntity="DDC3322ValidEntity2", mappedBy="manyToOne") - */ + /** @OneToMany(targetEntity="DDC3322ValidEntity2", mappedBy="manyToOne") */ private $oneToMany; - /** - * @ManyToOne(targetEntity="DDC3322ValidEntity2", inversedBy="oneToMany") - */ + /** @ManyToOne(targetEntity="DDC3322ValidEntity2", inversedBy="oneToMany") */ private $manyToOne; - /** - * @OneToOne(targetEntity="DDC3322ValidEntity2", mappedBy="oneToOneOwning") - */ + /** @OneToOne(targetEntity="DDC3322ValidEntity2", mappedBy="oneToOneOwning") */ private $oneToOneInverse; - /** - * @OneToOne(targetEntity="DDC3322ValidEntity2", inversedBy="oneToOneInverse") - */ + /** @OneToOne(targetEntity="DDC3322ValidEntity2", inversedBy="oneToOneInverse") */ private $oneToOneOwning; } @@ -405,29 +378,19 @@ class DDC3322ValidEntity1 */ class DDC3322ValidEntity2 { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ private $id; - /** - * @ManyToOne(targetEntity="DDC3322ValidEntity1", inversedBy="oneToMany") - */ + /** @ManyToOne(targetEntity="DDC3322ValidEntity1", inversedBy="oneToMany") */ private $manyToOne; - /** - * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="manyToOne") - */ + /** @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="manyToOne") */ private $oneToMany; - /** - * @OneToOne(targetEntity="DDC3322ValidEntity1", inversedBy="oneToOneInverse") - */ + /** @OneToOne(targetEntity="DDC3322ValidEntity1", inversedBy="oneToOneInverse") */ private $oneToOneOwning; - /** - * @OneToOne(targetEntity="DDC3322ValidEntity1", mappedBy="oneToOneOwning") - */ + /** @OneToOne(targetEntity="DDC3322ValidEntity1", mappedBy="oneToOneOwning") */ private $oneToOneInverse; } @@ -436,9 +399,7 @@ class DDC3322ValidEntity2 */ class DDC3322One { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ private $id; /** @@ -459,9 +420,7 @@ class DDC3322One */ class DDC3322Two { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ private $id; /** @@ -482,9 +441,7 @@ class DDC3322Two */ class DDC3322Three { - /** - * @Id @Column @GeneratedValue - */ + /** @Id @Column @GeneratedValue */ private $id; /** @@ -499,3 +456,12 @@ class DDC3322Three */ private $invalidAssoc; } + +/** + * @Embeddable + */ +class EmbeddableWithAssociation +{ + /** @OneToOne(targetEntity="Doctrine\Tests\Models\ECommerce\ECommerceCart") */ + private $cart; +}