Skip to content

Commit fd3178a

Browse files
committed
Adds move before, after and below
1 parent 19fe168 commit fd3178a

File tree

3 files changed

+106
-13
lines changed

3 files changed

+106
-13
lines changed

src/NestedSetInterface.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,34 @@ public function findAncestors(Leaf $leaf);
7474
public function getLeaf($id, $revision_id);
7575

7676
/**
77-
* Moves a Leaf and its sub-tree into a new position.
77+
* Moves a Leaf and its sub-tree below the target leaf.
7878
*
79-
* @param int $newLeftPosition
80-
* The new left position for the leaf.
79+
* @param Leaf $target
80+
* The leaf to move below.
8181
* @param \PNX\Tree\Leaf $leaf
8282
* The leaf to move.
8383
*/
84-
public function moveSubTree($newLeftPosition, Leaf $leaf);
84+
public function moveSubTreeBelow(Leaf $target, Leaf $leaf);
85+
86+
/**
87+
* Moves a Leaf and its sub-tree before the target leaf.
88+
*
89+
* @param Leaf $target
90+
* The leaf to move before.
91+
* @param \PNX\Tree\Leaf $leaf
92+
* The leaf to move.
93+
*/
94+
public function moveSubTreeBefore(Leaf $target, Leaf $leaf);
95+
96+
/**
97+
* Moves a Leaf and its sub-tree after the target leaf.
98+
*
99+
* @param Leaf $target
100+
* The leaf to move after.
101+
* @param \PNX\Tree\Leaf $leaf
102+
* The leaf to move.
103+
*/
104+
public function moveSubTreeAfter(Leaf $target, Leaf $leaf);
85105

86106
/**
87107
* Gets a leaf at a specified left position.

src/Storage/DbalNestedSet.php

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,49 @@ public function deleteSubTree(Leaf $leaf) {
238238
/**
239239
* {@inheritdoc}
240240
*/
241-
public function moveSubTree($newLeftPostion, Leaf $leaf) {
241+
public function moveSubTreeBelow(Leaf $target, Leaf $leaf) {
242+
$newLeftPosition = $target->getLeft() + 1;
243+
$this->moveSubTreeToPosition($newLeftPosition, $leaf);
244+
}
245+
246+
/**
247+
* {@inheritdoc}
248+
*/
249+
public function moveSubTreeBefore(Leaf $target, Leaf $leaf) {
250+
$newLeftPosition = $target->getLeft();
251+
$this->moveSubTreeToPosition($newLeftPosition, $leaf);
252+
}
253+
254+
/**
255+
* {@inheritdoc}
256+
*/
257+
public function moveSubTreeAfter(Leaf $target, Leaf $leaf) {
258+
$newLeftPosition = $target->getRight() + 1;
259+
$this->moveSubTreeToPosition($newLeftPosition, $leaf);
260+
}
242261

262+
/**
263+
* Moves a subtree to a new position.
264+
*
265+
* @param int $newLeftPosition
266+
* The new left position.
267+
* @param \PNX\Tree\Leaf $leaf
268+
* The leaf to move.
269+
*
270+
* @throws \Exception
271+
* If a transaction error occurs.
272+
*/
273+
protected function moveSubTreeToPosition($newLeftPosition, Leaf $leaf) {
243274
try {
244275
// Calculate position adjustment variables.
245276
$width = $leaf->getRight() - $leaf->getLeft() + 1;
246-
$distance = $newLeftPostion - $leaf->getLeft();
277+
$distance = $newLeftPosition - $leaf->getLeft();
247278
$tempPos = $leaf->getLeft();
248279

249280
$this->connection->beginTransaction();
250281

251282
// Calculate depth difference.
252-
$newLeaf = $this->getLeafAtPosition($newLeftPostion);
283+
$newLeaf = $this->getLeafAtPosition($newLeftPosition);
253284
$depthDiff = $newLeaf->getDepth() - $leaf->getDepth();
254285

255286
// Backwards movement must account for new space.
@@ -260,11 +291,11 @@ public function moveSubTree($newLeftPostion, Leaf $leaf) {
260291

261292
// Create new space for subtree.
262293
$this->connection->executeUpdate('UPDATE tree SET nested_left = nested_left + ? WHERE nested_left >= ?',
263-
[$width, $newLeftPostion]
294+
[$width, $newLeftPosition]
264295
);
265296

266297
$this->connection->executeUpdate('UPDATE tree SET nested_right = nested_right + ? WHERE nested_right >= ?',
267-
[$width, $newLeftPostion]
298+
[$width, $newLeftPosition]
268299
);
269300

270301
// Move subtree into new space.

tests/Functional/DbalNestedSetTest.php

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,17 @@ public function testDeleteSubTree() {
235235
}
236236

237237
/**
238-
* Tests moving a sub-tree.
238+
* Tests moving a sub-tree under a parent leaf.
239239
*/
240-
public function testMoveSubTree() {
240+
public function testMoveSubTreeBelow() {
241241
print "BEFORE:" . PHP_EOL;
242242
$tree = $this->nestedSet->getTree();
243243
$this->printTree($tree);
244244

245+
$parent = $this->nestedSet->getLeaf(1, 1);
245246
$leaf = $this->nestedSet->getLeaf(7, 1);
246247

247-
$newPosition = 2;
248-
$this->nestedSet->moveSubTree($newPosition, $leaf);
248+
$this->nestedSet->moveSubTreeBelow($parent, $leaf);
249249

250250
print "AFTER:" . PHP_EOL;
251251
$tree = $this->nestedSet->getTree();
@@ -276,6 +276,48 @@ public function testMoveSubTree() {
276276

277277
}
278278

279+
/**
280+
* Tests moving a sub-tree before a target leaf.
281+
*/
282+
public function testMoveSubTreeBefore() {
283+
print "BEFORE:" . PHP_EOL;
284+
$tree = $this->nestedSet->getTree();
285+
$this->printTree($tree);
286+
287+
$target = $this->nestedSet->getLeaf(4, 1);
288+
$leaf = $this->nestedSet->getLeaf(7, 1);
289+
290+
$this->nestedSet->moveSubTreeBefore($target, $leaf);
291+
292+
print "AFTER:" . PHP_EOL;
293+
$tree = $this->nestedSet->getTree();
294+
$this->printTree($tree);
295+
296+
// Check leaf is in new position.
297+
$leaf = $this->nestedSet->getLeaf(7, 1);
298+
$this->assertEquals(3, $leaf->getLeft());
299+
$this->assertEquals(8, $leaf->getRight());
300+
$this->assertEquals(2, $leaf->getDepth());
301+
302+
// Check children are in new position.
303+
$leaf = $this->nestedSet->getLeaf(10, 1);
304+
$this->assertEquals(4, $leaf->getLeft());
305+
$this->assertEquals(5, $leaf->getRight());
306+
$this->assertEquals(3, $leaf->getDepth());
307+
308+
$leaf = $this->nestedSet->getLeaf(11, 1);
309+
$this->assertEquals(6, $leaf->getLeft());
310+
$this->assertEquals(7, $leaf->getRight());
311+
$this->assertEquals(3, $leaf->getDepth());
312+
313+
// Check old parent is updated.
314+
$leaf = $this->nestedSet->getLeaf(3, 1);
315+
$this->assertEquals(16, $leaf->getLeft());
316+
$this->assertEquals(21, $leaf->getRight());
317+
$this->assertEquals(1, $leaf->getDepth());
318+
319+
}
320+
279321
/**
280322
* Creates the table.
281323
*/

0 commit comments

Comments
 (0)