From 686758e84603d459ebb088146c91c35032207ff4 Mon Sep 17 00:00:00 2001 From: guilhermeblanco Date: Sun, 6 Sep 2009 03:25:44 +0000 Subject: [PATCH] [2.0] fixes #2478 Now PersistentCollections may contain NEW elements and track policy monitor them when flushing on DEFER_IMPLICIT mode --- .../ORM/Internal/Hydration/ObjectHydrator.php | 4 ---- lib/Doctrine/ORM/PersistentCollection.php | 11 +++++++++-- lib/Doctrine/ORM/UnitOfWork.php | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index f1a90d4de..df805d2ec 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -141,11 +141,7 @@ class ObjectHydrator extends AbstractHydrator $pColl = new PersistentCollection( $this->_em, $this->_ce[$relation->targetEntityName], - /* - TICKET #2478: This seems to double resultset in Collections after add/persist/retrieve execution $class->reflFields[$name]->getValue($entity) ?: new ArrayCollection - */ - new ArrayCollection() ); $pColl->setOwner($entity, $relation); diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php index b98d1853c..134deb695 100644 --- a/lib/Doctrine/ORM/PersistentCollection.php +++ b/lib/Doctrine/ORM/PersistentCollection.php @@ -134,6 +134,7 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect { $this->_owner = $entity; $this->_association = $assoc; + // Check for bidirectionality if ( ! $assoc->isOwningSide) { // For sure bi-directional @@ -176,7 +177,10 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect */ public function hydrateAdd($element) { - $this->_coll->add($element); + if ( ! $this->contains($element)) { + $this->_coll->add($element); + } + // If _backRefFieldName is set, then the association is bidirectional // and we need to set the back reference. if ($this->_backRefFieldName) { @@ -202,7 +206,10 @@ final class PersistentCollection implements \Doctrine\Common\Collections\Collect */ public function hydrateSet($key, $element) { - $this->_coll->set($key, $element); + if ( ! $this->contains($element)) { + $this->_coll->set($key, $element); + } + // If _backRefFieldName is set, then the association is bidirectional // and we need to set the back reference. if ($this->_backRefFieldName) { diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 590866a97..c65acdeba 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -451,16 +451,25 @@ class UnitOfWork implements PropertyChangedListener $actualData[$name] = $refProp->getValue($entity); } - if ($class->isCollectionValuedAssociation($name) && $actualData[$name] !== null - && ! ($actualData[$name] instanceof PersistentCollection)) { + if ($class->isCollectionValuedAssociation($name) && $actualData[$name] !== null) { // If $actualData[$name] is Collection then unwrap the array if ( ! $actualData[$name] instanceof ArrayCollection) { + if ($actualData[$name] instanceof PersistentCollection) { + $actualData[$name] = $actualData[$name]->toArray(); + } + $actualData[$name] = new ArrayCollection($actualData[$name]); } + $assoc = $class->associationMappings[$name]; + // Inject PersistentCollection - $coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata( - $assoc->targetEntityName), $actualData[$name]); + $coll = new PersistentCollection( + $this->_em, + $this->_em->getClassMetadata($assoc->targetEntityName), + $actualData[$name] + ); + $coll->setOwner($entity, $assoc); $coll->setDirty( ! $coll->isEmpty()); $class->reflFields[$name]->setValue($entity, $coll);