diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index a66d7b462..7044ce57e 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2390,17 +2390,8 @@ class UnitOfWork implements PropertyChangedListener $this->visitedCollections = $this->orphanRemovals = array(); } else { - $visited = array(); - - foreach ($this->identityMap as $className => $entities) { - if ($className !== $entityName) { - continue; - } - - foreach ($entities as $entity) { - $this->doDetach($entity, $visited, false); - } - } + $this->clearIdentityMapForEntityName($entityName); + $this->clearEntityInsertionsForEntityName($entityName); } if ($this->evm->hasListeners(Events::onClear)) { @@ -3463,4 +3454,33 @@ class UnitOfWork implements PropertyChangedListener { $this->hydrationCompleteHandler->hydrationComplete(); } + + /** + * @param string $entityName + */ + private function clearIdentityMapForEntityName($entityName) + { + if (! isset($this->identityMap[$entityName])) { + return; + } + + $visited = []; + + foreach ($this->identityMap[$entityName] as $entity) { + $this->doDetach($entity, $visited, false); + } + } + + /** + * @param string $entityName + */ + private function clearEntityInsertionsForEntityName($entityName) + { + foreach ($this->entityInsertions as $hash => $entity) { + // note: performance optimization - `instanceof` is much faster than a function call + if ($entity instanceof $entityName && get_class($entity) === $entityName) { + unset($this->entityInsertions[$hash]); + } + } + } } diff --git a/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php b/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php index eb8bf3a5c..8755a4eaa 100644 --- a/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php @@ -15,6 +15,8 @@ use Doctrine\Tests\Mocks\UnitOfWorkMock; use Doctrine\Tests\Models\CMS\CmsPhonenumber; use Doctrine\Tests\Models\Forum\ForumAvatar; use Doctrine\Tests\Models\Forum\ForumUser; +use Doctrine\Tests\Models\GeoNames\City; +use Doctrine\Tests\Models\GeoNames\Country; use Doctrine\Tests\OrmTestCase; use stdClass; @@ -323,6 +325,28 @@ class UnitOfWorkTest extends OrmTestCase $this->assertTrue($this->_unitOfWork->isInIdentityMap($entity)); } + /** + * @group 5849 + * @group 5850 + */ + public function testPersistedEntityAndClearManager() + { + $entity1 = new City(123, 'London'); + $entity2 = new Country(456, 'United Kingdom'); + + $this->_unitOfWork->persist($entity1); + $this->assertTrue($this->_unitOfWork->isInIdentityMap($entity1)); + + $this->_unitOfWork->persist($entity2); + $this->assertTrue($this->_unitOfWork->isInIdentityMap($entity2)); + + $this->_unitOfWork->clear(Country::class); + $this->assertTrue($this->_unitOfWork->isInIdentityMap($entity1)); + $this->assertFalse($this->_unitOfWork->isInIdentityMap($entity2)); + $this->assertTrue($this->_unitOfWork->isScheduledForInsert($entity1)); + $this->assertFalse($this->_unitOfWork->isScheduledForInsert($entity2)); + } + /** * Data Provider *