From ff115efbacc60a48da41645656a2fe9723c97b06 Mon Sep 17 00:00:00 2001 From: piccoloprincipe Date: Mon, 6 Jul 2009 12:18:04 +0000 Subject: [PATCH] added many-many self referential functional tests (affects #2276) --- .../Models/ECommerce/ECommerceProduct.php | 32 +++++ .../Tests/ORM/Functional/AllTests.php | 1 + ...nyToManySelfReferentialAssociationTest.php | 111 ++++++++++++++++++ .../Doctrine/Tests/OrmFunctionalTestCase.php | 1 + 4 files changed, 145 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php diff --git a/tests/Doctrine/Tests/Models/ECommerce/ECommerceProduct.php b/tests/Doctrine/Tests/Models/ECommerce/ECommerceProduct.php index 0094d7969..db0eff3d7 100644 --- a/tests/Doctrine/Tests/Models/ECommerce/ECommerceProduct.php +++ b/tests/Doctrine/Tests/Models/ECommerce/ECommerceProduct.php @@ -45,10 +45,21 @@ class ECommerceProduct */ private $categories; + /** + * This relation is saved with two records in the association table for + * simplicity. + * @ManyToMany(targetEntity="ECommerceProduct", cascade={"save"}) + * @JoinTable(name="ecommerce_products_related", + joinColumns={{"name"="product_id", "referencedColumnName"="id"}}, + inverseJoinColumns={{"name"="related_id", "referencedColumnName"="id"}}) + */ + private $related; + public function __construct() { $this->features = new Collection; $this->categories = new Collection; + $this->related = new Collection; } public function getId() @@ -128,4 +139,25 @@ class ECommerceProduct { return $this->categories; } + + public function getRelated() + { + return $this->related; + } + + public function addRelated(ECommerceProduct $related) + { + if (!$this->related->contains($related)) { + $this->related[] = $related; + $related->addRelated($this); + } + } + + public function removeRelated(ECommerceProduct $related) + { + $removed = $this->related->removeElement($related); + if ($removed) { + $related->removeRelated($this); + } + } } diff --git a/tests/Doctrine/Tests/ORM/Functional/AllTests.php b/tests/Doctrine/Tests/ORM/Functional/AllTests.php index 3a0a3e208..d792293ed 100644 --- a/tests/Doctrine/Tests/ORM/Functional/AllTests.php +++ b/tests/Doctrine/Tests/ORM/Functional/AllTests.php @@ -32,6 +32,7 @@ class AllTests $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManyUnidirectionalAssociationTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManyBidirectionalAssociationTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToManySelfReferentialAssociationTest'); + $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManySelfReferentialAssociationTest'); return $suite; } diff --git a/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php new file mode 100644 index 000000000..36a62c499 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php @@ -0,0 +1,111 @@ +useModelSet('ecommerce'); + parent::setUp(); + $this->firstProduct = new ECommerceProduct(); + $this->secondProduct = new ECommerceProduct(); + $this->firstRelated = new ECommerceProduct(); + $this->firstRelated->setName("Business"); + $this->secondRelated = new ECommerceProduct(); + $this->secondRelated->setName("Home"); + } + + public function testSavesAManyToManyAssociationWithCascadeSaveSet() + { + $this->firstProduct->addRelated($this->firstRelated); + $this->firstProduct->addRelated($this->secondRelated); + $this->_em->save($this->firstProduct); + $this->_em->flush(); + + $this->assertForeignKeysContain($this->firstProduct->getId(), + $this->firstRelated->getId()); + $this->assertForeignKeysContain($this->firstProduct->getId(), + $this->secondRelated->getId()); + } + + public function testRemovesAManyToManyAssociation() + { + $this->firstProduct->addRelated($this->firstRelated); + $this->firstProduct->addRelated($this->secondRelated); + $this->_em->save($this->firstProduct); + $this->firstProduct->removeRelated($this->firstRelated); + + $this->_em->flush(); + + $this->assertForeignKeysNotContain($this->firstProduct->getId(), + $this->firstRelated->getId()); + $this->assertForeignKeysContain($this->firstProduct->getId(), + $this->secondRelated->getId()); + } + + public function testEagerLoadsOwningSide() + { + $this->_createLoadingFixture(); + list ($firstProduct, $secondProduct) = $this->_findProducts(); + + $this->assertEquals(2, count($firstProduct->getRelated())); + $this->assertEquals(2, count($secondProduct->getRelated())); + + $categories = $firstProduct->getRelated(); + $firstRelatedBy = $categories[0]->getRelated(); + $secondRelatedBy = $categories[1]->getRelated(); + + $this->assertEquals(2, count($firstRelatedBy)); + $this->assertEquals(2, count($secondRelatedBy)); + + $this->assertTrue($firstRelatedBy[0] instanceof ECommerceProduct); + $this->assertTrue($firstRelatedBy[1] instanceof ECommerceProduct); + $this->assertTrue($secondRelatedBy[0] instanceof ECommerceProduct); + $this->assertTrue($secondRelatedBy[1] instanceof ECommerceProduct); + + $this->assertCollectionEquals($firstRelatedBy, $secondRelatedBy); + } + + protected function _createLoadingFixture() + { + $this->firstProduct->addRelated($this->firstRelated); + $this->firstProduct->addRelated($this->secondRelated); + $this->secondProduct->addRelated($this->firstRelated); + $this->secondProduct->addRelated($this->secondRelated); + $this->_em->save($this->firstProduct); + $this->_em->save($this->secondProduct); + + $this->_em->flush(); + $this->_em->clear(); + } + + protected function _findProducts() + { + $query = $this->_em->createQuery('SELECT p, r FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p LEFT JOIN p.related r ORDER BY p.id, r.id'); + return $query->getResultList(); + } + + /* TODO: not yet implemented + public function testLazyLoad() { + + }*/ +} diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 1ebff721e..694f8dd64 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -85,6 +85,7 @@ class OrmFunctionalTestCase extends OrmTestCase $conn->exec('DELETE FROM ecommerce_features'); $conn->exec('DELETE FROM ecommerce_categories'); $conn->exec('DELETE FROM ecommerce_products_categories'); + $conn->exec('DELETE FROM ecommerce_products_related'); } if (isset($this->_usedModelSets['company'])) { $conn->exec('DELETE FROM company_persons_friends');