-
-
Save doctrinebot/0462974f72618e031f98 to your computer and use it in GitHub Desktop.
Attachments to Doctrine Jira Issue DDC-166 - https://github.com/doctrine/doctrine2/issues/2303
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php | |
index bf7c6da..f578a22 100644 | |
--- a/lib/Doctrine/ORM/PersistentCollection.php | |
+++ b/lib/Doctrine/ORM/PersistentCollection.php | |
@@ -487,6 +487,11 @@ final class PersistentCollection implements Collection | |
$this->initialize(); | |
$this->coll->set($key, $value); | |
$this->changed(); | |
+ | |
+ if ($this->association !== null && $this->association['type'] == ClassMetadata::ONE_TO_MANY && | |
+ $this->association['orphanRemoval']) { | |
+ $this->em->getUnitOfWork()->unscheduleOrphanRemoval($value); | |
+ } | |
} | |
/** | |
@@ -496,6 +501,12 @@ final class PersistentCollection implements Collection | |
{ | |
$this->coll->add($value); | |
$this->changed(); | |
+ | |
+ if ($this->association !== null && $this->association['type'] == ClassMetadata::ONE_TO_MANY && | |
+ $this->association['orphanRemoval']) { | |
+ $this->em->getUnitOfWork()->unscheduleOrphanRemoval($value); | |
+ } | |
+ | |
return true; | |
} | |
diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php | |
index 76ce521..7e8ac49 100644 | |
--- a/lib/Doctrine/ORM/UnitOfWork.php | |
+++ b/lib/Doctrine/ORM/UnitOfWork.php | |
@@ -1797,6 +1797,20 @@ class UnitOfWork implements PropertyChangedListener | |
{ | |
$this->orphanRemovals[spl_object_hash($entity)] = $entity; | |
} | |
+ | |
+ /** | |
+ * INTERNAL: | |
+ * Unschedules an orphaned entity from removal during flush(). | |
+ * | |
+ * This can happen if an orphan entity is moved from one to another collection. | |
+ * | |
+ * @ignore | |
+ * @param object $entity | |
+ */ | |
+ public function unscheduleOrphanRemoval($entity) | |
+ { | |
+ unset($this->orphanRemovals[spl_object_hash($entity)]); | |
+ } | |
/** | |
* INTERNAL: | |
diff --git a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php | |
index 7a7da0c..35810ee 100644 | |
--- a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php | |
+++ b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php | |
@@ -172,6 +172,37 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase | |
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_phonenumbers")); | |
} | |
+ /** | |
+ * @group DDC-166 | |
+ */ | |
+ public function testReuseOrphanUnschedulesRemoval() | |
+ { | |
+ $user1 = new CmsUser; | |
+ $user1->name = 'Roman'; | |
+ $user1->username = 'romanb'; | |
+ $user1->status = 'developer'; | |
+ | |
+ $phone = new CmsPhonenumber; | |
+ $phone->phonenumber = 100; | |
+ $user1->addPhonenumber($phone); | |
+ | |
+ $user2 = new CmsUser; | |
+ $user2->name = 'Guilherme'; | |
+ $user2->username = 'gblanco'; | |
+ $user2->status = 'developer'; | |
+ $this->_em->persist($user1); | |
+ $this->_em->persist($user2); | |
+ $this->_em->persist($phone); | |
+ $this->_em->flush(); | |
+ | |
+ $user1->getPhonenumbers()->remove(0); // here its scheduled for orphan removal | |
+ $user2->addPhonenumber($phone); // here its reused in another collection | |
+ | |
+ $this->_em->flush(); | |
+ | |
+ $this->assertTrue($this->_em->contains($phone), "The Phonenumber should be contained in the UoW and associated with user2."); | |
+ } | |
+ | |
public function testBasicQuery() | |
{ | |
$user = new CmsUser; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php | |
index bf7c6da..f578a22 100644 | |
--- a/lib/Doctrine/ORM/PersistentCollection.php | |
+++ b/lib/Doctrine/ORM/PersistentCollection.php | |
@@ -487,6 +487,11 @@ final class PersistentCollection implements Collection | |
$this->initialize(); | |
$this->coll->set($key, $value); | |
$this->changed(); | |
+ | |
+ if ($this->association !== null && $this->association['type'] == ClassMetadata::ONE_TO_MANY && | |
+ $this->association['orphanRemoval']) { | |
+ $this->em->getUnitOfWork()->unscheduleOrphanRemoval($value); | |
+ } | |
} | |
/** | |
@@ -496,6 +501,12 @@ final class PersistentCollection implements Collection | |
{ | |
$this->coll->add($value); | |
$this->changed(); | |
+ | |
+ if ($this->association !== null && $this->association['type'] == ClassMetadata::ONE_TO_MANY && | |
+ $this->association['orphanRemoval']) { | |
+ $this->em->getUnitOfWork()->unscheduleOrphanRemoval($value); | |
+ } | |
+ | |
return true; | |
} | |
diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php | |
index 76ce521..a2c4ec1 100644 | |
--- a/lib/Doctrine/ORM/UnitOfWork.php | |
+++ b/lib/Doctrine/ORM/UnitOfWork.php | |
@@ -407,6 +407,13 @@ class UnitOfWork implements PropertyChangedListener | |
} | |
$assoc = $class->associationMappings[$name]; | |
+ | |
+ // unschedule possible orphan removals if entities are reused. | |
+ if ($assoc['type'] == ClassMetadata::ONE_TO_MANY && $assoc['orphanRemoval']) { | |
+ foreach ($value AS $element) { | |
+ unset($this->orphanRemovals[spl_object_hash($element)]); | |
+ } | |
+ } | |
// Inject PersistentCollection | |
$coll = new PersistentCollection( | |
@@ -1797,6 +1804,20 @@ class UnitOfWork implements PropertyChangedListener | |
{ | |
$this->orphanRemovals[spl_object_hash($entity)] = $entity; | |
} | |
+ | |
+ /** | |
+ * INTERNAL: | |
+ * Unschedules an orphaned entity from removal during flush(). | |
+ * | |
+ * This can happen if an orphan entity is moved from one to another collection. | |
+ * | |
+ * @ignore | |
+ * @param object $entity | |
+ */ | |
+ public function unscheduleOrphanRemoval($entity) | |
+ { | |
+ unset($this->orphanRemovals[spl_object_hash($entity)]); | |
+ } | |
/** | |
* INTERNAL: | |
diff --git a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php | |
index 7a7da0c..5b66425 100644 | |
--- a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php | |
+++ b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php | |
@@ -172,6 +172,50 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase | |
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_phonenumbers")); | |
} | |
+ /** | |
+ * @group DDC-166 | |
+ */ | |
+ public function testReuseOrphanUnschedulesRemoval() | |
+ { | |
+ $user1 = new CmsUser; | |
+ $user1->name = 'Roman'; | |
+ $user1->username = 'romanb'; | |
+ $user1->status = 'developer'; | |
+ | |
+ $phone = new CmsPhonenumber; | |
+ $phone->phonenumber = 100; | |
+ $user1->addPhonenumber($phone); | |
+ | |
+ $user2 = new CmsUser; | |
+ $user2->name = 'Guilherme'; | |
+ $user2->username = 'gblanco'; | |
+ $user2->status = 'developer'; | |
+ $this->_em->persist($user1); | |
+ $this->_em->persist($user2); | |
+ $this->_em->persist($phone); | |
+ $this->_em->flush(); | |
+ | |
+ $user1->getPhonenumbers()->remove(0); // here its scheduled for orphan removal | |
+ $user2->addPhonenumber($phone); // here its reused in another collection | |
+ | |
+ $this->_em->flush(); | |
+ | |
+ $this->assertTrue($this->_em->contains($phone), "The Phonenumber should be contained in the UoW and associated with user2."); | |
+ | |
+ $user3 = new CmsUser(); | |
+ $user3->name = "Jonathan"; | |
+ $user3->username = "jwage"; | |
+ $user3->status = 'active'; | |
+ | |
+ $user2->getPhonenumbers()->remove(0); // here its scheduled for orphan removal | |
+ $user3->addPhonenumber($phone); // here it is reused, but NOT descheduled (ArrayCollection) | |
+ | |
+ $this->_em->persist($user3); | |
+ $this->_em->flush(); | |
+ | |
+ $this->assertTrue($this->_em->contains($phone), "The Phonenumber should be contained in the UoW and associated with user3."); | |
+ } | |
+ | |
public function testBasicQuery() | |
{ | |
$user = new CmsUser; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment