Skip to content

Commit 8f69bdc

Browse files
committed
BC compatibilish introduction of ObjectChangeSet
1 parent c850247 commit 8f69bdc

8 files changed

Lines changed: 118 additions & 37 deletions

File tree

lib/Doctrine/ODM/MongoDB/ChangeSet/FieldChange.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
namespace Doctrine\ODM\MongoDB\ChangeSet;
2121

22-
final class FieldChange
22+
final class FieldChange implements \ArrayAccess
2323
{
2424
private $oldValue;
2525
private $newValue;
@@ -45,4 +45,38 @@ public function getOldValue()
4545
{
4646
return $this->oldValue;
4747
}
48+
49+
public function offsetExists($offset)
50+
{
51+
return in_array($offset, [0, 1], true);
52+
}
53+
54+
public function offsetGet($offset)
55+
{
56+
switch ($offset) {
57+
case 0:
58+
return $this->oldValue;
59+
case 1:
60+
return $this->newValue;
61+
default:
62+
throw new \OutOfBoundsException();
63+
}
64+
}
65+
66+
public function offsetSet($offset, $value)
67+
{
68+
switch ($offset) {
69+
case 0:
70+
return $this->oldValue = $value;
71+
case 1:
72+
return $this->newValue = $value;
73+
default:
74+
throw new \OutOfBoundsException();
75+
}
76+
}
77+
78+
public function offsetUnset($offset)
79+
{
80+
throw new \BadMethodCallException('Not allowed.');
81+
}
4882
}

lib/Doctrine/ODM/MongoDB/ChangeSet/LegacyChangeSetCalculator.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,14 @@ public function __construct(DocumentManager $documentManager, UnitOfWork $unitOf
5050
/**
5151
* @param object $document
5252
* @param ClassMetadata $class
53-
* @param array $originalData
53+
* @param ObjectChangeSet $originalData
5454
* @return ObjectChangeSet
5555
*/
56-
public function calculate($document, ClassMetadata $class, $originalData = null, $changeSet = [])
56+
public function calculate($document, ClassMetadata $class, $originalData = null, ObjectChangeSet $changeSet = null)
5757
{
58+
if ($changeSet === null) {
59+
$changeSet = new ObjectChangeSet($document, []);
60+
}
5861
$actualData = $this->getDocumentActualData($document, $class);
5962
$isNewDocument = $originalData === null;
6063
if ($isNewDocument) {
@@ -73,7 +76,7 @@ public function calculate($document, ClassMetadata $class, $originalData = null,
7376
if (isset($class->fieldMappings[$propName]['reference']) && $class->fieldMappings[$propName]['isInverseSide']) {
7477
continue;
7578
}
76-
$changeSet[$propName] = array(null, $actualValue);
79+
$changeSet[$propName] = new FieldChange(null, $actualValue);
7780
}
7881
return $changeSet;
7982
} else {
@@ -108,7 +111,7 @@ public function calculate($document, ClassMetadata $class, $originalData = null,
108111
$this->uow->scheduleOrphanRemoval($orgValue);
109112
}
110113

111-
$changeSet[$propName] = array($orgValue, $actualValue);
114+
$changeSet[$propName] = new FieldChange($orgValue, $actualValue);
112115
continue;
113116
}
114117

@@ -118,7 +121,7 @@ public function calculate($document, ClassMetadata $class, $originalData = null,
118121
$this->uow->scheduleOrphanRemoval($orgValue);
119122
}
120123

121-
$changeSet[$propName] = array($orgValue, $actualValue);
124+
$changeSet[$propName] = new FieldChange($orgValue, $actualValue);
122125
continue;
123126
}
124127

@@ -140,7 +143,7 @@ public function calculate($document, ClassMetadata $class, $originalData = null,
140143

141144
// if embed-many or reference-many relationship
142145
if (isset($class->fieldMappings[$propName]['type']) && $class->fieldMappings[$propName]['type'] === 'many') {
143-
$changeSet[$propName] = array($orgValue, $actualValue);
146+
$changeSet[$propName] = new FieldChange($orgValue, $actualValue);
144147
/* If original collection was exchanged with a non-empty value
145148
* and $set will be issued, there is no need to $unset it first
146149
*/
@@ -165,7 +168,7 @@ public function calculate($document, ClassMetadata $class, $originalData = null,
165168
}
166169

167170
// regular field
168-
$changeSet[$propName] = array($orgValue, $actualValue);
171+
$changeSet[$propName] = new FieldChange($orgValue, $actualValue);
169172
}
170173
return $changeSet;
171174
}

lib/Doctrine/ODM/MongoDB/ChangeSet/ObjectChangeSet.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
namespace Doctrine\ODM\MongoDB\ChangeSet;
2121

22-
final class ObjectChangeSet implements \IteratorAggregate
22+
final class ObjectChangeSet implements \IteratorAggregate, \ArrayAccess, \Countable
2323
{
2424
private $changes = [];
2525

@@ -35,14 +35,39 @@ public function getChanges()
3535
{
3636
return $this->changes;
3737
}
38-
38+
3939
public function getObject()
4040
{
4141
return $this->object;
4242
}
43-
43+
4444
public function getIterator()
4545
{
4646
return new \ArrayIterator($this->changes);
4747
}
48+
49+
public function offsetExists($offset)
50+
{
51+
return isset($this->changes[$offset]);
52+
}
53+
54+
public function offsetGet($offset)
55+
{
56+
return $this->changes[$offset];
57+
}
58+
59+
public function offsetSet($offset, $value)
60+
{
61+
$this->changes[$offset] = $value;
62+
}
63+
64+
public function offsetUnset($offset)
65+
{
66+
throw new \BadMethodCallException('Not allowed.');
67+
}
68+
69+
public function count()
70+
{
71+
return count($this->changes);
72+
}
4873
}

lib/Doctrine/ODM/MongoDB/Event/PreUpdateEventArgs.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
namespace Doctrine\ODM\MongoDB\Event;
2121

22+
use Doctrine\ODM\MongoDB\ChangeSet\ObjectChangeSet;
2223
use Doctrine\ODM\MongoDB\DocumentManager;
2324

2425
/**
@@ -29,7 +30,7 @@
2930
class PreUpdateEventArgs extends LifecycleEventArgs
3031
{
3132
/**
32-
* @var array
33+
* @var ObjectChangeSet
3334
*/
3435
private $documentChangeSet;
3536

@@ -38,9 +39,9 @@ class PreUpdateEventArgs extends LifecycleEventArgs
3839
*
3940
* @param object $document
4041
* @param DocumentManager $dm
41-
* @param array $changeSet
42+
* @param ObjectChangeSet $changeSet
4243
*/
43-
public function __construct($document, DocumentManager $dm, array $changeSet)
44+
public function __construct($document, DocumentManager $dm, ObjectChangeSet $changeSet)
4445
{
4546
parent::__construct($document, $dm);
4647
$this->documentChangeSet = $changeSet;
@@ -49,7 +50,7 @@ public function __construct($document, DocumentManager $dm, array $changeSet)
4950
/**
5051
* Retrieves the document changeset.
5152
*
52-
* @return array
53+
* @return ObjectChangeSet
5354
*/
5455
public function getDocumentChangeSet()
5556
{

lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public function prepareInsertData($document)
7575
$insertData = array();
7676
foreach ($class->fieldMappings as $mapping) {
7777

78-
$new = isset($changeset[$mapping['fieldName']][1]) ? $changeset[$mapping['fieldName']][1] : null;
78+
$new = isset($changeset[$mapping['fieldName']]) ? $changeset[$mapping['fieldName']][1] : null;
7979

8080
if ($new === null && $mapping['nullable']) {
8181
$insertData[$mapping['name']] = null;
@@ -131,7 +131,7 @@ public function prepareUpdateData($document)
131131
$changeset = $this->uow->getDocumentChangeSet($document);
132132

133133
$updateData = array();
134-
foreach ($changeset as $fieldName => $change) {
134+
foreach ($changeset ?: [] as $fieldName => $change) {
135135
$mapping = $class->fieldMappings[$fieldName];
136136

137137
// skip non embedded document identifiers

lib/Doctrine/ODM/MongoDB/UnitOfWork.php

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,20 @@
1919

2020
namespace Doctrine\ODM\MongoDB;
2121

22-
use Doctrine\Common\Collections\ArrayCollection;
2322
use Doctrine\Common\Collections\Collection;
2423
use Doctrine\Common\EventManager;
2524
use Doctrine\Common\NotifyPropertyChanged;
2625
use Doctrine\Common\PropertyChangedListener;
27-
use Doctrine\MongoDB\GridFSFile;
2826
use Doctrine\ODM\MongoDB\ChangeSet\ChangeSetCalculator;
27+
use Doctrine\ODM\MongoDB\ChangeSet\FieldChange;
2928
use Doctrine\ODM\MongoDB\ChangeSet\LegacyChangeSetCalculator;
29+
use Doctrine\ODM\MongoDB\ChangeSet\ObjectChangeSet;
3030
use Doctrine\ODM\MongoDB\Hydrator\HydratorFactory;
3131
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
3232
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface;
3333
use Doctrine\ODM\MongoDB\Persisters\PersistenceBuilder;
3434
use Doctrine\ODM\MongoDB\Proxy\Proxy;
3535
use Doctrine\ODM\MongoDB\Query\Query;
36-
use Doctrine\ODM\MongoDB\Types\Type;
3736
use Doctrine\ODM\MongoDB\Utility\CollectionHelper;
3837
use Doctrine\ODM\MongoDB\Utility\LifecycleEventManager;
3938

@@ -582,25 +581,25 @@ private function computeSingleDocumentChangeSet($document)
582581
* Gets the changeset for a document.
583582
*
584583
* @param object $document
585-
* @return array array('property' => array(0 => mixed|null, 1 => mixed|null))
584+
* @return ObjectChangeSet|null
586585
*/
587586
public function getDocumentChangeSet($document)
588587
{
589588
$oid = spl_object_hash($document);
590589
if (isset($this->documentChangeSets[$oid])) {
591590
return $this->documentChangeSets[$oid];
592591
}
593-
return array();
592+
return null;
594593
}
595594

596595
/**
597596
* INTERNAL:
598597
* Sets the changeset for a document.
599598
*
600599
* @param object $document
601-
* @param array $changeset
600+
* @param ObjectChangeSet $changeset
602601
*/
603-
public function setDocumentChangeSet($document, $changeset)
602+
public function setDocumentChangeSet($document, ObjectChangeSet $changeset)
604603
{
605604
$this->documentChangeSets[spl_object_hash($document)] = $changeset;
606605
}
@@ -670,15 +669,19 @@ private function computeOrRecomputeChangeSet(ClassMetadata $class, $document, $r
670669
if ($isChangeTrackingNotify && ! $recompute && isset($this->documentChangeSets[$oid])) {
671670
$changeSet = $this->documentChangeSets[$oid];
672671
} else {
673-
$changeSet = array();
672+
$changeSet = new ObjectChangeSet($document, []);
674673
}
675674

676675
$changeSet = $this->changeSetCalculator->calculate($document, $class, $isNewDocument ? null : $this->originalDocumentData[$oid], $changeSet);
677676

678-
if ($changeSet) {
679-
$this->documentChangeSets[$oid] = isset($this->documentChangeSets[$oid])
680-
? $changeSet + $this->documentChangeSets[$oid]
681-
: $changeSet;
677+
if (count($changeSet)) {
678+
if (isset($this->documentChangeSets[$oid])) {
679+
foreach ($changeSet as $field => $change) {
680+
$this->documentChangeSets[$oid][$field] = $change;
681+
}
682+
} else {
683+
$this->documentChangeSets[$oid] = $changeSet;
684+
}
682685

683686
$this->originalDocumentData[$oid] = $this->changeSetCalculator->getDocumentActualData($document, $class);
684687
if (! $isNewDocument) {
@@ -711,7 +714,10 @@ function ($assoc) { return empty($assoc['notSaved']); }
711714
$oid2 = spl_object_hash($obj);
712715

713716
if (isset($this->documentChangeSets[$oid2])) {
714-
$this->documentChangeSets[$oid][$mapping['fieldName']] = array($value, $value);
717+
if (! isset($this->documentChangeSets[$oid])) {
718+
$this->documentChangeSets[$oid] = new ObjectChangeSet($document, []);
719+
}
720+
$this->documentChangeSets[$oid][$mapping['fieldName']] = new FieldChange($value, $value);
715721

716722
if ( ! $isNewDocument) {
717723
$this->scheduleForUpdate($document);
@@ -1034,7 +1040,7 @@ private function executeUpdates(ClassMetadata $class, array $documents, array $o
10341040
foreach ($documents as $oid => $document) {
10351041
$this->lifecycleEventManager->preUpdate($class, $document);
10361042

1037-
if ( ! empty($this->documentChangeSets[$oid]) || $this->hasScheduledCollections($document)) {
1043+
if (! empty($this->documentChangeSets[$oid]) || $this->hasScheduledCollections($document)) {
10381044
$persister->update($document, $options);
10391045
}
10401046

@@ -2698,7 +2704,7 @@ public function registerManaged($document, $id, array $data)
26982704
*/
26992705
public function clearDocumentChangeSet($oid)
27002706
{
2701-
$this->documentChangeSets[$oid] = array();
2707+
unset($this->documentChangeSets[$oid]);
27022708
}
27032709

27042710
/* PropertyChangedListener implementation */
@@ -2721,7 +2727,10 @@ public function propertyChanged($document, $propertyName, $oldValue, $newValue)
27212727
}
27222728

27232729
// Update changeset and mark document for synchronization
2724-
$this->documentChangeSets[$oid][$propertyName] = array($oldValue, $newValue);
2730+
if (! isset($this->documentChangeSets[$oid])) {
2731+
$this->documentChangeSets[$oid] = new ObjectChangeSet($document, []);
2732+
}
2733+
$this->documentChangeSets[$oid][$propertyName] = new FieldChange($oldValue, $newValue);
27252734
if ( ! isset($this->scheduledForDirtyCheck[$class->name][$oid])) {
27262735
$this->scheduleForDirtyCheck($document);
27272736
}

lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
namespace Doctrine\ODM\MongoDB\Utility;
2121

2222
use Doctrine\Common\EventManager;
23+
use Doctrine\ODM\MongoDB\ChangeSet\ObjectChangeSet;
2324
use Doctrine\ODM\MongoDB\DocumentManager;
2425
use Doctrine\ODM\MongoDB\Event\DocumentNotFoundEventArgs;
2526
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
@@ -160,11 +161,15 @@ public function preUpdate(ClassMetadata $class, $document)
160161
{
161162
if ( ! empty($class->lifecycleCallbacks[Events::preUpdate])) {
162163
$class->invokeLifecycleCallbacks(Events::preUpdate, $document, array(
163-
new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document))
164+
new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document) ?: new ObjectChangeSet($document, []))
164165
));
165166
$this->uow->recomputeSingleDocumentChangeSet($class, $document);
166167
}
167-
$this->evm->dispatchEvent(Events::preUpdate, new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document)));
168+
// @todo there seems to be a bug in old change set calculation, cleared collections are not in change set
169+
$this->evm->dispatchEvent(
170+
Events::preUpdate,
171+
new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document) ?: new ObjectChangeSet($document, []))
172+
);
168173
$this->cascadePreUpdate($class, $document);
169174
}
170175

tests/Doctrine/ODM/MongoDB/Tests/UnitOfWorkTest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Doctrine\Common\PropertyChangedListener;
66
use Doctrine\Common\Collections\ArrayCollection;
7+
use Doctrine\ODM\MongoDB\ChangeSet\ObjectChangeSet;
78
use Doctrine\ODM\MongoDB\DocumentManager;
89
use Doctrine\ODM\MongoDB\UnitOfWork;
910
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
@@ -208,7 +209,10 @@ public function testChangeTrackingNotify()
208209
$entity->setTransient('newtransientvalue');
209210

210211
$this->assertTrue($this->uow->isScheduledForDirtyCheck($entity));
211-
$this->assertEquals(array('data' => array('thedata', 'newdata')), $this->uow->getDocumentChangeSet($entity));
212+
$changeSet = $this->uow->getDocumentChangeSet($entity);
213+
$this->assertInstanceOf(ObjectChangeSet::class, $changeSet);
214+
$this->assertEquals('thedata', $changeSet['data'][0]);
215+
$this->assertEquals('newdata', $changeSet['data'][1]);
212216

213217
$item = new NotifyChangedRelatedItem();
214218
$item->setId(1);
@@ -632,7 +636,7 @@ public function testRecomputeChangesetForUninitializedProxyDoesNotCreateChangese
632636

633637
$this->uow->recomputeSingleDocumentChangeSet($classMetadata, $user->getAvatar());
634638

635-
$this->assertEquals(array(), $this->uow->getDocumentChangeSet($user->getAvatar()));
639+
$this->assertEquals(null, $this->uow->getDocumentChangeSet($user->getAvatar()));
636640
}
637641

638642

0 commit comments

Comments
 (0)