updated tree behavior addressing most of the issues related to its use with postgreSQL and sqlite

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6995 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
AD7six 2008-05-21 20:03:12 +00:00
parent c0ff1b6fd1
commit 84eb4ae36d

View file

@ -40,7 +40,7 @@ class TreeBehavior extends ModelBehavior {
var $_defaults = array( var $_defaults = array(
'parent' => 'parent_id', 'left' => 'lft', 'right' => 'rght', 'parent' => 'parent_id', 'left' => 'lft', 'right' => 'rght',
'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false 'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false, 'recursive' => -1
); );
function setup(&$model, $config = array()) { function setup(&$model, $config = array()) {
@ -53,6 +53,7 @@ class TreeBehavior extends ModelBehavior {
$data = $model->getAssociated($settings['scope']); $data = $model->getAssociated($settings['scope']);
$parent =& $model->{$settings['scope']}; $parent =& $model->{$settings['scope']};
$settings['scope'] = $model->alias . '.' . $data['foreignKey'] . ' = ' . $parent->alias . '.' . $parent->primaryKey; $settings['scope'] = $model->alias . '.' . $data['foreignKey'] . ' = ' . $parent->alias . '.' . $parent->primaryKey;
$settings['recursive'] = 0;
} }
$this->settings[$model->alias] = $settings; $this->settings[$model->alias] = $settings;
} }
@ -61,7 +62,10 @@ class TreeBehavior extends ModelBehavior {
*/ */
function setScope(&$model, $scope) { function setScope(&$model, $scope) {
trigger_error(__('(TreeBehavior::setScope) Deprecated - Use BehaviorCollection::attach() to re-attach with new settings', true), E_USER_WARNING); trigger_error(__('(TreeBehavior::setScope) Deprecated - Use BehaviorCollection::attach() to re-attach with new settings', true), E_USER_WARNING);
$this->settings[$model->name]['scope'] = $scope; $this->settings[$model->alias]['scope'] = $scope;
if ($this->settings[$model->alias]['recursive'] < 0) {
$this->settings[$model->alias]['recursive'] = 0;
}
} }
/** /**
* After save method. Called after all saves * After save method. Called after all saves
@ -77,7 +81,7 @@ class TreeBehavior extends ModelBehavior {
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
if ($created) { if ($created) {
if ((isset($model->data[$model->alias][$parent])) && $model->data[$model->alias][$parent]) { if ((isset($model->data[$model->alias][$parent])) && $model->data[$model->alias][$parent]) {
return $this->_setParent($model, $model->data[$model->alias][$parent]); return $this->_setParent($model, $model->data[$model->alias][$parent], $created);
} }
} elseif ($__parentChange) { } elseif ($__parentChange) {
$this->settings[$model->alias]['__parentChange'] = false; $this->settings[$model->alias]['__parentChange'] = false;
@ -135,21 +139,23 @@ class TreeBehavior extends ModelBehavior {
unset($model->data[$model->alias][$model->primaryKey]); unset($model->data[$model->alias][$model->primaryKey]);
} }
$this->_addToWhitelist($model, array($left, $right));
if (!$model->id) { if (!$model->id) {
if ((!array_key_exists($parent, $model->data[$model->alias])) || (!$model->data[$model->alias][$parent])) { if (array_key_exists($parent, $model->data[$model->alias]) && $model->data[$model->alias][$parent]) {
$edge = $this->__getMax($model, $scope, $right);
$model->data[$model->alias][$left] = $edge + 1;
$model->data[$model->alias][$right] = $edge + 2;
$this->_addToWhitelist($model, array($left, $right));
} else {
$parentNode = $model->find('first', array( $parentNode = $model->find('first', array(
'conditions' => array($scope, $model->escapeField() => $model->data[$model->alias][$parent]), 'conditions' => array($scope, $model->escapeField() => $model->data[$model->alias][$parent]),
'fields' => array($model->primaryKey), 'recursive' => -1 'fields' => array($model->primaryKey, $right), 'recursive' => $recursive
)); ));
if (!$parentNode) { if (!$parentNode) {
return false; return false;
} }
list($parentNode) = array_values($parentNode);
$model->data[$model->alias][$left] = 0; //$parentNode[$right];
$model->data[$model->alias][$right] = 0; //$parentNode[$right] + 1;
} else {
$edge = $this->__getMax($model, $scope, $right, $recursive);
$model->data[$model->alias][$left] = $edge + 1;
$model->data[$model->alias][$right] = $edge + 2;
} }
} elseif (array_key_exists($parent, $model->data[$model->alias])) { } elseif (array_key_exists($parent, $model->data[$model->alias])) {
if ($model->data[$model->alias][$parent] != $model->field($parent)) { if ($model->data[$model->alias][$parent] != $model->field($parent)) {
@ -161,12 +167,12 @@ class TreeBehavior extends ModelBehavior {
} else { } else {
list($node) = array_values($model->find('first', array( list($node) = array_values($model->find('first', array(
'conditions' => array($scope,$model->escapeField() => $model->id), 'conditions' => array($scope,$model->escapeField() => $model->id),
'fields' => array($model->primaryKey, $parent, $left, $right ), 'recursive' => -1) 'fields' => array($model->primaryKey, $parent, $left, $right ), 'recursive' => $recursive)
)); ));
$parentNode = $model->find('first', array( $parentNode = $model->find('first', array(
'conditions' => array($scope, $model->escapeField() => $model->data[$model->alias][$parent]), 'conditions' => array($scope, $model->escapeField() => $model->data[$model->alias][$parent]),
'fields' => array($model->primaryKey, $left, $right), 'recursive' => -1 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive
)); ));
if (!$parentNode) { if (!$parentNode) {
return false; return false;
@ -195,6 +201,9 @@ class TreeBehavior extends ModelBehavior {
* @access public * @access public
*/ */
function childcount(&$model, $id = null, $direct = false) { function childcount(&$model, $id = null, $direct = false) {
if (is_array($id)) {
extract (array_merge($id, array('id' => null)));
}
if ($id === null && $model->id) { if ($id === null && $model->id) {
$id = $model->id; $id = $model->id;
} elseif (!$id) { } elseif (!$id) {
@ -211,7 +220,7 @@ class TreeBehavior extends ModelBehavior {
} elseif (!empty ($model->data)) { } elseif (!empty ($model->data)) {
$data = $model->data[$model->alias]; $data = $model->data[$model->alias];
} else { } else {
list($data) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $id), 'recursive' => -1))); list($data) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $id), 'recursive' => $recursive)));
} }
return ($data[$right] - $data[$left] - 1) / 2; return ($data[$right] - $data[$left] - 1) / 2;
} }
@ -232,16 +241,20 @@ class TreeBehavior extends ModelBehavior {
* @return array Array of child nodes * @return array Array of child nodes
* @access public * @access public
*/ */
function children(&$model, $id = null, $direct = false, $fields = null, $order = null, $limit = null, $page = 1, $recursive = -1) { function children(&$model, $id = null, $direct = false, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null) {
if (is_array($id)) {
extract (array_merge($id, array('id' => null)));
}
$overrideRecursive = $recursive;
if ($id === null && $model->id) { if ($id === null && $model->id) {
$id = $model->id; $id = $model->id;
} elseif (!$id) { } elseif (!$id) {
$id = null; $id = null;
} }
$name = $model->alias; $name = $model->alias;
extract($this->settings[$name]); extract($this->settings[$model->alias]);
if ($scope != '1 = 1') { if (!is_null($overrideRecursive)) {
$recursive = 0; $recursive = $overrideRecursive;
} }
if (!$order) { if (!$order) {
$order = $model->alias . '.' . $left . ' asc'; $order = $model->alias . '.' . $left . ' asc';
@ -275,8 +288,15 @@ class TreeBehavior extends ModelBehavior {
* @return array An associative array of records, where the id is the key, and the display field is the value * @return array An associative array of records, where the id is the key, and the display field is the value
* @access public * @access public
*/ */
function generatetreelist(&$model, $conditions = null, $keyPath = null, $valuePath = null, $spacer = '_', $recursive = -1) { function generatetreelist(&$model, $conditions = null, $keyPath = null, $valuePath = null, $spacer = '_', $recursive = null) {
if (is_array($conditions)) {
extract (array_merge($conditions, array('conditions' => null)));
}
$overrideRecursive = $recursive;
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
if (!is_null($overrideRecursive)) {
$recursive = $overrideRecursive;
}
if ($keyPath == null && $valuePath == null && $model->hasField($model->displayField)) { if ($keyPath == null && $valuePath == null && $model->hasField($model->displayField)) {
$fields = array($model->primaryKey, $model->displayField, $left, $right); $fields = array($model->primaryKey, $model->displayField, $left, $right);
@ -325,11 +345,18 @@ class TreeBehavior extends ModelBehavior {
* @return array Array of data for the parent node * @return array Array of data for the parent node
* @access public * @access public
*/ */
function getparentnode(&$model, $id = null, $fields = null, $recursive = -1) { function getparentnode(&$model, $id = null, $fields = null, $recursive = null) {
if (is_array($id)) {
extract (array_merge($id, array('id' => null)));
}
$overrideRecursive = $recursive;
if (empty ($id)) { if (empty ($id)) {
$id = $model->id; $id = $model->id;
} }
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
if (!is_null($overrideRecursive)) {
$recursive = $overrideRecursive;
}
$parentId = $model->read($parent, $id); $parentId = $model->read($parent, $id);
if ($parentId) { if ($parentId) {
@ -351,14 +378,22 @@ class TreeBehavior extends ModelBehavior {
* @return array Array of nodes from top most parent to current node * @return array Array of nodes from top most parent to current node
* @access public * @access public
*/ */
function getpath(&$model, $id = null, $fields = null, $recursive = -1) { function getpath(&$model, $id = null, $fields = null, $recursive = null) {
if (is_array($id)) {
extract (array_merge($id, array('id' => null)));
}
$overrideRecursive = $recursive;
if (empty ($id)) { if (empty ($id)) {
$id = $model->id; $id = $model->id;
} }
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
$result = array_values($model->find('first', array('conditions' => array($model->escapeField() => $id), 'fields' => array($left, $right), 'recursive' => -1))); if (!is_null($overrideRecursive)) {
$recursive = $overrideRecursive;
if (empty($result) || !isset($result[0])) { }
$result = $model->find('first', array('conditions' => array($model->escapeField() => $id), 'fields' => array($left, $right), 'recursive' => $recursive));
if ($result) {
$result = array_values($result);
} else {
return null; return null;
} }
$item = $result[0]; $item = $result[0];
@ -380,6 +415,9 @@ class TreeBehavior extends ModelBehavior {
* @access public * @access public
*/ */
function movedown(&$model, $id = null, $number = 1) { function movedown(&$model, $id = null, $number = 1) {
if (is_array($id)) {
extract (array_merge($id, array('id' => null)));
}
if (!$number) { if (!$number) {
return false; return false;
} }
@ -387,10 +425,6 @@ class TreeBehavior extends ModelBehavior {
$id = $model->id; $id = $model->id;
} }
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
$recursive = -1;
if ($scope != '1 = 1') {
$recursive = 0;
}
list($node) = array_values($model->find('first', array( list($node) = array_values($model->find('first', array(
'conditions' => array($scope, $model->escapeField() => $id), 'conditions' => array($scope, $model->escapeField() => $id),
'fields' => array($model->primaryKey, $left, $right, $parent), 'recursive' => $recursive 'fields' => array($model->primaryKey, $left, $right, $parent), 'recursive' => $recursive
@ -435,6 +469,9 @@ class TreeBehavior extends ModelBehavior {
* @access public * @access public
*/ */
function moveup(&$model, $id = null, $number = 1) { function moveup(&$model, $id = null, $number = 1) {
if (is_array($id)) {
extract (array_merge($id, array('id' => null)));
}
if (!$number) { if (!$number) {
return false; return false;
} }
@ -442,10 +479,6 @@ class TreeBehavior extends ModelBehavior {
$id = $model->id; $id = $model->id;
} }
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
$recursive = -1;
if ($scope != '1 = 1') {
$recursive = 0;
}
list($node) = array_values($model->find('first', array( list($node) = array_values($model->find('first', array(
'conditions' => array($scope, $model->escapeField() => $id), 'conditions' => array($scope, $model->escapeField() => $id),
'fields' => array($model->primaryKey, $left, $right, $parent ), 'recursive' => $recursive 'fields' => array($model->primaryKey, $left, $right, $parent ), 'recursive' => $recursive
@ -496,10 +529,10 @@ class TreeBehavior extends ModelBehavior {
*/ */
function recover(&$model, $mode = 'parent', $missingParentAction = null) { function recover(&$model, $mode = 'parent', $missingParentAction = null) {
if (is_array($mode)) { if (is_array($mode)) {
extract ($mode); extract (array_merge($mode, array('mode' => 'parent')));
} }
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
$model->recursive = -1; $model->recursive = $recursive;
if ($mode == 'parent') { if ($mode == 'parent') {
$model->bindModel(array('belongsTo' => array('VerifyParent' => array( $model->bindModel(array('belongsTo' => array('VerifyParent' => array(
'className' => $model->alias, 'className' => $model->alias,
@ -533,7 +566,7 @@ class TreeBehavior extends ModelBehavior {
foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey, $parent), 'order' => $left)) as $array) { foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey, $parent), 'order' => $left)) as $array) {
$model->create(); $model->create();
$model->id = $array[$model->alias][$model->primaryKey]; $model->id = $array[$model->alias][$model->primaryKey];
$this->_setParent($model, $array[$model->alias][$parent], true); $this->_setParent($model, $array[$model->alias][$parent]);
} }
} else { } else {
foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey, $parent), 'order' => $left)) as $array) { foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey, $parent), 'order' => $left)) as $array) {
@ -570,7 +603,7 @@ class TreeBehavior extends ModelBehavior {
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
$fields = array($model->primaryKey, $field, $left, $right); $fields = array($model->primaryKey, $field, $left, $right);
$sort = $field . ' ' . $order; $sort = $field . ' ' . $order;
$nodes = $model->children($id, true, $fields, $sort, null, null, -1); $nodes = $model->children($id, true, $fields, $sort, null, null, $recursive);
if ($nodes) { if ($nodes) {
foreach ($nodes as $node) { foreach ($nodes as $node) {
$id = $node[$model->alias][$model->primaryKey]; $id = $node[$model->alias][$model->primaryKey];
@ -595,12 +628,12 @@ class TreeBehavior extends ModelBehavior {
* @access public * @access public
*/ */
function removefromtree(&$model, $id = null, $delete = false) { function removefromtree(&$model, $id = null, $delete = false) {
if (empty ($id)) { if (is_array($id)) {
$id = $model->id; extract (array_merge($id, array('id' => null)));
} }
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
list($node) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $id), list($node) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $id),
'fields' => array($model->primaryKey, $left, $right, $parent), 'recursive' => -1)) 'fields' => array($model->primaryKey, $left, $right, $parent), 'recursive' => $recursive))
); );
if ($node[$right] == $node[$left] + 1) { if ($node[$right] == $node[$left] + 1) {
if ($delete) { if ($delete) {
@ -610,7 +643,7 @@ class TreeBehavior extends ModelBehavior {
} }
} elseif ($node[$parent]) { } elseif ($node[$parent]) {
list($parentNode) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $node[$parent]), list($parentNode) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $node[$parent]),
'fields' => array($model->primaryKey, $left, $right), 'recursive' => -1)) 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive))
); );
} else { } else {
$parentNode[$right]= $node[$right] + 1; $parentNode[$right]= $node[$right] + 1;
@ -622,12 +655,12 @@ class TreeBehavior extends ModelBehavior {
if ($delete) { if ($delete) {
$model->updateAll( $model->updateAll(
array($model->escapeField($left) => null, $model->escapeField($right) => null, $model->escapeField($parent) => null), array($model->escapeField($left) => 0, $model->escapeField($right) => 0, $model->escapeField($parent) => null),
array($model->escapeField() => $id) array($model->escapeField() => $id)
); );
return $model->delete($id); return $model->delete($id);
} else { } else {
$edge = $this->__getMax($model, $scope, $right); $edge = $this->__getMax($model, $scope, $right, $recursive);
if ($node[$right] == $edge) { if ($node[$right] == $edge) {
$edge = $edge - 2; $edge = $edge - 2;
} }
@ -667,8 +700,8 @@ class TreeBehavior extends ModelBehavior {
if (!$model->find('count', array('conditions' => $scope))) { if (!$model->find('count', array('conditions' => $scope))) {
return true; return true;
} }
$min = $this->__getMin($model, $scope, $left); $min = $this->__getMin($model, $scope, $left, $recursive);
$edge = $this->__getMax($model, $scope, $right); $edge = $this->__getMax($model, $scope, $right, $recursive);
$errors = array(); $errors = array();
for ($i = $min; $i <= $edge; $i++) { for ($i = $min; $i <= $edge; $i++) {
@ -681,10 +714,9 @@ class TreeBehavior extends ModelBehavior {
} }
} }
} }
$count = $model->find('count', array('conditions' => array($scope, $model->escapeField($right) => '< ' . $model->escapeField($left)))); $node = $model->find('first', array('conditions' => array($scope, $model->escapeField($right) . '< ' . $model->escapeField($left)), 'recursive' => 0));
if ($count != 0) { if ($node) {
$node = $model->find('first', array('conditions' => array($scope, $model->escapeField($right) => '< ' . $model->escapeField($left)))); $errors[] = array('node', $node[$model->alias][$model->primaryKey], 'left greater than right.');
$errors[] = array('node', $node[$model->primaryKey], 'left greater than right.');
} }
$model->bindModel(array('belongsTo' => array('VerifyParent' => array( $model->bindModel(array('belongsTo' => array('VerifyParent' => array(
@ -693,8 +725,11 @@ class TreeBehavior extends ModelBehavior {
'fields' => array($model->primaryKey, $left, $right, $parent) 'fields' => array($model->primaryKey, $left, $right, $parent)
)))); ))));
foreach ($model->find('all', array('conditions' => $scope, 'recursive' => 1)) as $instance) { foreach ($model->find('all', array('conditions' => $scope, 'recursive' => 0)) as $instance) {
if ($instance[$model->alias][$parent]) { if (is_null($instance[$model->alias][$left]) || is_null($instance[$model->alias][$right])) {
$errors[] = array('node', $instance[$model->alias][$model->primaryKey],
'has invalid left or right values');
} elseif ($instance[$model->alias][$parent]) {
if (!$instance['VerifyParent'][$model->primaryKey]) { if (!$instance['VerifyParent'][$model->primaryKey]) {
$errors[] = array('node', $instance[$model->alias][$model->primaryKey], $errors[] = array('node', $instance[$model->alias][$model->primaryKey],
'The parent node ' . $instance[$model->alias][$parent] . ' doesn\'t exist'); 'The parent node ' . $instance[$model->alias][$parent] . ' doesn\'t exist');
@ -705,7 +740,7 @@ class TreeBehavior extends ModelBehavior {
$errors[] = array('node', $instance[$model->alias][$model->primaryKey], $errors[] = array('node', $instance[$model->alias][$model->primaryKey],
'right greater than parent (node ' . $instance['VerifyParent'][$model->primaryKey] . ').'); 'right greater than parent (node ' . $instance['VerifyParent'][$model->primaryKey] . ').');
} }
} elseif ($model->find('count', array('conditions' => array($scope, $left . '< ' . $instance[$model->alias][$left], $right . '> ' . $instance[$model->alias][$right])))) { } elseif ($model->find('count', array('conditions' => array($scope, $left . '< ' . $instance[$model->alias][$left], $right . '> ' . $instance[$model->alias][$right]), 'recursive' => 0))) {
$errors[] = array('node', $instance[$model->alias][$model->primaryKey], 'The parent field is blank, but has a parent'); $errors[] = array('node', $instance[$model->alias][$model->primaryKey], 'The parent field is blank, but has a parent');
} }
} }
@ -728,18 +763,18 @@ class TreeBehavior extends ModelBehavior {
* @return boolean true on success, false on failure * @return boolean true on success, false on failure
* @access protected * @access protected
*/ */
function _setParent(&$model, $parentId = null) { function _setParent(&$model, $parentId = null, $created = false) {
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
list($node) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $model->id), list($node) = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $model->id),
'fields' => array($model->primaryKey, $parent, $left, $right), 'recursive' => -1))); 'fields' => array($model->primaryKey, $parent, $left, $right), 'recursive' => $recursive)));
$edge = $this->__getMax($model, $scope, $right); $edge = $this->__getMax($model, $scope, $right, $recursive, $created);
if (empty ($parentId)) { if (empty ($parentId)) {
$this->__sync($model, $edge - $node[$left] + 1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right]); $this->__sync($model, $edge - $node[$left] + 1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right], $created);
$this->__sync($model, $node[$right] - $node[$left] + 1, '-', '> ' . $node[$left]); $this->__sync($model, $node[$right] - $node[$left] + 1, '-', '> ' . $node[$left], $created);
} else { } else {
$parentNode = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $parentId), $parentNode = array_values($model->find('first', array('conditions' => array($scope, $model->escapeField() => $parentId),
'fields' => array($model->primaryKey, $left, $right), 'recursive' => -1))); 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive)));
if (empty($parentNode) || empty($parentNode[0])) { if (empty($parentNode) || empty($parentNode[0])) {
return false; return false;
@ -752,25 +787,24 @@ class TreeBehavior extends ModelBehavior {
} elseif (($node[$left] < $parentNode[$left]) && ($parentNode[$right] < $node[$right])) { } elseif (($node[$left] < $parentNode[$left]) && ($parentNode[$right] < $node[$right])) {
return false; return false;
} }
if (empty ($node[$left]) && empty ($node[$right])) { if (empty ($node[$left]) && empty ($node[$right])) {
$this->__sync($model, 2, '+', '>= ' . $parentNode[$right]); $this->__sync($model, 2, '+', '>= ' . $parentNode[$right], $created);
$model->save(array($left => $parentNode[$right], $right => $parentNode[$right] + 1, $parent => $parentId), false); $model->save(array($left => $parentNode[$right], $right => $parentNode[$right] + 1, $parent => $parentId), false);
} else { } else {
$this->__sync($model, $edge - $node[$left] +1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right]); $this->__sync($model, $edge - $node[$left] +1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right], $created);
$diff = $node[$right] - $node[$left] + 1; $diff = $node[$right] - $node[$left] + 1;
if ($node[$left] > $parentNode[$left]) { if ($node[$left] > $parentNode[$left]) {
if ($node[$right] < $parentNode[$right]) { if ($node[$right] < $parentNode[$right]) {
$this->__sync($model, $diff, '-', 'BETWEEN ' . $node[$right] . ' AND ' . ($parentNode[$right] - 1)); $this->__sync($model, $diff, '-', 'BETWEEN ' . $node[$right] . ' AND ' . ($parentNode[$right] - 1), $created);
$this->__sync($model, $edge - $parentNode[$right] + $diff + 1, '-', '> ' . $edge); $this->__sync($model, $edge - $parentNode[$right] + $diff + 1, '-', '> ' . $edge, $created);
} else { } else {
$this->__sync($model, $diff, '+', 'BETWEEN ' . $parentNode[$right] . ' AND ' . $node[$right]); $this->__sync($model, $diff, '+', 'BETWEEN ' . $parentNode[$right] . ' AND ' . $node[$right], $created);
$this->__sync($model, $edge - $parentNode[$right] + 1, '-', '> ' . $edge); $this->__sync($model, $edge - $parentNode[$right] + 1, '-', '> ' . $edge, $created);
} }
} else { } else {
$this->__sync($model, $diff, '-', 'BETWEEN ' . $node[$right] . ' AND ' . ($parentNode[$right] - 1)); $this->__sync($model, $diff, '-', 'BETWEEN ' . $node[$right] . ' AND ' . ($parentNode[$right] - 1), $created);
$this->__sync($model, $edge - $parentNode[$right] + $diff + 1, '-', '> ' . $edge); $this->__sync($model, $edge - $parentNode[$right] + $diff + 1, '-', '> ' . $edge, $created);
} }
} }
} }
@ -785,8 +819,15 @@ class TreeBehavior extends ModelBehavior {
* @return int * @return int
* @access private * @access private
*/ */
function __getMax($model, $scope, $right, $recursive = -1) { function __getMax($model, $scope, $right, $recursive = -1, $created = false) {
$db =& ConnectionManager::getDataSource($model->useDbConfig); $db =& ConnectionManager::getDataSource($model->useDbConfig);
if ($created) {
if (is_string($scope)) {
$scope .= ' AND ' . $model->alias . '.' . $model->primaryKey . ' <> ' . $model->id;
} else {
$scope['NOT'][$model->alias . '.' . $model->primaryKey] = $model->id;
}
}
list($edge) = array_values($model->find('first', array('conditions' => $scope, 'fields' => $db->calculate($model, 'max', array($right)), 'recursive' => $recursive))); list($edge) = array_values($model->find('first', array('conditions' => $scope, 'fields' => $db->calculate($model, 'max', array($right)), 'recursive' => $recursive)));
return ife(empty ($edge[$right]), 0, $edge[$right]); return ife(empty ($edge[$right]), 0, $edge[$right]);
} }
@ -799,8 +840,9 @@ class TreeBehavior extends ModelBehavior {
* @return int * @return int
* @access private * @access private
*/ */
function __getMin($model, $scope, $left) { function __getMin($model, $scope, $left, $recursive = -1) {
list($edge) = array_values($model->find('first', array('conditions' => $scope, 'fields' => 'MIN(' . $left . ') AS ' . $left, 'recursive' => -1))); $db =& ConnectionManager::getDataSource($model->useDbConfig);
list($edge) = array_values($model->find('first', array('conditions' => $scope, 'fields' => $db->calculate($model, 'min', array($left)), 'recursive' => $recursive)));
return ife(empty ($edge[$left]), 0, $edge[$left]); return ife(empty ($edge[$left]), 0, $edge[$left]);
} }
/** /**
@ -815,10 +857,12 @@ class TreeBehavior extends ModelBehavior {
* @param string $field * @param string $field
* @access private * @access private
*/ */
function __sync(&$model, $shift, $dir = '+', $conditions = array(), $field = 'both') { function __sync(&$model, $shift, $dir = '+', $conditions = array(), $created = false, $field = 'both') {
$modelRecursive = $model->recursive;
extract($this->settings[$model->alias]); extract($this->settings[$model->alias]);
$model->recursive = $recursive;
if ($field == 'both') { if ($field == 'both') {
$this->__sync($model, $shift, $dir, $conditions, $left); $this->__sync($model, $shift, $dir, $conditions, $created, $left);
$field = $right; $field = $right;
} }
if (is_string($conditions)) { if (is_string($conditions)) {
@ -831,7 +875,11 @@ class TreeBehavior extends ModelBehavior {
$conditions= array_merge($conditions, $scope); $conditions= array_merge($conditions, $scope);
} }
} }
if ($created) {
$conditions['NOT'][$model->alias . '.' . $model->primaryKey] = $model->id;
}
$model->updateAll(array($model->alias . '.' . $field => $model->alias . '.' . $field . ' ' . $dir . ' ' . $shift), $conditions); $model->updateAll(array($model->alias . '.' . $field => $model->alias . '.' . $field . ' ' . $dir . ' ' . $shift), $conditions);
$model->recursive = $modelRecursive;
} }
} }
?> ?>