mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
Allow setting level (depth) of tree nodes on save.
Backported from 3.0.
This commit is contained in:
parent
18246daf17
commit
6ad68ae1e2
3 changed files with 123 additions and 6 deletions
|
@ -44,7 +44,7 @@ class TreeBehavior extends ModelBehavior {
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_defaults = array(
|
protected $_defaults = array(
|
||||||
'parent' => 'parent_id', 'left' => 'lft', 'right' => 'rght',
|
'parent' => 'parent_id', 'left' => 'lft', 'right' => 'rght', 'level' => null,
|
||||||
'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false, 'recursive' => -1
|
'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false, 'recursive' => -1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -97,10 +97,47 @@ class TreeBehavior extends ModelBehavior {
|
||||||
}
|
}
|
||||||
} elseif ($this->settings[$Model->alias]['__parentChange']) {
|
} elseif ($this->settings[$Model->alias]['__parentChange']) {
|
||||||
$this->settings[$Model->alias]['__parentChange'] = false;
|
$this->settings[$Model->alias]['__parentChange'] = false;
|
||||||
|
if ($level) {
|
||||||
|
$this->_setChildrenLevel($Model, $Model->id);
|
||||||
|
}
|
||||||
return $this->_setParent($Model, $Model->data[$Model->alias][$parent]);
|
return $this->_setParent($Model, $Model->data[$Model->alias][$parent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set level for descendents.
|
||||||
|
*
|
||||||
|
* @param Model $Model Model using this behavior.
|
||||||
|
* @param int|string $id Record ID
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function _setChildrenLevel($Model, $id) {
|
||||||
|
$settings = $Model->Behaviors->Tree->settings[$Model->alias];
|
||||||
|
$primaryKey = $Model->primaryKey;
|
||||||
|
$depths = array($id => (int)$Model->data[$Model->alias][$settings['level']]);
|
||||||
|
|
||||||
|
$children = $Model->children(
|
||||||
|
$id,
|
||||||
|
false,
|
||||||
|
array($primaryKey, $settings['parent'], $settings['level']),
|
||||||
|
$settings['left'],
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
-1
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($children as $node) {
|
||||||
|
$parentIdValue = $node[$Model->alias][$settings['parent']];
|
||||||
|
$depth = (int)$depths[$parentIdValue] + 1;
|
||||||
|
$depths[$node[$Model->alias][$primaryKey]] = $depth;
|
||||||
|
|
||||||
|
$Model->updateAll(
|
||||||
|
array($settings['level'] => $depth),
|
||||||
|
array($primaryKey => $node[$Model->alias][$primaryKey])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs before a find() operation
|
* Runs before a find() operation
|
||||||
*
|
*
|
||||||
|
@ -182,8 +219,13 @@ class TreeBehavior extends ModelBehavior {
|
||||||
extract($this->settings[$Model->alias]);
|
extract($this->settings[$Model->alias]);
|
||||||
|
|
||||||
$this->_addToWhitelist($Model, array($left, $right));
|
$this->_addToWhitelist($Model, array($left, $right));
|
||||||
|
if ($level) {
|
||||||
|
$this->_addToWhitelist($Model, $level);
|
||||||
|
}
|
||||||
|
$parentIsSet = array_key_exists($parent, $Model->data[$Model->alias]);
|
||||||
|
|
||||||
if (!$Model->id || !$Model->exists()) {
|
if (!$Model->id || !$Model->exists()) {
|
||||||
if (array_key_exists($parent, $Model->data[$Model->alias]) && $Model->data[$Model->alias][$parent]) {
|
if ($parentIsSet && $Model->data[$Model->alias][$parent]) {
|
||||||
$parentNode = $this->_getNode($Model, $Model->data[$Model->alias][$parent]);
|
$parentNode = $this->_getNode($Model, $Model->data[$Model->alias][$parent]);
|
||||||
if (!$parentNode) {
|
if (!$parentNode) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -191,22 +233,31 @@ class TreeBehavior extends ModelBehavior {
|
||||||
|
|
||||||
$Model->data[$Model->alias][$left] = 0;
|
$Model->data[$Model->alias][$left] = 0;
|
||||||
$Model->data[$Model->alias][$right] = 0;
|
$Model->data[$Model->alias][$right] = 0;
|
||||||
|
if ($level) {
|
||||||
|
$Model->data[$Model->alias][$level] = (int)$parentNode[$Model->alias][$level] + 1;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$edge = $this->_getMax($Model, $scope, $right, $recursive);
|
$edge = $this->_getMax($Model, $scope, $right, $recursive);
|
||||||
$Model->data[$Model->alias][$left] = $edge + 1;
|
$Model->data[$Model->alias][$left] = $edge + 1;
|
||||||
$Model->data[$Model->alias][$right] = $edge + 2;
|
$Model->data[$Model->alias][$right] = $edge + 2;
|
||||||
|
if ($level) {
|
||||||
|
$Model->data[$Model->alias][$level] = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists($parent, $Model->data[$Model->alias])) {
|
if ($parentIsSet) {
|
||||||
if ($Model->data[$Model->alias][$parent] != $Model->field($parent)) {
|
if ($Model->data[$Model->alias][$parent] != $Model->field($parent)) {
|
||||||
$this->settings[$Model->alias]['__parentChange'] = true;
|
$this->settings[$Model->alias]['__parentChange'] = true;
|
||||||
}
|
}
|
||||||
if (!$Model->data[$Model->alias][$parent]) {
|
if (!$Model->data[$Model->alias][$parent]) {
|
||||||
$Model->data[$Model->alias][$parent] = null;
|
$Model->data[$Model->alias][$parent] = null;
|
||||||
$this->_addToWhitelist($Model, $parent);
|
$this->_addToWhitelist($Model, $parent);
|
||||||
|
if ($level) {
|
||||||
|
$Model->data[$Model->alias][$level] = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +279,9 @@ class TreeBehavior extends ModelBehavior {
|
||||||
if ($node[$Model->primaryKey] === $parentNode[$Model->primaryKey]) {
|
if ($node[$Model->primaryKey] === $parentNode[$Model->primaryKey]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ($level) {
|
||||||
|
$Model->data[$Model->alias][$level] = (int)$parentNode[$level] + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -242,10 +296,14 @@ class TreeBehavior extends ModelBehavior {
|
||||||
*/
|
*/
|
||||||
protected function _getNode(Model $Model, $id) {
|
protected function _getNode(Model $Model, $id) {
|
||||||
$settings = $this->settings[$Model->alias];
|
$settings = $this->settings[$Model->alias];
|
||||||
|
$fields = array($Model->primaryKey, $settings['parent'], $settings['left'], $settings['right']);
|
||||||
|
if ($settings['level']) {
|
||||||
|
$fields[] = $settings['level'];
|
||||||
|
}
|
||||||
|
|
||||||
return $Model->find('first', array(
|
return $Model->find('first', array(
|
||||||
'conditions' => array($Model->escapeField() => $id),
|
'conditions' => array($Model->escapeField() => $id),
|
||||||
'fields' => array($Model->primaryKey, $settings['parent'], $settings['left'], $settings['right']),
|
'fields' => $fields,
|
||||||
'recursive' => $settings['recursive'],
|
'recursive' => $settings['recursive'],
|
||||||
'order' => false,
|
'order' => false,
|
||||||
));
|
));
|
||||||
|
|
|
@ -46,7 +46,8 @@ class TreeBehaviorNumberTest extends CakeTestCase {
|
||||||
'modelClass' => 'NumberTree',
|
'modelClass' => 'NumberTree',
|
||||||
'leftField' => 'lft',
|
'leftField' => 'lft',
|
||||||
'rightField' => 'rght',
|
'rightField' => 'rght',
|
||||||
'parentField' => 'parent_id'
|
'parentField' => 'parent_id',
|
||||||
|
'level' => 'level'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1527,4 +1528,61 @@ class TreeBehaviorNumberTest extends CakeTestCase {
|
||||||
);
|
);
|
||||||
$this->assertEquals($expected, $result);
|
$this->assertEquals($expected, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLevel() {
|
||||||
|
extract($this->settings);
|
||||||
|
$this->Tree = new $modelClass();
|
||||||
|
$this->Tree->Behaviors->attach('Tree', array('level' => 'level'));
|
||||||
|
$this->Tree->initialize(2, 2);
|
||||||
|
|
||||||
|
$result = $this->Tree->findByName('1. Root');
|
||||||
|
$this->assertEquals(0, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
$result = $this->Tree->findByName('1.1');
|
||||||
|
$this->assertEquals(1, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
$result = $this->Tree->findByName('1.2.2');
|
||||||
|
$this->assertEquals(2, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
$result = $this->Tree->findByName('1.2.1');
|
||||||
|
$this->assertEquals(2, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
// Save with parent_id not set
|
||||||
|
$this->Tree->save(array('id' => $result[$modelClass]['id'], 'name' => 'foo'));
|
||||||
|
$result = $this->Tree->findByName('foo');
|
||||||
|
$this->assertEquals(2, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
// Save with parent_id not changed
|
||||||
|
$this->Tree->save(array(
|
||||||
|
'id' => $result[$modelClass]['id'],
|
||||||
|
'parent_id' => $result[$modelClass]['parent_id'],
|
||||||
|
'name' => 'foo2'
|
||||||
|
));
|
||||||
|
$result = $this->Tree->findByName('foo2');
|
||||||
|
$this->assertEquals(2, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
// Save with parent_id changed
|
||||||
|
$result = $this->Tree->findByName('1.1');
|
||||||
|
$this->Tree->save(array(
|
||||||
|
'id' => $result[$modelClass]['id'],
|
||||||
|
'parent_id' => ''
|
||||||
|
));
|
||||||
|
$result = $this->Tree->findByName('1.1');
|
||||||
|
$this->assertEquals(0, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
$result = $this->Tree->findByName('1.1.2');
|
||||||
|
$this->assertEquals(1, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
$parent = $this->Tree->findByName('1.1.2');
|
||||||
|
$result = $this->Tree->findByName('1.2');
|
||||||
|
$this->Tree->save(array(
|
||||||
|
'id' => $result[$modelClass]['id'],
|
||||||
|
'parent_id' => $parent[$modelClass]['id']
|
||||||
|
));
|
||||||
|
$result = $this->Tree->findByName('1.2');
|
||||||
|
$this->assertEquals(2, $result[$modelClass][$level]);
|
||||||
|
|
||||||
|
$result = $this->Tree->findByName('1.2.2');
|
||||||
|
$this->assertEquals(3, $result[$modelClass][$level]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ class NumberTreeFixture extends CakeTestFixture {
|
||||||
'name' => array('type' => 'string', 'null' => false),
|
'name' => array('type' => 'string', 'null' => false),
|
||||||
'parent_id' => 'integer',
|
'parent_id' => 'integer',
|
||||||
'lft' => array('type' => 'integer', 'null' => false),
|
'lft' => array('type' => 'integer', 'null' => false),
|
||||||
'rght' => array('type' => 'integer', 'null' => false)
|
'rght' => array('type' => 'integer', 'null' => false),
|
||||||
|
'level' => array('type' => 'integer', 'null' => false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue