Commit 38bf6c66 authored by romanb's avatar romanb

[2.0][DDC-237][DDC-216] Fixed. If you're using manual proxy generation through...

[2.0][DDC-237][DDC-216] Fixed. If you're using manual proxy generation through the CLI, please regenerate your proxies.
parent 0a7727e1
...@@ -571,6 +571,15 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect ...@@ -571,6 +571,15 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
$this->_initialize(); $this->_initialize();
return $this->_coll->partition($p); return $this->_coll->partition($p);
} }
/**
* {@inheritdoc}
*/
public function toArray()
{
$this->_initialize();
return $this->_coll->toArray();
}
/** /**
* {@inheritdoc} * {@inheritdoc}
...@@ -637,11 +646,6 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect ...@@ -637,11 +646,6 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect
return $this->remove($offset); return $this->remove($offset);
} }
public function toArray()
{
return $this->_coll->toArray();
}
public function key() public function key()
{ {
return $this->_coll->key(); return $this->_coll->key();
......
...@@ -27,7 +27,4 @@ namespace Doctrine\ORM\Proxy; ...@@ -27,7 +27,4 @@ namespace Doctrine\ORM\Proxy;
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @since 2.0 * @since 2.0
*/ */
interface Proxy interface Proxy {}
{ \ No newline at end of file
function __isInitialized__();
}
\ No newline at end of file
...@@ -253,26 +253,25 @@ namespace <namespace> { ...@@ -253,26 +253,25 @@ namespace <namespace> {
class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy { class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy {
private $_entityPersister; private $_entityPersister;
private $_identifier; private $_identifier;
private $_loaded = false; public $__isInitialized__ = false;
public function __construct($entityPersister, $identifier) { public function __construct($entityPersister, $identifier) {
$this->_entityPersister = $entityPersister; $this->_entityPersister = $entityPersister;
$this->_identifier = $identifier; $this->_identifier = $identifier;
<constructorInvocation> <constructorInvocation>
} }
private function _load() { private function _load() {
if ( ! $this->_loaded) { if (!$this->__isInitialized__) {
$this->_loaded = true; $this->__isInitialized__ = true;
$this->_entityPersister->load($this->_identifier, $this); $this->_entityPersister->load($this->_identifier, $this);
unset($this->_entityPersister); unset($this->_entityPersister);
unset($this->_identifier); unset($this->_identifier);
} }
} }
public function __isInitialized__() { return $this->_loaded; }
<methods> <methods>
public function __sleep() { public function __sleep() {
if (!$this->_loaded) { if (!$this->__isInitialized__) {
throw new \RuntimeException("Not fully loaded proxy can not be serialized."); throw new \RuntimeException("Not fully loaded proxy can not be serialized.");
} }
<sleepImpl> <sleepImpl>
......
...@@ -38,8 +38,7 @@ use Doctrine\Common\Collections\ArrayCollection, ...@@ -38,8 +38,7 @@ use Doctrine\Common\Collections\ArrayCollection,
* @since 2.0 * @since 2.0
* @version $Revision$ * @version $Revision$
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @internal This class contains performance-critical code. Work with care and * @internal This class contains performance-critical code.
* regularly run the ORM performance tests.
*/ */
class UnitOfWork implements PropertyChangedListener class UnitOfWork implements PropertyChangedListener
{ {
...@@ -401,7 +400,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -401,7 +400,7 @@ class UnitOfWork implements PropertyChangedListener
foreach ($entitiesToProcess as $entity) { foreach ($entitiesToProcess as $entity) {
// Ignore uninitialized proxy objects // Ignore uninitialized proxy objects
if (/* $entity is readOnly || */ $entity instanceof Proxy && ! $entity->__isInitialized__()) { if (/* $entity is readOnly || */ $entity instanceof Proxy && ! $entity->__isInitialized__) {
continue; continue;
} }
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here. // Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here.
...@@ -560,7 +559,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -560,7 +559,7 @@ class UnitOfWork implements PropertyChangedListener
// Look through the entities, and in any of their associations, for transient // Look through the entities, and in any of their associations, for transient
// enities, recursively. ("Persistence by reachability") // enities, recursively. ("Persistence by reachability")
if ($assoc->isOneToOne()) { if ($assoc->isOneToOne()) {
if ($value instanceof Proxy && ! $value->__isInitialized__()) { if ($value instanceof Proxy && ! $value->__isInitialized__) {
return; // Ignore uninitialized proxy objects return; // Ignore uninitialized proxy objects
} }
$value = array($value); $value = array($value);
...@@ -1732,7 +1731,12 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1732,7 +1731,12 @@ class UnitOfWork implements PropertyChangedListener
if (isset($this->_identityMap[$class->rootEntityName][$idHash])) { if (isset($this->_identityMap[$class->rootEntityName][$idHash])) {
$entity = $this->_identityMap[$class->rootEntityName][$idHash]; $entity = $this->_identityMap[$class->rootEntityName][$idHash];
$oid = spl_object_hash($entity); $oid = spl_object_hash($entity);
$overrideLocalValues = isset($hints[Query::HINT_REFRESH]); if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
$entity->__isInitialized__ = true;
$overrideLocalValues = true;
} else {
$overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
}
} else { } else {
//$entity = clone $class->prototype; //$entity = clone $class->prototype;
$entity = new $className; $entity = new $className;
......
...@@ -34,7 +34,7 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -34,7 +34,7 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase
$user2 = $this->_em->getReference(get_class($user), $userId); $user2 = $this->_em->getReference(get_class($user), $userId);
$this->_em->flush(); $this->_em->flush();
$this->assertFalse($user2->__isInitialized__()); $this->assertFalse($user2->__isInitialized__);
$a = new DefaultValueAddress; $a = new DefaultValueAddress;
$a->country = 'de'; $a->country = 'de';
...@@ -46,7 +46,7 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -46,7 +46,7 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($a); $this->_em->persist($a);
$this->_em->flush(); $this->_em->flush();
$this->assertFalse($user2->__isInitialized__()); $this->assertFalse($user2->__isInitialized__);
$this->_em->clear(); $this->_em->clear();
$a2 = $this->_em->find(get_class($a), $a->id); $a2 = $this->_em->find(get_class($a), $a->id);
......
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
class DDC237Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC237EntityX'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC237EntityY'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC237EntityZ')
));
}
public function testUninitializedProxyIsInitializedOnFetchJoin()
{
$x = new DDC237EntityX;
$y = new DDC237EntityY;
$z = new DDC237EntityZ;
$x->data = 'X';
$y->data = 'Y';
$z->data = 'Z';
$x->y = $y;
$z->y = $y;
$this->_em->persist($x);
$this->_em->persist($y);
$this->_em->persist($z);
$this->_em->flush();
$this->_em->clear();
$x2 = $this->_em->find(get_class($x), $x->id); // proxy injected for Y
$this->assertTrue($x2->y instanceof \Doctrine\ORM\Proxy\Proxy);
$this->assertFalse($x2->y->__isInitialized__);
// proxy for Y is in identity map
$z2 = $this->_em->createQuery('select z,y from ' . get_class($z) . ' z join z.y y where z.id = ?1')
->setParameter(1, $z->id)
->getSingleResult();
$this->assertTrue($z2->y instanceof \Doctrine\ORM\Proxy\Proxy);
$this->assertTrue($z2->y->__isInitialized__);
$this->assertEquals('Y', $z2->y->data);
$this->assertEquals($y->id, $z2->y->id);
// since the Y is the same, the instance from the identity map is
// used, even if it is a proxy.
$this->assertNotSame($x, $x2);
$this->assertNotSame($z, $z2);
$this->assertSame($z2->y, $x2->y);
$this->assertTrue($z2->y instanceof \Doctrine\ORM\Proxy\Proxy);
}
}
/**
* @Entity @Table(name="ddc237_x")
*/
class DDC237EntityX
{
/**
* @Id @Column(type="integer") @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @Column(type="string")
*/
public $data;
/**
* @OneToOne(targetEntity="DDC237EntityY")
* @JoinColumn(name="y_id", referencedColumnName="id")
*/
public $y;
}
/** @Entity @Table(name="ddc237_y") */
class DDC237EntityY
{
/**
* @Id @Column(type="integer") @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @Column(type="string")
*/
public $data;
}
/** @Entity @Table(name="ddc237_z") */
class DDC237EntityZ
{
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
public $id;
/** @Column(type="string") */
public $data;
/**
* @OneToOne(targetEntity="DDC237EntityY")
* @JoinColumn(name="y_id", referencedColumnName="id")
*/
public $y;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment