Browse Source

Fully implemented moving a subtree as a new root

Jose Lorenzo Rodriguez 12 years ago
parent
commit
6f5f4aa5f8

+ 17 - 5
src/Model/Behavior/TreeBehavior.php

@@ -170,12 +170,24 @@ class TreeBehavior extends Behavior {
 		$edge = $this->_getMax();
 		$right = $entity->get($config['right']);
 		$left = $entity->get($config['left']);
-		$internalLeft = $left + 1;
-		$internalRight = $right - 1;
+		$diff = $right - $left;
 
-		$entity->set($config['left'], $edge + 1);
-		$entity->set($config['right'], $edge + $right - 1);
-		$this->_sync($edge - 1, '+', "BETWEEN {$internalLeft} AND {$internalRight}");
+		if ($right - $left > 1) {
+			//Correcting internal subtree
+			$internalLeft = $left + 1;
+			$internalRight = $right - 1;
+			$this->_sync($edge - $diff - $left, '+', "BETWEEN {$internalLeft} AND {$internalRight}", true);
+		}
+
+		$this->_sync($diff + 1, '-', "BETWEEN {$right} AND {$edge}");
+
+		if ($right - $left > 1) {
+			//Inverting sign again
+			$this->_sync('-1', '*', "< 0");
+		}
+
+		$entity->set($config['left'], $edge - $diff);
+		$entity->set($config['right'], $edge);
 	}
 
 	public function findPath($query, $options) {

+ 13 - 7
tests/TestCase/Model/Behavior/TreeBehaviorTest.php

@@ -461,7 +461,7 @@ class TreeBehaviorTest extends TestCase {
 	}
 
 /**
- * Tests moving as a new root
+ * Tests moving a subtree as a new root
  *
  * @return void
  */
@@ -471,13 +471,19 @@ class TreeBehaviorTest extends TestCase {
 		$entity = $table->get(2);
 		$entity->parent_id = null;
 		$this->assertSame($entity, $table->save($entity));
-		$this->assertEquals(23, $entity->lft);
-		$this->assertEquals(30, $entity->rght);
+		$this->assertEquals(15, $entity->lft);
+		$this->assertEquals(22, $entity->rght);
 
-		$result = $table->find()->order('lft')->hydrate(false)->toArray();
-		$table->recover();
-		$expected = $table->find()->order('lft')->hydrate(false)->toArray();
-		$this->assertEquals($expected, $result);
+		$result = $table->find()->order('lft')->hydrate(false);
+		$expected = [1, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5];
+		$this->assertEquals($expected, $result->extract('id')->toArray());
+		$numbers = [];
+		$result->each(function($v) use (&$numbers) {
+			$numbers[] = $v['lft'];
+			$numbers[] = $v['rght'];
+		});
+		sort($numbers);
+		$this->assertEquals(range(1, 22), $numbers);
 	}
 
 }