From ca23555c3ee176e59f35f0d54cb1d4cb3b796a47 Mon Sep 17 00:00:00 2001 From: romanb Date: Wed, 10 Feb 2010 10:47:42 +0000 Subject: [PATCH] [2.0][DDC-79][DDC-261] Fixed. Also fixed support for deleting objects by reference (getReference() + remove() + flush()) to effectively delete objects without loading them. --- lib/Doctrine/ORM/Mapping/ClassMetadata.php | 28 ++++++++++++++----- lib/Doctrine/ORM/UnitOfWork.php | 9 +++--- tests/Doctrine/Tests/Models/CMS/CmsUser.php | 1 + .../ORM/Functional/BasicFunctionalTest.php | 23 +++++++++++++++ 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index 7b3336524..725343c8f 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -54,6 +54,13 @@ class ClassMetadata extends ClassMetadataInfo * @var array */ public $reflFields = array(); + + /** + * The prototype from which new instances of the mapped class are created. + * + * @var object + */ + private $_prototype; /** * Initializes a new ClassMetadata instance that will hold the object-relational mapping @@ -68,8 +75,6 @@ class ClassMetadata extends ClassMetadataInfo $this->namespace = $this->reflClass->getNamespaceName(); $this->primaryTable['name'] = $this->reflClass->getShortName(); $this->rootEntityName = $entityName; - - //$this->prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); } /** @@ -320,7 +325,7 @@ class ClassMetadata extends ClassMetadataInfo public function __sleep() { return array( - 'associationMappings', // unserialization bottleneck with many assocs + 'associationMappings', // unserialization "bottleneck" with many associations 'changeTrackingPolicy', 'columnNames', //TODO: Not really needed. Can use fieldMappings[$fieldName]['columnName'] 'customRepositoryClassName', @@ -375,13 +380,22 @@ class ClassMetadata extends ClassMetadataInfo } else { $reflField = $this->reflClass->getProperty($field); } - + $reflField->setAccessible(true); $this->reflFields[$field] = $reflField; } - - //$this->prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); } - //public $prototype; + /** + * Creates a new instance of the mapped class, without invoking the constructor. + * + * @return object + */ + public function newInstance() + { + if ($this->_prototype === null) { + $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); + } + return clone $this->_prototype; + } } diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 58103185c..d008d0e7e 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -781,7 +781,7 @@ class UnitOfWork implements PropertyChangedListener $hasListeners = $this->_evm->hasListeners(Events::postRemove); foreach ($this->_entityDeletions as $oid => $entity) { - if (get_class($entity) == $className) { + if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) { $persister->delete($entity); unset( $this->_entityDeletions[$oid], @@ -956,11 +956,11 @@ class UnitOfWork implements PropertyChangedListener unset($this->_entityInsertions[$oid]); return; // entity has not been persisted yet, so nothing more to do. } - + if ( ! $this->isInIdentityMap($entity)) { return; // ignore } - + $this->removeFromIdentityMap($entity); if (isset($this->_entityUpdates[$oid])) { @@ -1738,8 +1738,7 @@ class UnitOfWork implements PropertyChangedListener $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); } } else { - //$entity = clone $class->prototype; - $entity = new $className; + $entity = $class->newInstance(); $oid = spl_object_hash($entity); $this->_entityIdentifiers[$oid] = $id; $this->_entityStates[$oid] = self::STATE_MANAGED; diff --git a/tests/Doctrine/Tests/Models/CMS/CmsUser.php b/tests/Doctrine/Tests/Models/CMS/CmsUser.php index 148fa6674..9c21c7836 100644 --- a/tests/Doctrine/Tests/Models/CMS/CmsUser.php +++ b/tests/Doctrine/Tests/Models/CMS/CmsUser.php @@ -116,4 +116,5 @@ class CmsUser $address->setUser($this); } } + } diff --git a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php index b123db1af..5e49f86c1 100644 --- a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php @@ -589,6 +589,29 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->getConnection()->getConfiguration()->setSqlLogger($oldLogger); } + public function testRemoveEntityByReference() + { + $user = new CmsUser; + $user->name = 'Guilherme'; + $user->username = 'gblanco'; + $user->status = 'developer'; + + //$this->_em->getConnection()->getConfiguration()->setSqlLogger(new \Doctrine\DBAL\Logging\EchoSqlLogger); + + $this->_em->persist($user); + $this->_em->flush(); + $this->_em->clear(); + + $userRef = $this->_em->getReference('Doctrine\Tests\Models\CMS\CmsUser', $user->getId()); + $this->_em->remove($userRef); + $this->_em->flush(); + $this->_em->clear(); + + $this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_users")); + + //$this->_em->getConnection()->getConfiguration()->setSqlLogger(null); + } + //DRAFT OF EXPECTED/DESIRED BEHAVIOR /*public function testPersistentCollectionContainsDoesNeverInitialize() {