From 95193ab5f84a8f2a82c969ae784a7bd049fcefee Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Mon, 31 Oct 2011 21:17:01 +0100 Subject: [PATCH] DDC-1399 - Fix extra lazy collections when inner collection contains values but persistent collection is marked not dirty because of flush() --- lib/Doctrine/ORM/PersistentCollection.php | 46 +++++++++---------- .../Functional/ExtraLazyCollectionTest.php | 32 +++++++++++-- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php index 82d616686..9840bead2 100644 --- a/lib/Doctrine/ORM/PersistentCollection.php +++ b/lib/Doctrine/ORM/PersistentCollection.php @@ -93,21 +93,21 @@ final class PersistentCollection implements Collection /** * Whether the collection has already been initialized. - * + * * @var boolean */ private $initialized = true; - + /** * The wrapped Collection instance. - * + * * @var Collection */ private $coll; /** * Creates a new persistent collection. - * + * * @param EntityManager $em The EntityManager the collection will be associated with. * @param ClassMetadata $class The class descriptor of the entity type of this collection. * @param array The collection elements. @@ -144,7 +144,7 @@ final class PersistentCollection implements Collection { return $this->owner; } - + public function getTypeClass() { return $this->typeClass; @@ -154,7 +154,7 @@ final class PersistentCollection implements Collection * INTERNAL: * Adds an element to a collection during hydration. This will automatically * complete bidirectional associations in the case of a one-to-many association. - * + * * @param mixed $element The element to add. */ public function hydrateAdd($element) @@ -172,7 +172,7 @@ final class PersistentCollection implements Collection $this->owner); } } - + /** * INTERNAL: * Sets a keyed element in the collection during hydration. @@ -271,7 +271,7 @@ final class PersistentCollection implements Collection { return $this->association; } - + /** * Marks this collection as changed/dirty. */ @@ -306,17 +306,17 @@ final class PersistentCollection implements Collection { $this->isDirty = $dirty; } - + /** * Sets the initialized flag of the collection, forcing it into that state. - * + * * @param boolean $bool */ public function setInitialized($bool) { $this->initialized = $bool; } - + /** * Checks whether this collection has been initialized. * @@ -377,7 +377,7 @@ final class PersistentCollection implements Collection $this->em->getUnitOfWork()->getCollectionPersister($this->association) ->deleteRows($this, $element); }*/ - + $this->initialize(); $removed = $this->coll->removeElement($element); if ($removed) { @@ -410,7 +410,7 @@ final class PersistentCollection implements Collection ->getCollectionPersister($this->association) ->contains($this, $element); } - + $this->initialize(); return $this->coll->contains($element); } @@ -468,7 +468,7 @@ final class PersistentCollection implements Collection if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) { return $this->em->getUnitOfWork() ->getCollectionPersister($this->association) - ->count($this) + $this->coll->count(); + ->count($this) + ($this->isDirty ? $this->coll->count() : 0); } $this->initialize(); @@ -503,7 +503,7 @@ final class PersistentCollection implements Collection $this->initialize(); return $this->coll->isEmpty(); } - + /** * {@inheritdoc} */ @@ -530,7 +530,7 @@ final class PersistentCollection implements Collection $this->initialize(); return $this->coll->filter($p); } - + /** * {@inheritdoc} */ @@ -548,7 +548,7 @@ final class PersistentCollection implements Collection $this->initialize(); return $this->coll->partition($p); } - + /** * {@inheritdoc} */ @@ -579,7 +579,7 @@ final class PersistentCollection implements Collection $this->takeSnapshot(); } } - + /** * Called by PHP when this collection is serialized. Ensures that only the * elements are properly serialized. @@ -591,7 +591,7 @@ final class PersistentCollection implements Collection { return array('coll', 'initialized'); } - + /* ArrayAccess implementation */ /** @@ -629,12 +629,12 @@ final class PersistentCollection implements Collection { return $this->remove($offset); } - + public function key() { return $this->coll->key(); } - + /** * Gets the element of the collection at the current iterator position. */ @@ -642,7 +642,7 @@ final class PersistentCollection implements Collection { return $this->coll->current(); } - + /** * Moves the internal iterator position to the next element. */ @@ -650,7 +650,7 @@ final class PersistentCollection implements Collection { return $this->coll->next(); } - + /** * Retrieves the wrapped Collection instance. */ diff --git a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php index 4bf010602..43b45650f 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php @@ -29,7 +29,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup'); $class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY; - + $this->loadFixture(); } @@ -137,9 +137,9 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase { $user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId); $this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized."); - + $queryCount = $this->getCurrentQueryCount(); - + $someGroups = $user->groups->slice(0, 2); $this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsGroup', $someGroups); @@ -225,7 +225,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertFalse($user->articles->isInitialized(), "Pre-Condition: Collection is not initialized."); $article = $this->_em->find('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId); - + $queryCount = $this->getCurrentQueryCount(); $this->assertTrue($user->articles->contains($article)); $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized."); @@ -304,6 +304,28 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized."); } + /** + * @group DDC-1399 + */ + public function testCountAfterAddThenFlush() + { + $user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId); + + $newGroup = new \Doctrine\Tests\Models\CMS\CmsGroup(); + $newGroup->name = "Test4"; + + $user->addGroup($newGroup); + $this->_em->persist($newGroup); + + $this->assertFalse($user->groups->isInitialized()); + $this->assertEquals(4, count($user->groups)); + $this->assertFalse($user->groups->isInitialized()); + + $this->_em->flush(); + + $this->assertEquals(4, count($user->groups)); + } + private function loadFixture() { $user1 = new \Doctrine\Tests\Models\CMS\CmsUser(); @@ -364,7 +386,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->persist($article1); $this->_em->persist($article2); - + $this->_em->flush(); $this->_em->clear();