From a705b81d9beeb0bc73ba916636fca61b6242ccff Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sun, 8 Aug 2010 16:07:40 +0200 Subject: [PATCH] DDC-729 - Fix issue with merging of collections leading to dereference behaviour after next flush(). Added a test for dereferencing of collections as there was none --- lib/Doctrine/ORM/UnitOfWork.php | 18 +++-- .../ManyToManyBasicAssociationTest.php | 12 +++ .../ORM/Functional/Ticket/DDC729Test.php | 80 +++++++++++++++++++ 3 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index dbad60626..874df3ce2 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -1426,13 +1426,17 @@ class UnitOfWork implements PropertyChangedListener continue; } - $coll = new PersistentCollection($this->em, - $this->em->getClassMetadata($assoc2->targetEntityName), - new ArrayCollection - ); - $coll->setOwner($managedCopy, $assoc2); - $coll->setInitialized($assoc2->isCascadeMerge); - $prop->setValue($managedCopy, $coll); + $managedCol = $prop->getValue($managedCopy); + if (!$managedCol) { + $managedCol = new PersistentCollection($this->em, + $this->em->getClassMetadata($assoc2->targetEntityName), + new ArrayCollection + ); + $managedCol->setOwner($managedCopy, $assoc2); + $prop->setValue($managedCopy, $managedCol); + $this->originalEntityData[$oid][$name] = $managedCol; + } + $managedCol->setInitialized($assoc2->isCascadeMerge); } } if ($class->isChangeTrackingNotify()) { diff --git a/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php index efb15d2d9..1fee14767 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php @@ -235,6 +235,18 @@ class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCa $this->assertEquals(0, count($newUser->getGroups())); } + public function testDereferenceCollectionDelete() + { + $user = $this->addCmsUserGblancoWithGroups(2); + $user->groups = null; + + $this->_em->flush(); + $this->_em->clear(); + + $newUser = $this->_em->find(get_class($user), $user->getId()); + $this->assertEquals(0, count($newUser->getGroups())); + } + /** * @param int $groupCount * @return CmsUser diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php new file mode 100644 index 000000000..b63dfdbce --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php @@ -0,0 +1,80 @@ +_em); + $schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC729A'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC729B'), + )); + } catch(\Exception $e) { + + } + } + + public function testMergeManyToMany() + { + $a = new DDC729A(); + $b = new DDC729B(); + $a->related[] = $b; + + $this->_em->persist($a); + $this->_em->persist($b); + $this->_em->flush(); + $this->_em->clear(); + $aId = $a->id; + + $a = new DDC729A(); + $a->id = $aId; + + $this->assertType('Doctrine\Common\Collections\ArrayCollection', $a->related); + + $a = $this->_em->merge($a); + + $this->assertType('Doctrine\ORM\PersistentCollection', $a->related); + + $this->assertFalse($a->related->isInitialized(), "Collection should not be marked initialized."); + $this->assertFalse($a->related->isDirty(), "Collection should not be marked as dirty."); + + $this->_em->flush(); + $this->_em->clear(); + + $a = $this->_em->find(__NAMESPACE__ . '\DDC729A', $aId); + $this->assertEquals(1, count($a->related)); + } +} + +/** + * @Entity + */ +class DDC729A +{ + /** @Id @GeneratedValue @Column(type="integer") */ + public $id; + + /** @ManyToMany(targetEntity="DDC729B") */ + public $related; + + public function __construct() + { + $this->related = new \Doctrine\Common\Collections\ArrayCollection(); + } +} + +/** + * @Entity + */ +class DDC729B +{ + /** @Id @GeneratedValue @Column(type="integer") */ + public $id; +}