From 94f5f53d2afe39e96b83754f5f5860c67ed656fe Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Tue, 23 Sep 2014 15:13:57 +0200 Subject: [PATCH] Allow orderBy to reference associations --- lib/Doctrine/ORM/Tools/SchemaValidator.php | 15 +- .../Tests/ORM/Tools/SchemaValidatorTest.php | 212 ++++++++++++++++++ 2 files changed, 225 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/SchemaValidator.php b/lib/Doctrine/ORM/Tools/SchemaValidator.php index 6652e4966..378cbbd9a 100644 --- a/lib/Doctrine/ORM/Tools/SchemaValidator.php +++ b/lib/Doctrine/ORM/Tools/SchemaValidator.php @@ -228,9 +228,20 @@ class SchemaValidator if (isset($assoc['orderBy']) && $assoc['orderBy'] !== null) { foreach ($assoc['orderBy'] as $orderField => $orientation) { - if (!$targetMetadata->hasField($orderField)) { + if (!$targetMetadata->hasField($orderField) && !$targetMetadata->hasAssociation($orderField)) { $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a foreign field " . - $orderField . " that is not a field on the target entity " . $targetMetadata->name; + $orderField . " that is not a field on the target entity " . $targetMetadata->name . "."; + continue; + } + if ($targetMetadata->isCollectionValuedAssociation($orderField)) { + $ce[] = "The association " . $class->name."#".$fieldName." is ordered by an field " . + $orderField . " on " . $targetMetadata->name . " that is a collection-valued association."; + continue; + } + if ($targetMetadata->isAssociationInverseSide($orderField)) { + $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a field " . + $orderField . " on " . $targetMetadata->name . " that is the inverse side of an association."; + continue; } } } diff --git a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php index f36ed162a..2c20b85b1 100644 --- a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php @@ -152,6 +152,57 @@ class SchemaValidatorTest extends \Doctrine\Tests\OrmTestCase $ce ); } + + /** + * @group DDC-3322 + */ + public function testInvalidOrderByInvalidField() + { + $class = $this->em->getClassMetadata(__NAMESPACE__ . '\DDC3322One'); + $ce = $this->validator->validateClass($class); + + $this->assertEquals( + array( + "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 + ); + } + + /** + * @group DDC-3322 + */ + public function testInvalidOrderByCollectionValuedAssociation() + { + $class = $this->em->getClassMetadata(__NAMESPACE__ . '\DDC3322Two'); + $ce = $this->validator->validateClass($class); + + $this->assertEquals( + array( + "The association Doctrine\Tests\ORM\Tools\DDC3322Two#invalidAssoc is ordered by an field oneToMany " . + "on Doctrine\Tests\ORM\Tools\DDC3322ValidEntity1 that is a collection-valued association." + ), + $ce + ); + } + + /** + * @group DDC-3322 + */ + public function testInvalidOrderByAssociationInverseSide() + { + $class = $this->em->getClassMetadata(__NAMESPACE__ . '\DDC3322Three'); + $ce = $this->validator->validateClass($class); + + $this->assertEquals( + array( + "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 + ); + } } /** @@ -308,3 +359,164 @@ class DDC3274Two */ private $one; } + +/** + * @Entity + */ +class DDC3322ValidEntity1 +{ + /** + * @Id @Column @GeneratedValue + */ + private $id; + + /** + * @ManyToOne(targetEntity="DDC3322One", inversedBy="validAssoc") + */ + private $oneValid; + + /** + * @ManyToOne(targetEntity="DDC3322One", inversedBy="invalidAssoc") + */ + private $oneInvalid; + + /** + * @ManyToOne(targetEntity="DDC3322Two", inversedBy="validAssoc") + */ + private $twoValid; + + /** + * @ManyToOne(targetEntity="DDC3322Two", inversedBy="invalidAssoc") + */ + private $twoInvalid; + + /** + * @ManyToOne(targetEntity="DDC3322Three", inversedBy="validAssoc") + */ + private $threeValid; + + /** + * @ManyToOne(targetEntity="DDC3322Three", inversedBy="invalidAssoc") + */ + private $threeInvalid; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity2", mappedBy="manyToOne") + */ + private $oneToMany; + + /** + * @ManyToOne(targetEntity="DDC3322ValidEntity2", inversedBy="oneToMany") + */ + private $manyToOne; + + /** + * @OneToOne(targetEntity="DDC3322ValidEntity2", mappedBy="oneToOneOwning") + */ + private $oneToOneInverse; + + /** + * @OneToOne(targetEntity="DDC3322ValidEntity2", inversedBy="oneToOneInverse") + */ + private $oneToOneOwning; +} + +/** + * @Entity + */ +class DDC3322ValidEntity2 +{ + /** + * @Id @Column @GeneratedValue + */ + private $id; + + /** + * @ManyToOne(targetEntity="DDC3322ValidEntity1", inversedBy="oneToMany") + */ + private $manyToOne; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="manyToOne") + */ + private $oneToMany; + + /** + * @OneToOne(targetEntity="DDC3322ValidEntity1", inversedBy="oneToOneInverse") + */ + private $oneToOneOwning; + + /** + * @OneToOne(targetEntity="DDC3322ValidEntity1", mappedBy="oneToOneOwning") + */ + private $oneToOneInverse; +} + +/** + * @Entity + */ +class DDC3322One +{ + /** + * @Id @Column @GeneratedValue + */ + private $id; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="oneValid") + * @OrderBy({"id" = "ASC"}) + */ + private $validAssoc; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="oneInvalid") + * @OrderBy({"invalidField" = "ASC"}) + */ + private $invalidAssoc; +} + +/** + * @Entity + */ +class DDC3322Two +{ + /** + * @Id @Column @GeneratedValue + */ + private $id; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="twoValid") + * @OrderBy({"manyToOne" = "ASC"}) + */ + private $validAssoc; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="twoInvalid") + * @OrderBy({"oneToMany" = "ASC"}) + */ + private $invalidAssoc; +} + +/** + * @Entity + */ +class DDC3322Three +{ + /** + * @Id @Column @GeneratedValue + */ + private $id; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="threeValid") + * @OrderBy({"oneToOneOwning" = "ASC"}) + */ + private $validAssoc; + + /** + * @OneToMany(targetEntity="DDC3322ValidEntity1", mappedBy="threeInvalid") + * @OrderBy({"oneToOneInverse" = "ASC"}) + */ + private $invalidAssoc; +}