diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 99fe9fb5f..3a3f14e59 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2659,7 +2659,10 @@ class UnitOfWork implements PropertyChangedListener $this->entityIdentifiers[$newValueOid] = $associatedId; $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue; - if ($newValue instanceof NotifyPropertyChanged) { + if ( + $newValue instanceof NotifyPropertyChanged && + ( ! $newValue instanceof Proxy || $newValue->__isInitialized()) + ) { $newValue->addPropertyChangedListener($this); } $this->entityStates[$newValueOid] = self::STATE_MANAGED; @@ -3003,7 +3006,7 @@ class UnitOfWork implements PropertyChangedListener $this->addToIdentityMap($entity); - if ($entity instanceof NotifyPropertyChanged) { + if ($entity instanceof NotifyPropertyChanged && ( ! $entity instanceof Proxy || $entity->__isInitialized())) { $entity->addPropertyChangedListener($this); } } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1690Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1690Test.php index ab5d2934a..fd2288eed 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1690Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1690Test.php @@ -50,7 +50,14 @@ class DDC1690Test extends \Doctrine\Tests\OrmFunctionalTestCase $child = $this->_em->find(__NAMESPACE__.'\DDC1690Child', $childId); $this->assertEquals(1, count($parent->listeners)); - $this->assertEquals(1, count($child->listeners)); + $this->assertInstanceOf( + 'Doctrine\\ORM\\Proxy\\Proxy', + $child, + 'Verifying that $child is a proxy before using proxy API' + ); + $this->assertCount(0, $child->listeners); + $child->__load(); + $this->assertCount(1, $child->listeners); unset($parent, $child); $parent = $this->_em->find(__NAMESPACE__.'\DDC1690Parent', $parentId); diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2230Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2230Test.php new file mode 100644 index 000000000..9b69fe50f --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2230Test.php @@ -0,0 +1,102 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2230User'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2230Address'), + )); + } catch (ToolsException $e) {} + } + + public function testNotifyTrackingNotCalledOnUninitializedProxies() + { + $insertedUser = new DDC2230User(); + $insertedUser->address = new DDC2230Address(); + + $this->_em->persist($insertedUser); + $this->_em->persist($insertedUser->address); + $this->_em->flush(); + $this->_em->clear(); + + $user = $this->_em->find(__NAMESPACE__ . '\\DDC2230User', $insertedUser->id); + + $this->_em->clear(); + + $mergedUser = $this->_em->merge($user); + + /* @var $address \Doctrine\Common\Proxy\Proxy */ + $address = $mergedUser->address; + + $this->assertInstanceOf('Doctrine\\ORM\\Proxy\\Proxy', $address); + $this->assertFalse($address->__isInitialized()); + } + + public function testNotifyTrackingCalledOnProxyInitialization() + { + $insertedAddress = new DDC2230Address(); + + $this->_em->persist($insertedAddress); + $this->_em->flush(); + $this->_em->clear(); + + $addressProxy = $this->_em->getReference(__NAMESPACE__ . '\\DDC2230Address', $insertedAddress->id); + + /* @var $addressProxy \Doctrine\Common\Proxy\Proxy|\Doctrine\Tests\ORM\Functional\Ticket\DDC2230Address */ + $this->assertFalse($addressProxy->__isInitialized()); + $this->assertNull($addressProxy->listener); + + $addressProxy->__load(); + + $this->assertSame($this->_em->getUnitOfWork(), $addressProxy->listener); + } +} + +/** @Entity */ +class DDC2230User +{ + /** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */ + public $id; + + /** + * @OneToOne(targetEntity="DDC2230Address") + */ + public $address; +} + +/** + * @Entity + * @ChangeTrackingPolicy("NOTIFY") + */ +class DDC2230Address implements NotifyPropertyChanged +{ + /** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */ + public $id; + + /** + * @var \Doctrine\Common\PropertyChangedListener + */ + public $listener; + + /** {@inheritDoc} */ + function addPropertyChangedListener(PropertyChangedListener $listener) + { + $this->listener = $listener; + } +} +