Skip to content

Commit 5ea9846

Browse files
authored
Merge pull request #1926 from naitsirch/sync_positions_after_multiple_deletes
[Sortable] Fix issue with position synchronization after multiple deletes
2 parents 0b7bdbe + c11f09a commit 5ea9846

File tree

2 files changed

+73
-4
lines changed

2 files changed

+73
-4
lines changed

lib/Gedmo/Sortable/SortableListener.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ public function postFlush(EventArgs $args)
413413
{
414414
$ea = $this->getEventAdapter($args);
415415
$em = $ea->getObjectManager();
416+
417+
$updatedObjects = [];
418+
416419
foreach ($this->relocations as $hash => $relocation) {
417420
$config = $this->getConfiguration($em, $relocation['name']);
418421
foreach ($relocation['deltas'] as $delta) {
@@ -473,12 +476,28 @@ public function postFlush(EventArgs $args)
473476
$value = next($relocation['groups']);
474477
}
475478
if ($matches) {
476-
$this->setFieldValue($ea, $object, $config['position'], $pos, $pos + $delta['delta']);
479+
// We cannot use `$this->setFieldValue()` here, because it will create a change set, that will
480+
// prevent from other relocations being executed on this object.
481+
// We just update the object value and will create the change set later.
482+
if (!isset($updatedObjects[$oid])) {
483+
$updatedObjects[$oid] = array(
484+
'object' => $object,
485+
'field' => $config['position'],
486+
'oldValue' => $pos,
487+
);
488+
}
489+
$updatedObjects[$oid]['newValue'] = $pos + $delta['delta'];
490+
491+
$meta->getReflectionProperty($config['position'])->setValue($object, $updatedObjects[$oid]['newValue']);
477492
}
478493
}
479494
}
480495
}
481496

497+
foreach ($updatedObjects as $updateData) {
498+
$this->setFieldValue($ea, $updateData['object'], $updateData['field'], $updateData['oldValue'], $updateData['newValue']);
499+
}
500+
482501
// Clear relocations
483502
unset($this->relocations[$hash]);
484503
unset($this->maxPositions[$hash]); // unset only if relocations has been processed

tests/Gedmo/Sortable/SortableTest.php

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public function testMoveLastPosition()
7474
$node->setPath("/");
7575
$this->em->persist($node);
7676
}
77-
$this->em->flush();
77+
$this->em->flush();
7878

7979
$repo = $this->em->getRepository(self::NODE);
8080

@@ -91,7 +91,7 @@ public function testMoveLastPosition()
9191
$node = $repo->findOneByPosition(9);
9292
$this->assertNotNull($node);
9393
$this->assertEquals('Node1', $node->getName());
94-
94+
9595
}
9696

9797
/**
@@ -248,6 +248,56 @@ public function shouldSyncPositionAfterDelete()
248248
$this->assertEquals(1, $nodes[1]->getPosition());
249249
}
250250

251+
/**
252+
* Test if the sorting is correct if multiple items are deleted.
253+
*
254+
* Example:
255+
* Position | Element | Action | Expected Position
256+
* 0 | Node1 | | 0
257+
* 1 | Node2 | delete |
258+
* 2 | Node3 | delete |
259+
* 3 | Node4 | | 1
260+
*
261+
* @test
262+
*/
263+
public function shouldSyncPositionAfterMultipleDeletes()
264+
{
265+
$repo = $this->em->getRepository(self::NODE);
266+
267+
$node2 = new Node();
268+
$node2->setName("Node2");
269+
$node2->setPath("/");
270+
$this->em->persist($node2);
271+
272+
$node3 = new Node();
273+
$node3->setName("Node3");
274+
$node3->setPath("/");
275+
$this->em->persist($node3);
276+
277+
$node4 = new Node();
278+
$node4->setName("Node4");
279+
$node4->setPath("/");
280+
$this->em->persist($node4);
281+
282+
$this->em->flush();
283+
284+
$node1 = $repo->findOneByName('Node1');
285+
$this->em->remove($node2);
286+
$this->em->remove($node3);
287+
$this->em->flush();
288+
289+
// test if synced on objects in memory correctly
290+
$this->assertEquals(0, $node1->getPosition());
291+
$this->assertEquals(1, $node4->getPosition());
292+
293+
// test if persisted correctly
294+
$this->em->clear();
295+
$nodes = $repo->findAll();
296+
$this->assertCount(2, $nodes);
297+
$this->assertEquals(0, $nodes[0]->getPosition());
298+
$this->assertEquals(1, $nodes[1]->getPosition());
299+
}
300+
251301
/**
252302
* This is a test case for issue #1209
253303
* @test
@@ -792,7 +842,7 @@ public function testSetOutOfBoundsHighPosition()
792842

793843
$this->assertEquals(4, $nodes[4]->getPosition());
794844
}
795-
845+
796846
/**
797847
* @test
798848
*/

0 commit comments

Comments
 (0)