From d473824279bfee19772bb1692d2a3453a2aff233 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sun, 23 Mar 2014 13:16:33 +0100 Subject: [PATCH] [DDC-2996] Fix bug in UnitOfWork#recomputeSingleEntityChangeSet When calling UnitOfWork#recomputeSingleEntityChangeSet on an entity that didn't have a changeset before, the computation was ignored. This method however is suggested to be used in "onFlush" and "preFlush" events in the documentation. Also fix a bug where recomputeSingleEntityChangeSet was used before calculating a real changeset for an object. --- lib/Doctrine/ORM/UnitOfWork.php | 11 ++- .../ORM/Functional/Ticket/DDC2996Test.php | 90 +++++++++++++++++++ .../ORM/Functional/Ticket/DDC3033Test.php | 2 - 3 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2996Test.php diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 26e446ce0..34561aef8 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -925,6 +925,10 @@ class UnitOfWork implements PropertyChangedListener } } + if ( ! isset($this->originalEntityData[$oid])) { + throw new \RuntimeException('Cannot call recomputeSingleEntityChangeSet before computeChangeSet on an entity.'); + } + $originalData = $this->originalEntityData[$oid]; $changeSet = array(); @@ -937,11 +941,12 @@ class UnitOfWork implements PropertyChangedListener } if ($changeSet) { - if (isset($this->entityChangeSets[$oid])) { - $this->entityChangeSets[$oid] = array_merge($this->entityChangeSets[$oid], $changeSet); - } + $this->entityChangeSets[$oid] = (isset($this->entityChangeSets[$oid])) + ? array_merge($this->entityChangeSets[$oid], $changeSet) + : $changeSet; $this->originalEntityData[$oid] = $actualData; + $this->entityUpdates[$oid] = $entity; } } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2996Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2996Test.php new file mode 100644 index 000000000..30724b2c7 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2996Test.php @@ -0,0 +1,90 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2996User'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2996UserPreference'), + )); + + $pref = new DDC2996UserPreference(); + $pref->user = new DDC2996User(); + $pref->value = "foo"; + + $this->_em->persist($pref); + $this->_em->persist($pref->user); + $this->_em->flush(); + + $pref->value = "bar"; + $this->_em->flush(); + + $this->assertEquals(1, $pref->user->counter); + + $this->_em->clear(); + + $pref = $this->_em->find(__NAMESPACE__ . '\\DDC2996UserPreference', $pref->id); + $this->assertEquals(1, $pref->user->counter); + } +} + +/** + * @Entity + */ +class DDC2996User +{ + /** + * @Id @GeneratedValue @Column(type="integer") + */ + public $id; + /** + * @Column(type="integer") + */ + public $counter = 0; +} + +/** + * @Entity @HasLifecycleCallbacks + */ +class DDC2996UserPreference +{ + /** + * @Id @GeneratedValue @Column(type="integer") + */ + public $id; + /** + * @Column(type="string") + */ + public $value; + + /** + * @ManyToOne(targetEntity="DDC2996User") + */ + public $user; + + /** + * @PreFlush + */ + public function preFlush($event) + { + $em = $event->getEntityManager(); + $uow = $em->getUnitOfWork(); + + if ($uow->getOriginalEntityData($this->user)) { + $this->user->counter++; + $uow->recomputeSingleEntityChangeSet( + $em->getClassMetadata(get_class($this->user)), + $this->user + ); + } + } +} diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3033Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3033Test.php index 4cb78d399..b08217873 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3033Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3033Test.php @@ -5,8 +5,6 @@ namespace Doctrine\Tests\ORM\Functional\Ticket; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Event\LifecycleEventArgs; -require_once __DIR__ . '/../../../TestInit.php'; - /** * @group DDC-3033 */