diff --git a/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php index e6662b799..ee67a3502 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php @@ -142,6 +142,9 @@ abstract class AbstractHydrator $this->_rsm = $resultSetMapping; $this->_hints = $hints; + $evm = $this->_em->getEventManager(); + $evm->addEventListener(array(Events::onClear), $this); + $this->prepare(); $result = $this->hydrateAllData(); diff --git a/tests/Doctrine/Tests/ORM/Hydration/AbstractHydratorTest.php b/tests/Doctrine/Tests/ORM/Hydration/AbstractHydratorTest.php new file mode 100644 index 000000000..1d02b6c2b --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Hydration/AbstractHydratorTest.php @@ -0,0 +1,68 @@ +<?php + +namespace Doctrine\Tests\ORM\Functional\Ticket; + +use Doctrine\DBAL\Connection; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\Common\EventManager; +use Doctrine\DBAL\Driver\Statement; +use Doctrine\ORM\Events; +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\Internal\Hydration\AbstractHydrator; +use Doctrine\Tests\OrmFunctionalTestCase; + +/** + * @covers \Doctrine\ORM\Internal\Hydration\AbstractHydrator + */ +class AbstractHydratorTest extends OrmFunctionalTestCase +{ + /** + * @group DDC-3146 + * @group #1515 + * + * Verify that the number of added events to the event listener from the abstract hydrator class is equal to the + * number of removed events + */ + public function testOnClearEventListenerIsDetachedOnCleanup() + { + $mockConnection = $this->createMock(Connection::class); + $mockEntityManagerInterface = $this->createMock(EntityManagerInterface::class); + $mockEventManager = $this->createMock(EventManager::class); + $mockStatement = $this->createMock(Statement::class); + $mockResultMapping = $this->getMockBuilder(ResultSetMapping::class); + + $mockEntityManagerInterface->expects(self::any())->method('getEventManager')->willReturn($mockEventManager); + $mockEntityManagerInterface->expects(self::any())->method('getConnection')->willReturn($mockConnection); + $mockStatement->expects(self::once())->method('fetch')->willReturn(false); + + /* @var $mockAbstractHydrator AbstractHydrator */ + $mockAbstractHydrator = $this + ->getMockBuilder(AbstractHydrator::class) + ->setConstructorArgs([$mockEntityManagerInterface]) + ->setMethods(['hydrateAllData']) + ->getMock(); + + $mockEventManager + ->expects(self::at(0)) + ->method('addEventListener') + ->with([Events::onClear], $mockAbstractHydrator); + + $mockEventManager + ->expects(self::at(1)) + ->method('removeEventListener') + ->with([Events::onClear], $mockAbstractHydrator); + + $mockEventManager + ->expects(self::at(2)) + ->method('addEventListener') + ->with([Events::onClear], $mockAbstractHydrator); + + $mockEventManager + ->expects(self::at(3)) + ->method('removeEventListener') + ->with([Events::onClear], $mockAbstractHydrator); + + iterator_to_array($mockAbstractHydrator->iterate($mockStatement, $mockResultMapping)); + $mockAbstractHydrator->hydrateAll($mockStatement, $mockResultMapping); + } +}