Skip to content

Commit c793488

Browse files
committed
Adds insert before and after
1 parent 67e8516 commit c793488

File tree

3 files changed

+114
-29
lines changed

3 files changed

+114
-29
lines changed

src/NestedSetInterface.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,36 @@ interface NestedSetInterface {
1616
* The node to insert. Only id and revision ID are required.
1717
*
1818
* @return \PNX\NestedSet\Node
19-
* Returns a new child with position values set.
19+
* Returns a new node with position values set.
2020
*/
2121
public function insertNodeBelow(Node $target, Node $node);
2222

23+
/**
24+
* Inserts a node before the target node.
25+
*
26+
* @param \PNX\NestedSet\Node $target
27+
* The target node to insert before.
28+
* @param \PNX\NestedSet\Node $node
29+
* The node to insert. Only id and revision ID are required.
30+
*
31+
* @return \PNX\NestedSet\Node
32+
* Returns a node with position values set.
33+
*/
34+
public function insertNodeBefore(Node $target, Node $node);
35+
36+
/**
37+
* Inserts a node after the target node.
38+
*
39+
* @param \PNX\NestedSet\Node $target
40+
* The target node to insert after.
41+
* @param \PNX\NestedSet\Node $node
42+
* The node to insert. Only id and revision ID are required.
43+
*
44+
* @return \PNX\NestedSet\Node
45+
* Returns a node with position values set.
46+
*/
47+
public function insertNodeAfter(Node $target, Node $node);
48+
2349
/**
2450
* Deletes a node and moves descendants up a level.
2551
*

src/Storage/DbalNestedSet.php

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,29 @@ public function __construct(Connection $connection) {
3333
* {@inheritdoc}
3434
*/
3535
public function insertNodeBelow(Node $target, Node $node) {
36-
$newLeftPosition = $target->getRight() - 1;
36+
$newLeftPosition = $target->getRight();
3737
$depth = $target->getDepth() + 1;
3838
return $this->insertNodeAtPostion($newLeftPosition, $depth, $node);
3939
}
4040

41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function insertNodeBefore(Node $target, Node $node) {
45+
$newLeftPosition = $target->getLeft();
46+
$depth = $target->getDepth();
47+
return $this->insertNodeAtPostion($newLeftPosition, $depth, $node);
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
public function insertNodeAfter(Node $target, Node $node) {
54+
$newLeftPosition = $target->getRight() + 1;
55+
$depth = $target->getDepth();
56+
return $this->insertNodeAtPostion($newLeftPosition, $depth, $node);
57+
}
58+
4159
/**
4260
* Inserts a node to the target position.
4361
*
@@ -59,20 +77,20 @@ protected function insertNodeAtPostion($newLeftPosition, $depth, Node $node) {
5977
try {
6078
$this->connection->beginTransaction();
6179

62-
// Move everything across two places.
63-
$this->connection->executeUpdate('UPDATE tree SET nested_right = nested_right + 2 WHERE nested_right > ?',
80+
// Make space for inserting node.
81+
$this->connection->executeUpdate('UPDATE tree SET nested_right = nested_right + 2 WHERE nested_right >= ?',
6482
[$newLeftPosition]
6583
);
66-
$this->connection->executeUpdate('UPDATE tree SET nested_left = nested_left + 2 WHERE nested_left > ?',
84+
$this->connection->executeUpdate('UPDATE tree SET nested_left = nested_left + 2 WHERE nested_left >= ?',
6785
[$newLeftPosition]
6886
);
6987

7088
// Create a new node object to be returned.
7189
$newNode = new Node(
7290
$node->getId(),
7391
$node->getRevisionId(),
92+
$newLeftPosition,
7493
$newLeftPosition + 1,
75-
$newLeftPosition + 2,
7694
$depth
7795
);
7896

@@ -155,6 +173,23 @@ public function findAncestors(Node $node) {
155173
return $ancestors;
156174
}
157175

176+
/**
177+
* Finds the root node for this node.
178+
*
179+
* @param \PNX\NestedSet\Node $node
180+
* The start node.
181+
*
182+
* @return \PNX\NestedSet\Node
183+
* The root node.
184+
*/
185+
public function findRoot(Node $node) {
186+
$ancestors = $this->findAncestors($node);
187+
if (!empty($ancestors)) {
188+
return array_shift($ancestors);
189+
}
190+
return NULL;
191+
}
192+
158193
/**
159194
* {@inheritdoc}
160195
*/

tests/Functional/DbalNestedSetTest.php

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ public function testFindParent() {
160160
}
161161

162162
/**
163-
* Tests adding a node.
163+
* Tests inserting a node below a parent with existing children.
164164
*/
165-
public function testAddNodeWithExistingChildren() {
165+
public function testInsertNodeBelowWithExistingChildren() {
166166

167167
$parent = $this->nestedSet->getNode(3, 1);
168168
$child = new Node(12, 1);
@@ -182,14 +182,13 @@ public function testAddNodeWithExistingChildren() {
182182
}
183183

184184
/**
185-
* Tests adding a node.
185+
* Tests inserting a node below a parent with no children.
186186
*/
187-
public function testAddNodeWithNoChildren() {
187+
public function testInsertNodeBelowWithNoChildren() {
188+
$target = $this->nestedSet->getNode(6, 1);
189+
$node = new Node(13, 1);
188190

189-
$parent = $this->nestedSet->getNode(6, 1);
190-
$child = new Node(13, 1);
191-
192-
$newNode = $this->nestedSet->insertNodeBelow($parent, $child);
191+
$newNode = $this->nestedSet->insertNodeBelow($target, $node);
193192

194193
// Should be inserted below 6 with depth 4.
195194
$this->assertEquals(7, $newNode->getLeft());
@@ -202,6 +201,46 @@ public function testAddNodeWithNoChildren() {
202201
$this->assertEquals(9, $newParent->getRight());
203202
}
204203

204+
/**
205+
* Tests inserting a node before another sibling.
206+
*/
207+
public function testInsertNodeBefore() {
208+
$parent = $this->nestedSet->getNode(6, 1);
209+
$child = new Node(14, 1);
210+
211+
$newNode = $this->nestedSet->insertNodeBefore($parent, $child);
212+
213+
// Should be inserted below 6 with depth 4.
214+
$this->assertEquals(6, $newNode->getLeft());
215+
$this->assertEquals(7, $newNode->getRight());
216+
$this->assertEquals(3, $newNode->getDepth());
217+
218+
// Parent node right should have incremented.
219+
$newParent = $this->nestedSet->getNode(4, 1);
220+
$this->assertEquals(3, $newParent->getLeft());
221+
$this->assertEquals(10, $newParent->getRight());
222+
}
223+
224+
/**
225+
* Tests inserting a node after another sibling.
226+
*/
227+
public function testInsertNodeAfter() {
228+
$parent = $this->nestedSet->getNode(5, 1);
229+
$child = new Node(15, 1);
230+
231+
$newNode = $this->nestedSet->insertNodeAfter($parent, $child);
232+
233+
// Should be inserted below 6 with depth 4.
234+
$this->assertEquals(6, $newNode->getLeft());
235+
$this->assertEquals(7, $newNode->getRight());
236+
$this->assertEquals(3, $newNode->getDepth());
237+
238+
// Parent node right should have incremented.
239+
$newParent = $this->nestedSet->getNode(4, 1);
240+
$this->assertEquals(3, $newParent->getLeft());
241+
$this->assertEquals(10, $newParent->getRight());
242+
}
243+
205244
/**
206245
* Tests deleting a node.
207246
*/
@@ -226,7 +265,6 @@ public function testDeleteNode() {
226265
$this->assertEquals(2, $node->getDepth());
227266

228267
$tree = $this->nestedSet->getTree();
229-
$this->printTree($tree);
230268
}
231269

232270
/**
@@ -254,19 +292,12 @@ public function testDeleteSubTree() {
254292
* Tests moving a sub-tree under a parent node.
255293
*/
256294
public function testMoveSubTreeBelow() {
257-
print "BEFORE:" . PHP_EOL;
258-
$tree = $this->nestedSet->getTree();
259-
$this->printTree($tree);
260295

261296
$parent = $this->nestedSet->getNode(1, 1);
262297
$node = $this->nestedSet->getNode(7, 1);
263298

264299
$this->nestedSet->moveSubTreeBelow($parent, $node);
265300

266-
print "AFTER:" . PHP_EOL;
267-
$tree = $this->nestedSet->getTree();
268-
$this->printTree($tree);
269-
270301
// Check node is in new position.
271302
$node = $this->nestedSet->getNode(7, 1);
272303
$this->assertEquals(2, $node->getLeft());
@@ -296,19 +327,12 @@ public function testMoveSubTreeBelow() {
296327
* Tests moving a sub-tree before a target node.
297328
*/
298329
public function testMoveSubTreeBefore() {
299-
print "BEFORE:" . PHP_EOL;
300-
$tree = $this->nestedSet->getTree();
301-
$this->printTree($tree);
302330

303331
$target = $this->nestedSet->getNode(4, 1);
304332
$node = $this->nestedSet->getNode(7, 1);
305333

306334
$this->nestedSet->moveSubTreeBefore($target, $node);
307335

308-
print "AFTER:" . PHP_EOL;
309-
$tree = $this->nestedSet->getTree();
310-
$this->printTree($tree);
311-
312336
// Check node is in new position.
313337
$node = $this->nestedSet->getNode(7, 1);
314338
$this->assertEquals(3, $node->getLeft());

0 commit comments

Comments
 (0)