Merge branch 'DDC-758'
This commit is contained in:
commit
4804f623c1
@ -196,7 +196,7 @@ final class PersistentCollection implements Collection
|
||||
* Initializes the collection by loading its contents from the database
|
||||
* if the collection is not yet initialized.
|
||||
*/
|
||||
private function initialize()
|
||||
public function initialize()
|
||||
{
|
||||
if ( ! $this->initialized && $this->association) {
|
||||
if ($this->isDirty) {
|
||||
|
@ -1437,7 +1437,17 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$prop->setValue($managedCopy, $managedCol);
|
||||
$this->originalEntityData[$oid][$name] = $managedCol;
|
||||
}
|
||||
$managedCol->setInitialized($assoc2['isCascadeMerge']);
|
||||
if ($assoc2['isCascadeMerge']) {
|
||||
$managedCol->initialize();
|
||||
$managedCol->takeSnapshot();
|
||||
if (!$managedCol->isEmpty()) {
|
||||
$managedCol->unwrap()->clear();
|
||||
$managedCol->setDirty(true);
|
||||
if ($assoc2['isOwningSide'] && $assoc2['type'] == ClassMetadata::MANY_TO_MANY && $class->isChangeTrackingNotify()) {
|
||||
$this->scheduleForDirtyCheck($managedCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($class->isChangeTrackingNotify()) {
|
||||
@ -1456,7 +1466,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ($assoc['type'] & ClassMetadata::TO_ONE) {
|
||||
$prevClass->reflFields[$assocField]->setValue($prevManagedCopy, $managedCopy);
|
||||
} else {
|
||||
$prevClass->reflFields[$assocField]->getValue($prevManagedCopy)->unwrap()->add($managedCopy);
|
||||
$prevClass->reflFields[$assocField]->getValue($prevManagedCopy)->add($managedCopy);
|
||||
if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
|
||||
$class->reflFields[$assoc['mappedBy']]->setValue($managedCopy, $prevManagedCopy);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class DetachedEntityTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$user->status = 'developer';
|
||||
|
||||
$ph1 = new CmsPhonenumber;
|
||||
$ph1->phonenumber = 1234;
|
||||
$ph1->phonenumber = "1234";
|
||||
$user->addPhonenumber($ph1);
|
||||
|
||||
$this->_em->persist($user);
|
||||
@ -68,24 +68,36 @@ class DetachedEntityTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
unset($user);
|
||||
|
||||
$user = unserialize($serialized);
|
||||
|
||||
$this->assertEquals(1, count($user->getPhonenumbers()), "Pre-Condition: 1 Phonenumber");
|
||||
|
||||
$ph2 = new CmsPhonenumber;
|
||||
$ph2->phonenumber = 56789;
|
||||
$ph2->phonenumber = "56789";
|
||||
$user->addPhonenumber($ph2);
|
||||
$this->assertEquals(2, count($user->getPhonenumbers()));
|
||||
$oldPhonenumbers = $user->getPhonenumbers();
|
||||
$this->assertEquals(2, count($oldPhonenumbers), "Pre-Condition: 2 Phonenumbers");
|
||||
$this->assertFalse($this->_em->contains($user));
|
||||
|
||||
$this->_em->persist($ph2);
|
||||
|
||||
|
||||
// Merge back in
|
||||
$user = $this->_em->merge($user); // merge cascaded to phonenumbers
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsUser', $user->phonenumbers[0]->user);
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsUser', $user->phonenumbers[1]->user);
|
||||
$im = $this->_em->getUnitOfWork()->getIdentityMap();
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertTrue($this->_em->contains($user));
|
||||
$this->assertEquals(2, count($user->getPhonenumbers()));
|
||||
$this->assertTrue($this->_em->contains($user), "Failed to assert that merged user is contained inside EntityManager persistence context.");
|
||||
$phonenumbers = $user->getPhonenumbers();
|
||||
$this->assertTrue($this->_em->contains($phonenumbers[0]));
|
||||
$this->assertTrue($this->_em->contains($phonenumbers[1]));
|
||||
$this->assertNotSame($oldPhonenumbers, $phonenumbers, "Merge should replace the Detached Collection with a new PersistentCollection.");
|
||||
$this->assertEquals(2, count($phonenumbers), "Failed to assert that two phonenumbers are contained in the merged users phonenumber collection.");
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsPhonenumber', $phonenumbers[1]);
|
||||
$this->assertTrue($this->_em->contains($phonenumbers[1]), "Failed to assert that second phonenumber in collection is contained inside EntityManager persistence context.");
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsPhonenumber', $phonenumbers[0]);
|
||||
$this->assertTrue($this->_em->getUnitOfWork()->isInIdentityMap($phonenumbers[0]));
|
||||
$this->assertTrue($this->_em->contains($phonenumbers[0]), "Failed to assert that first phonenumber in collection is contained inside EntityManager persistence context.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
184
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC758Test.php
Normal file
184
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC758Test.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
use Doctrine\Tests\Models\CMS\CmsGroup;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class DDC758Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet("cms");
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set cascade to merge only
|
||||
*/
|
||||
private function setCascadeMergeFor($class)
|
||||
{
|
||||
$metadata = $this->_em->getMetadataFactory()->getMetaDataFor($class);
|
||||
foreach ($metadata->associationMappings as $key => $associationMapping) {
|
||||
$metadata->associationMappings[$key]["isCascadePersist"] = false;
|
||||
$metadata->associationMappings[$key]["isCascadeMerge"] = true;
|
||||
$metadata->associationMappings[$key]["isCascadeRemove"] = false;
|
||||
$metadata->associationMappings[$key]["isCascadeDetach"] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that changing associations on detached entities and then cascade merging them
|
||||
* causes the database to be updated with the new associations.
|
||||
* This specifically tests adding new associations.
|
||||
*/
|
||||
public function testManyToManyMergeAssociationAdds()
|
||||
{
|
||||
$this->setCascadeMergeFor('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$this->setCascadeMergeFor('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||
|
||||
// Put entities in the database
|
||||
$cmsUser = new CmsUser();
|
||||
$cmsUser->username = "dave";
|
||||
$cmsUser->name = "Dave Keen";
|
||||
$cmsUser->status = "testing";
|
||||
|
||||
$group1 = new CmsGroup();
|
||||
$group1->name = "Group 1";
|
||||
|
||||
$group2 = new CmsGroup();
|
||||
$group2->name = "Group 2";
|
||||
|
||||
$this->_em->persist($cmsUser);
|
||||
$this->_em->persist($group1);
|
||||
$this->_em->persist($group2);
|
||||
$this->_em->flush();
|
||||
|
||||
$cmsUserId = $cmsUser->id;
|
||||
$group1Id = $group1->id;
|
||||
$group2Id = $group2->id;
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
// Now create detached versions of the entities with some new associations.
|
||||
$cmsUser = new CmsUser();
|
||||
$cmsUser->id = $cmsUserId;
|
||||
$cmsUser->username = "dave";
|
||||
$cmsUser->name = "Dave Keen";
|
||||
$cmsUser->status = "testing";
|
||||
$cmsUser->groups = new ArrayCollection();
|
||||
|
||||
$group1 = new CmsGroup();
|
||||
$group1->id = $group1Id;
|
||||
$group1->name = "Group 1";
|
||||
$group1->users = new ArrayCollection();
|
||||
|
||||
$group2 = new CmsGroup();
|
||||
$group2->id = $group2Id;
|
||||
$group2->name = "Group 2";
|
||||
$group2->users = new ArrayCollection();
|
||||
|
||||
$cmsUser->addGroup($group1);
|
||||
$cmsUser->addGroup($group2);
|
||||
|
||||
// Cascade merge of cmsUser followed by a flush should add in the birectional new many-to-many associations between the user and the groups
|
||||
$this->_em->merge($cmsUser);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$cmsUsers = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findAll();
|
||||
$cmsGroups = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsGroup')->findAll();
|
||||
|
||||
// Check the entities are in the database
|
||||
$this->assertEquals(1, sizeof($cmsUsers));
|
||||
$this->assertEquals(2, sizeof($cmsGroups));
|
||||
|
||||
// Check the associations between the entities are now in the database
|
||||
$this->assertEquals(2, sizeof($cmsUsers[0]->groups));
|
||||
$this->assertEquals(1, sizeof($cmsGroups[0]->users));
|
||||
$this->assertEquals(1, sizeof($cmsGroups[1]->users));
|
||||
|
||||
$this->assertSame($cmsUsers[0]->groups[0], $cmsGroups[0]);
|
||||
$this->assertSame($cmsUsers[0]->groups[1], $cmsGroups[1]);
|
||||
$this->assertSame($cmsGroups[0]->users[0], $cmsUsers[0]);
|
||||
$this->assertSame($cmsGroups[1]->users[0], $cmsUsers[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that changing associations on detached entities and then cascade merging them causes the
|
||||
* database to be updated with the new associations.
|
||||
*/
|
||||
public function testManyToManyMergeAssociationRemoves()
|
||||
{
|
||||
$this->setCascadeMergeFor('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$this->setCascadeMergeFor('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||
|
||||
$cmsUser = new CmsUser();
|
||||
$cmsUser->username = "dave";
|
||||
$cmsUser->name = "Dave Keen";
|
||||
$cmsUser->status = "testing";
|
||||
|
||||
$group1 = new CmsGroup();
|
||||
$group1->name = "Group 1";
|
||||
|
||||
$group2 = new CmsGroup();
|
||||
$group2->name = "Group 2";
|
||||
|
||||
$cmsUser->addGroup($group1);
|
||||
$cmsUser->addGroup($group2);
|
||||
|
||||
$this->_em->persist($cmsUser);
|
||||
$this->_em->persist($group1);
|
||||
$this->_em->persist($group2);
|
||||
$this->_em->flush();
|
||||
|
||||
$cmsUserId = $cmsUser->id;
|
||||
$group1Id = $group1->id;
|
||||
$group2Id = $group2->id;
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
// Now create detached versions of the entities with NO associations.
|
||||
$cmsUser = new CmsUser();
|
||||
$cmsUser->id = $cmsUserId;
|
||||
$cmsUser->username = "dave";
|
||||
$cmsUser->name = "Dave Keen";
|
||||
$cmsUser->status = "testing";
|
||||
$cmsUser->groups = new ArrayCollection();
|
||||
|
||||
$group1 = new CmsGroup();
|
||||
$group1->id = $group1Id;
|
||||
$group1->name = "Group 1";
|
||||
$group1->users = new ArrayCollection();
|
||||
|
||||
$group2 = new CmsGroup();
|
||||
$group2->id = $group2Id;
|
||||
$group2->name = "Group 2";
|
||||
$group2->users = new ArrayCollection();
|
||||
|
||||
// Cascade merge of cmsUser followed by a flush should result in the association array collection being empty
|
||||
$this->_em->merge($cmsUser);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$cmsUsers = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findAll();
|
||||
$cmsGroups = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsGroup')->findAll();
|
||||
|
||||
// Check the entities are in the database
|
||||
$this->assertEquals(1, sizeof($cmsUsers));
|
||||
$this->assertEquals(2, sizeof($cmsGroups));
|
||||
|
||||
// Check the associations between the entities are now in the database
|
||||
$this->assertEquals(0, sizeof($cmsUsers[0]->groups));
|
||||
$this->assertEquals(0, sizeof($cmsGroups[0]->users));
|
||||
$this->assertEquals(0, sizeof($cmsGroups[1]->users));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user