From 07c207081e16e07b7bd574528427212194d871a3 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 9 May 2013 21:11:10 +0200 Subject: [PATCH 1/2] Adding failing test to demonstrate DDC-2432 Loading proxies with invalid identifiers will currently mark them as initialized regardless of the failure --- .../Tests/ORM/Proxy/ProxyFactoryTest.php | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/Doctrine/Tests/ORM/Proxy/ProxyFactoryTest.php b/tests/Doctrine/Tests/ORM/Proxy/ProxyFactoryTest.php index 90f1d7ef7..d91a3f2b5 100644 --- a/tests/Doctrine/Tests/ORM/Proxy/ProxyFactoryTest.php +++ b/tests/Doctrine/Tests/ORM/Proxy/ProxyFactoryTest.php @@ -2,6 +2,7 @@ namespace Doctrine\Tests\ORM\Proxy; +use Doctrine\ORM\EntityNotFoundException; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Proxy\ProxyFactory; use Doctrine\Common\Proxy\ProxyGenerator; @@ -80,6 +81,60 @@ class ProxyFactoryTest extends \Doctrine\Tests\OrmTestCase $this->assertEquals(0, $num, "No proxies generated."); } + + /** + * @group DDC-2432 + */ + public function testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized() + { + $persister = $this->getMock('Doctrine\ORM\Persisters\BasicEntityPersister', array('load'), array(), '', false); + $this->uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister); + + /* @var $proxy \Doctrine\Common\Proxy\Proxy */ + $proxy = $this->proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', array('id' => 42)); + + $persister + ->expects($this->atLeastOnce()) + ->method('load') + ->will($this->returnValue(null)); + + try { + $proxy->getDescription(); + $this->fail('An exception was expected to be raised'); + } catch (EntityNotFoundException $exception) { + } + + $this->assertFalse($proxy->__isInitialized()); + $this->assertInstanceOf('Closure', $proxy->__getInitializer(), 'The initializer wasn\'t removed'); + $this->assertInstanceOf('Closure', $proxy->__getCloner(), 'The cloner wasn\'t removed'); + } + + /** + * @group DDC-2432 + */ + public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized() + { + $persister = $this->getMock('Doctrine\ORM\Persisters\BasicEntityPersister', array('load'), array(), '', false); + $this->uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister); + + /* @var $proxy \Doctrine\Common\Proxy\Proxy */ + $proxy = $this->proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', array('id' => 42)); + + $persister + ->expects($this->atLeastOnce()) + ->method('load') + ->will($this->returnValue(null)); + + try { + $cloned = clone $proxy; + $this->fail('An exception was expected to be raised'); + } catch (EntityNotFoundException $exception) { + } + + $this->assertFalse($proxy->__isInitialized()); + $this->assertInstanceOf('Closure', $proxy->__getInitializer(), 'The initializer wasn\'t removed'); + $this->assertInstanceOf('Closure', $proxy->__getCloner(), 'The cloner wasn\'t removed'); + } } abstract class AbstractClass From 22c9f6ebec3dbfe7395760da824ab50cce0f2a7d Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 9 May 2013 21:14:58 +0200 Subject: [PATCH 2/2] applying required fixes for DDC-2432 --- lib/Doctrine/ORM/Proxy/ProxyFactory.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/Doctrine/ORM/Proxy/ProxyFactory.php b/lib/Doctrine/ORM/Proxy/ProxyFactory.php index c8964804e..dfac9a3e7 100644 --- a/lib/Doctrine/ORM/Proxy/ProxyFactory.php +++ b/lib/Doctrine/ORM/Proxy/ProxyFactory.php @@ -117,6 +117,9 @@ class ProxyFactory extends AbstractProxyFactory { if ($classMetadata->getReflectionClass()->hasMethod('__wakeup')) { return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) { + $initializer = $proxy->__getInitializer(); + $cloner = $proxy->__getCloner(); + $proxy->__setInitializer(null); $proxy->__setCloner(null); @@ -136,12 +139,19 @@ class ProxyFactory extends AbstractProxyFactory $proxy->__wakeup(); if (null === $entityPersister->load($classMetadata->getIdentifierValues($proxy), $proxy)) { + $proxy->__setInitializer($initializer); + $proxy->__setCloner($cloner); + $proxy->__setInitialized(false); + throw new EntityNotFoundException(); } }; } return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) { + $initializer = $proxy->__getInitializer(); + $cloner = $proxy->__getCloner(); + $proxy->__setInitializer(null); $proxy->__setCloner(null); @@ -160,6 +170,10 @@ class ProxyFactory extends AbstractProxyFactory $proxy->__setInitialized(true); if (null === $entityPersister->load($classMetadata->getIdentifierValues($proxy), $proxy)) { + $proxy->__setInitializer($initializer); + $proxy->__setCloner($cloner); + $proxy->__setInitialized(false); + throw new EntityNotFoundException(); } };