[2.0][DDC-136] Some fixes to internal UnitOfWork logic.
This commit is contained in:
parent
57a97eba01
commit
ab0c7b11c8
@ -771,7 +771,14 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
foreach ($this->_entityDeletions as $oid => $entity) {
|
foreach ($this->_entityDeletions as $oid => $entity) {
|
||||||
if (get_class($entity) == $className) {
|
if (get_class($entity) == $className) {
|
||||||
$persister->delete($entity);
|
$persister->delete($entity);
|
||||||
unset($this->_entityDeletions[$oid]);
|
unset(
|
||||||
|
$this->_entityDeletions[$oid],
|
||||||
|
$this->_entityIdentifiers[$oid],
|
||||||
|
$this->_originalEntityData[$oid]
|
||||||
|
);
|
||||||
|
// Entity with this $oid after deletion treated as NEW, even if the $oid
|
||||||
|
// is obtained by a new entity because the old one went out of scope.
|
||||||
|
$this->_entityStates[$oid] = self::STATE_NEW;
|
||||||
|
|
||||||
if ($hasLifecycleCallbacks) {
|
if ($hasLifecycleCallbacks) {
|
||||||
$class->invokeLifecycleCallbacks(Events::postRemove, $entity);
|
$class->invokeLifecycleCallbacks(Events::postRemove, $entity);
|
||||||
@ -919,16 +926,20 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
public function scheduleForDelete($entity)
|
public function scheduleForDelete($entity)
|
||||||
{
|
{
|
||||||
$oid = spl_object_hash($entity);
|
$oid = spl_object_hash($entity);
|
||||||
if ( ! $this->isInIdentityMap($entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->removeFromIdentityMap($entity);
|
|
||||||
|
|
||||||
if (isset($this->_entityInsertions[$oid])) {
|
if (isset($this->_entityInsertions[$oid])) {
|
||||||
|
if ($this->isInIdentityMap($entity)) {
|
||||||
|
$this->removeFromIdentityMap($entity);
|
||||||
|
}
|
||||||
unset($this->_entityInsertions[$oid]);
|
unset($this->_entityInsertions[$oid]);
|
||||||
return; // entity has not been persisted yet, so nothing more to do.
|
return; // entity has not been persisted yet, so nothing more to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! $this->isInIdentityMap($entity)) {
|
||||||
|
return; // ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->removeFromIdentityMap($entity);
|
||||||
|
|
||||||
if (isset($this->_entityUpdates[$oid])) {
|
if (isset($this->_entityUpdates[$oid])) {
|
||||||
unset($this->_entityUpdates[$oid]);
|
unset($this->_entityUpdates[$oid]);
|
||||||
@ -1102,7 +1113,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
if ($idHash === '') {
|
if ($idHash === '') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isset($this->_identityMap[$classMetadata->rootEntityName][$idHash]);
|
return isset($this->_identityMap[$classMetadata->rootEntityName][$idHash]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,9 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertFalse($this->_em->getUnitOfWork()->isScheduledForDelete($user));
|
$this->assertFalse($this->_em->getUnitOfWork()->isScheduledForDelete($user));
|
||||||
$this->assertFalse($this->_em->getUnitOfWork()->isScheduledForDelete($ph));
|
$this->assertFalse($this->_em->getUnitOfWork()->isScheduledForDelete($ph));
|
||||||
$this->assertFalse($this->_em->getUnitOfWork()->isScheduledForDelete($ph2));
|
$this->assertFalse($this->_em->getUnitOfWork()->isScheduledForDelete($ph2));
|
||||||
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
|
||||||
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($ph));
|
||||||
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($ph2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOneToManyAssociationModification()
|
public function testOneToManyAssociationModification()
|
||||||
|
@ -252,5 +252,37 @@ class IdentityMapTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
// Now the collection should be refreshed with correct count
|
// Now the collection should be refreshed with correct count
|
||||||
$this->assertEquals(4, count($user2->getPhonenumbers()));
|
$this->assertEquals(4, count($user2->getPhonenumbers()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testReusedSplObjectHashDoesNotConfuseUnitOfWork()
|
||||||
|
{
|
||||||
|
$hash1 = $this->subRoutine($this->_em);
|
||||||
|
// Make sure cycles are collected NOW, because a PersistentCollection references
|
||||||
|
// its owner, hence without forcing gc on cycles now the object will not (yet)
|
||||||
|
// be garbage collected and thus the object hash is not reused.
|
||||||
|
// This is not a memory leak!
|
||||||
|
gc_collect_cycles();
|
||||||
|
|
||||||
|
$user1 = new CmsUser;
|
||||||
|
$user1->status = 'dev';
|
||||||
|
$user1->username = 'jwage';
|
||||||
|
$user1->name = 'Jonathan W.';
|
||||||
|
$hash2 = spl_object_hash($user1);
|
||||||
|
$this->assertEquals($hash1, $hash2); // Hash reused!
|
||||||
|
$this->_em->persist($user1);
|
||||||
|
$this->_em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function subRoutine($em) {
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->status = 'dev';
|
||||||
|
$user->username = 'romanb';
|
||||||
|
$user->name = 'Roman B.';
|
||||||
|
$em->persist($user);
|
||||||
|
$em->flush();
|
||||||
|
$em->remove($user);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
return spl_object_hash($user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user