Browse Source

Implemented TreeBehavior::recover()

Jose Lorenzo Rodriguez 12 years ago
parent
commit
9efddaa007

+ 34 - 0
src/Model/Behavior/TreeBehavior.php

@@ -269,6 +269,40 @@ class TreeBehavior extends Behavior {
 		return true;
 	}
 
+	public function recover() {
+		$this->_table->connection()->transactional(function() {
+			$this->_recoverTree();
+		});
+	}
+
+	protected function _recoverTree($counter = 0, $parentId = null) {
+		$config = $this->config();
+		list($parent, $left, $right) = [$config['parent'], $config['left'], $config['right']];
+		$pk = (array)$this->_table->primaryKey();
+
+		$query = $this->_scope($this->_table->query())
+			->select($pk)
+			->where(function($exp) use ($parentId, $parent) {
+				return $parentId === null ? $exp->isNull($parent) : $exp->eq($parent, $parentId);
+			})
+			->order($pk)
+			->hydrate(false)
+			->bufferResults(false);
+
+		$leftCounter = $counter;
+		foreach ($query as $row) {
+			$counter++;
+			$counter = $this->_recoverTree($counter, $row[$pk[0]]);
+		}
+
+		$this->_table->updateAll(
+			[$left => $leftCounter, $right => $counter + 1],
+			[$pk[0] => $parentId]
+		);
+
+		return $counter + 1;
+	}
+
 /**
  * Get the maximum index value in the table.
  *

+ 2 - 2
tests/Fixture/MenuLinkTreeFixture.php

@@ -36,8 +36,8 @@ class MenuLinkTreeFixture extends TestFixture {
 	public $fields = array(
 		'id' => ['type' => 'integer'],
 		'menu' => ['type' => 'string', 'null' => false],
-		'lft' => ['type' => 'integer', 'null' => false],
-		'rght' => ['type' => 'integer', 'null' => false],
+		'lft' => ['type' => 'integer'],
+		'rght' => ['type' => 'integer'],
 		'parent_id' => 'integer',
 		'url' => ['type' => 'string', 'null' => false],
 		'title' => ['type' => 'string', 'null' => false],

+ 4 - 3
tests/Fixture/NumberTreeFixture.php

@@ -37,8 +37,8 @@ class NumberTreeFixture extends TestFixture {
 		'id' => ['type' => 'integer'],
 		'name' => ['type' => 'string', 'null' => false],
 		'parent_id' => 'integer',
-		'lft' => ['type' => 'integer', 'null' => false],
-		'rght' => ['type' => 'integer', 'null' => false],
+		'lft' => ['type' => 'integer'],
+		'rght' => ['type' => 'integer'],
 		'_constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]]
 	);
 
@@ -55,6 +55,7 @@ class NumberTreeFixture extends TestFixture {
  *				- flash:8
  *			- cd:9
  *			- radios:10
+ *	- alien ware: 11
  *
  * @var array
  */
@@ -134,7 +135,7 @@ class NumberTreeFixture extends TestFixture {
 			'name' => 'alien hardware',
 			'parent_id' => null,
 			'lft' => '21',
-			'rght' => '21'
+			'rght' => '22'
 		)
 	);
 

+ 40 - 0
tests/TestCase/Model/Behavior/TreeBehaviorTest.php

@@ -251,4 +251,44 @@ class TreeBehaviorTest extends TestCase {
 		$table->addBehavior('Tree', ['scope' => ['menu' => 'main-menu']]);
 		$table->moveDown(500, 1);
 	}
+
+/**
+ * Tests the recover function
+ *
+ * @return void
+ */
+	public function testRecover() {
+		$table = TableRegistry::get('NumberTrees');
+		$table->addBehavior('Tree');
+		$expected = $table->find()->order('lft')->hydrate(false)->toArray();
+		$table->updateAll(['lft' => null, 'rght' => null], []);
+		$table->recover();
+		$result = $table->find()->order('lft')->hydrate(false)->toArray();
+		$this->assertEquals($expected, $result);
+	}
+
+/**
+ * Tests the recover function with a custom scope
+ *
+ * @return void
+ */
+	public function testRecoverScoped() {
+		$table = TableRegistry::get('MenuLinkTrees');
+		$table->addBehavior('Tree', ['scope' => ['menu' => 'main-menu']]);
+		$expected = $table->find()
+			->where(['menu' => 'main-menu'])
+			->order('lft')
+			->hydrate(false)
+			->toArray();
+
+		$table->updateAll(['lft' => null, 'rght' => null], ['menu' => 'main-menu']);
+		$table->recover();
+		$result = $table->find()
+			->where(['menu' => 'main-menu'])
+			->order('lft')
+			->hydrate(false)
+			->toArray();
+		$this->assertEquals($expected, $result);
+	}
+
 }