#6613 #6614 ensuring that only newly added items that weren't loaded are restored in the dirty state of the collection
This commit is contained in:
parent
1fc7f81741
commit
d44e6e1a9e
@ -692,23 +692,41 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
|
|||||||
protected function doInitialize()
|
protected function doInitialize()
|
||||||
{
|
{
|
||||||
// Has NEW objects added through add(). Remember them.
|
// Has NEW objects added through add(). Remember them.
|
||||||
$newObjects = [];
|
$newlyAddedDirtyObjects = [];
|
||||||
|
|
||||||
if ($this->isDirty) {
|
if ($this->isDirty) {
|
||||||
$newObjects = $this->collection->toArray();
|
$newlyAddedDirtyObjects = $this->collection->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->collection->clear();
|
$this->collection->clear();
|
||||||
$this->em->getUnitOfWork()->loadCollection($this);
|
$this->em->getUnitOfWork()->loadCollection($this);
|
||||||
$this->takeSnapshot();
|
$this->takeSnapshot();
|
||||||
|
|
||||||
// Reattach NEW objects added through add(), if any.
|
if ($newlyAddedDirtyObjects) {
|
||||||
if ($newObjects) {
|
$this->restoreNewObjectsInDirtyCollection($newlyAddedDirtyObjects);
|
||||||
foreach ($newObjects as $obj) {
|
|
||||||
$this->collection->add($obj);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param object[] $newObjects
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* Note: the only reason why this entire looping/complexity is performed via `spl_object_hash`
|
||||||
|
* is because we want to prevent using `array_udiff()`, which is likely to cause very
|
||||||
|
* high overhead (complexity of O(n^2)). `array_diff_key()` performs the operation in
|
||||||
|
* core, which is faster than using a callback for comparisons
|
||||||
|
*/
|
||||||
|
private function restoreNewObjectsInDirtyCollection(array $newObjects)
|
||||||
|
{
|
||||||
|
$loadedObjects = $this->collection->toArray();
|
||||||
|
$newObjectsByOid = array_combine(array_map('spl_object_hash', $newObjects), $newObjects);
|
||||||
|
$loadedObjectsByOid = array_combine(array_map('spl_object_hash', $loadedObjects), $loadedObjects);
|
||||||
|
$newObjectsThatWereNotLoaded = array_diff_key($newObjectsByOid, $loadedObjectsByOid);
|
||||||
|
|
||||||
|
// Reattach NEW objects added through add(), if any.
|
||||||
|
array_walk($newObjectsThatWereNotLoaded, [$this->collection, 'add']);
|
||||||
|
|
||||||
$this->isDirty = true;
|
$this->isDirty = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user