Skip to content

Commit 0eab5aa

Browse files
committed
[Sortable] Fix issue with position synchronization when items are added and deleted in one operation
Deletion relocations must be aware of newly created objects in order to generate correct position update queries.
1 parent 1544f79 commit 0eab5aa

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

lib/Gedmo/Sortable/SortableListener.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@ protected function addRelocation($hash, $class, $groups, $start, $stop, $delta,
579579
$val['delta'] += $needle['delta'];
580580
$val['exclude'] = array_merge($val['exclude'], $needle['exclude']);
581581
throw new \Exception("Found delta. No need to add it again.");
582+
// For every deletion relocation add newly created object to the list of excludes
583+
// otherwise position update queries will run for created objects as well.
584+
} elseif (-1 == $val['delta'] && 1 == $needle['delta']) {
585+
$val['exclude'] = array_merge($val['exclude'], $needle['exclude']);
582586
}
583587
}, $newDelta);
584588
$this->relocations[$hash]['deltas'][] = $newDelta;

tests/Gedmo/Sortable/SortableTest.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,79 @@ public function shouldSyncPositionAfterMultipleDeletes()
298298
$this->assertEquals(1, $nodes[1]->getPosition());
299299
}
300300

301+
/**
302+
* Test if the sorting is correct if multiple items are added and deleted.
303+
*
304+
* Example:
305+
* Position | Element | Action | Expected Position
306+
* 0 | Node1 | | 0
307+
* 1 | Node2 | delete |
308+
* 2 | Node3 | delete |
309+
* 3 | Node4 | | 1
310+
* | Node5 | add | 2
311+
* | Node6 | add | 3
312+
*
313+
* @test
314+
*/
315+
public function shouldSyncPositionAfterMultipleAddsAndMultipleDeletes()
316+
{
317+
$repo = $this->em->getRepository(self::NODE);
318+
319+
$node2 = new Node();
320+
$node2->setName("Node2");
321+
$node2->setPath("/");
322+
$this->em->persist($node2);
323+
324+
$node3 = new Node();
325+
$node3->setName("Node3");
326+
$node3->setPath("/");
327+
$this->em->persist($node3);
328+
329+
$node4 = new Node();
330+
$node4->setName("Node4");
331+
$node4->setPath("/");
332+
$this->em->persist($node4);
333+
334+
$this->em->flush();
335+
336+
$node1 = $repo->findOneByName('Node1');
337+
338+
$this->em->remove($node2);
339+
340+
$node5 = new Node();
341+
$node5->setName("Node5");
342+
$node5->setPath("/");
343+
$this->em->persist($node5);
344+
345+
$node6 = new Node();
346+
$node6->setName("Node6");
347+
$node6->setPath("/");
348+
$this->em->persist($node6);
349+
350+
$this->em->remove($node3);
351+
352+
$this->em->flush();
353+
354+
// test if synced on objects in memory correctly
355+
$this->assertEquals(0, $node1->getPosition());
356+
$this->assertEquals(1, $node4->getPosition());
357+
$this->assertEquals(2, $node5->getPosition());
358+
$this->assertEquals(3, $node6->getPosition());
359+
360+
// test if persisted correctly
361+
$this->em->clear();
362+
$nodes = $repo->findAll();
363+
$this->assertCount(4, $nodes);
364+
$this->assertEquals(0, $nodes[0]->getPosition());
365+
$this->assertEquals("Node1", $nodes[0]->getName());
366+
$this->assertEquals(1, $nodes[1]->getPosition());
367+
$this->assertEquals("Node4", $nodes[1]->getName());
368+
$this->assertEquals(2, $nodes[2]->getPosition());
369+
$this->assertEquals("Node5", $nodes[2]->getName());
370+
$this->assertEquals(3, $nodes[3]->getPosition());
371+
$this->assertEquals("Node6", $nodes[3]->getName());
372+
}
373+
301374
/**
302375
* This is a test case for issue #1209
303376
* @test

0 commit comments

Comments
 (0)