📄 tree.php
字号:
if ($keyPath == null) { $keyPath = '{n}.' . $model->alias . '.' . $model->primaryKey; } if ($valuePath == null) { $valuePath = array('{0}{1}', '{n}.tree_prefix', '{n}.' . $model->alias . '.' . $model->displayField); } elseif (is_string($valuePath)) { $valuePath = array('{0}{1}', '{n}.tree_prefix', $valuePath); } else { $valuePath[0] = '{' . (count($valuePath) - 1) . '}' . $valuePath[0]; $valuePath[] = '{n}.tree_prefix'; } $order = $model->alias . '.' . $left . ' asc'; $results = $model->find('all', compact('conditions', 'fields', 'order', 'recursive')); $stack = array(); foreach ($results as $i => $result) { while ($stack && ($stack[count($stack) - 1] < $result[$model->alias][$right])) { array_pop($stack); } $results[$i]['tree_prefix'] = str_repeat($spacer,count($stack)); $stack[] = $result[$model->alias][$right]; } if (empty($results)) { return array(); } return Set::combine($results, $keyPath, $valuePath); }/** * Get the parent node * * reads the parent id and returns this node * * @param AppModel $model * @param mixed $id The ID of the record to read * @param integer $recursive The number of levels deep to fetch associated records * @return array Array of data for the parent node * @access public */ function getparentnode(&$model, $id = null, $fields = null, $recursive = null) { if (is_array($id)) { extract (array_merge(array('id' => null), $id)); } $overrideRecursive = $recursive; if (empty ($id)) { $id = $model->id; } extract($this->settings[$model->alias]); if (!is_null($overrideRecursive)) { $recursive = $overrideRecursive; } $parentId = $model->read($parent, $id); if ($parentId) { $parentId = $parentId[$model->alias][$parent]; $parent = $model->find('first', array('conditions' => array($model->escapeField() => $parentId), 'fields' => $fields, 'recursive' => $recursive)); return $parent; } else { return false; } }/** * Get the path to the given node * * @param AppModel $model * @param mixed $id The ID of the record to read * @param mixed $fields Either a single string of a field name, or an array of field names * @param integer $recursive The number of levels deep to fetch associated records * @return array Array of nodes from top most parent to current node * @access public */ function getpath(&$model, $id = null, $fields = null, $recursive = null) { if (is_array($id)) { extract (array_merge(array('id' => null), $id)); } $overrideRecursive = $recursive; if (empty ($id)) { $id = $model->id; } extract($this->settings[$model->alias]); if (!is_null($overrideRecursive)) { $recursive = $overrideRecursive; } $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; } $item = $result[0]; $results = $model->find('all', array( 'conditions' => array($scope, $model->escapeField($left) . ' <=' => $item[$left], $model->escapeField($right) . ' >=' => $item[$right]), 'fields' => $fields, 'order' => array($model->escapeField($left) => 'asc'), 'recursive' => $recursive )); return $results; }/** * Reorder the node without changing the parent. * * If the node is the last child, or is a top level node with no subsequent node this method will return false * * @param AppModel $model * @param mixed $id The ID of the record to move * @param mixed $number how many places to move the node or true to move to last position * @return boolean true on success, false on failure * @access public */ function movedown(&$model, $id = null, $number = 1) { if (is_array($id)) { extract (array_merge(array('id' => null), $id)); } if (!$number) { return false; } if (empty ($id)) { $id = $model->id; } extract($this->settings[$model->alias]); list($node) = array_values($model->find('first', array( 'conditions' => array($scope, $model->escapeField() => $id), 'fields' => array($model->primaryKey, $left, $right, $parent), 'recursive' => $recursive ))); if ($node[$parent]) { list($parentNode) = array_values($model->find('first', array( 'conditions' => array($scope, $model->escapeField() => $node[$parent]), 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive ))); if (($node[$right] + 1) == $parentNode[$right]) { return false; } } $nextNode = $model->find('first', array( 'conditions' => array($scope, $model->escapeField($left) => ($node[$right] + 1)), 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive) ); if ($nextNode) { list($nextNode)= array_values($nextNode); } else { return false; } $edge = $this->__getMax($model, $scope, $right, $recursive); $this->__sync($model, $edge - $node[$left] + 1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right]); $this->__sync($model, $nextNode[$left] - $node[$left], '-', 'BETWEEN ' . $nextNode[$left] . ' AND ' . $nextNode[$right]); $this->__sync($model, $edge - $node[$left] - ($nextNode[$right] - $nextNode[$left]), '-', '> ' . $edge); if (is_int($number)) { $number--; } if ($number) { $this->moveDown($model, $id, $number); } return true; }/** * Reorder the node without changing the parent. * * If the node is the first child, or is a top level node with no previous node this method will return false * * @param AppModel $model * @param mixed $id The ID of the record to move * @param mixed $number how many places to move the node, or true to move to first position * @return boolean true on success, false on failure * @access public */ function moveup(&$model, $id = null, $number = 1) { if (is_array($id)) { extract (array_merge(array('id' => null), $id)); } if (!$number) { return false; } if (empty ($id)) { $id = $model->id; } extract($this->settings[$model->alias]); list($node) = array_values($model->find('first', array( 'conditions' => array($scope, $model->escapeField() => $id), 'fields' => array($model->primaryKey, $left, $right, $parent ), 'recursive' => $recursive ))); if ($node[$parent]) { list($parentNode) = array_values($model->find('first', array( 'conditions' => array($scope, $model->escapeField() => $node[$parent]), 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive ))); if (($node[$left] - 1) == $parentNode[$left]) { return false; } } $previousNode = $model->find('first', array( 'conditions' => array($scope, $model->escapeField($right) => ($node[$left] - 1)), 'fields' => array($model->primaryKey, $left, $right), 'recursive' => $recursive )); if ($previousNode) { list($previousNode) = array_values($previousNode); } else { return false; } $edge = $this->__getMax($model, $scope, $right, $recursive); $this->__sync($model, $edge - $previousNode[$left] +1, '+', 'BETWEEN ' . $previousNode[$left] . ' AND ' . $previousNode[$right]); $this->__sync($model, $node[$left] - $previousNode[$left], '-', 'BETWEEN ' .$node[$left] . ' AND ' . $node[$right]); $this->__sync($model, $edge - $previousNode[$left] - ($node[$right] - $node[$left]), '-', '> ' . $edge); if (is_int($number)) { $number--; } if ($number) { $this->moveUp($model, $id, $number); } return true; }/** * Recover a corrupted tree * * The mode parameter is used to specify the source of info that is valid/correct. The opposite source of data * will be populated based upon that source of info. E.g. if the MPTT fields are corrupt or empty, with the $mode * 'parent' the values of the parent_id field will be used to populate the left and right fields. The missingParentAction * parameter only applies to "parent" mode and determines what to do if the parent field contains an id that is not present. * * @todo Could be written to be faster, *maybe*. Ideally using a subquery and putting all the logic burden on the DB. * @param AppModel $model * @param string $mode parent or tree * @param mixed $missingParentAction 'return' to do nothing and return, 'delete' to * delete, or the id of the parent to set as the parent_id * @return boolean true on success, false on failure * @access public */ function recover(&$model, $mode = 'parent', $missingParentAction = null) { if (is_array($mode)) { extract (array_merge(array('mode' => 'parent'), $mode)); } extract($this->settings[$model->alias]); $model->recursive = $recursive; if ($mode == 'parent') { $model->bindModel(array('belongsTo' => array('VerifyParent' => array( 'className' => $model->alias, 'foreignKey' => $parent, 'fields' => array($model->primaryKey, $left, $right, $parent, 'actsAs' => '') )))); $missingParents = $model->find('list', array( 'recursive' => 0, 'conditions' => array($scope, array( 'NOT' => array($model->escapeField($parent) => null), $model->VerifyParent->escapeField() => null )) )); $model->unbindModel(array('belongsTo' => array('VerifyParent'))); if ($missingParents) { if ($missingParentAction == 'return') { foreach ($missingParents as $id => $display) { $this->errors[] = 'cannot find the parent for ' . $model->alias . ' with id ' . $id . '(' . $display . ')'; } return false; } elseif ($missingParentAction == 'delete') { $model->deleteAll(array($model->primaryKey => array_flip($missingParents))); } else { $model->updateAll(array($parent => $missingParentAction), array($model->primaryKey => array_flip($missingParents))); } } $count = 1; foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey), 'order' => $left)) as $array) { $model->{$model->primaryKey} = $array[$model->alias][$model->primaryKey]; $lft = $count++; $rght = $count++; $model->save(array($left => $lft,$right => $rght)); } foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey, $parent), 'order' => $left)) as $array) { $model->create(); $model->id = $array[$model->alias][$model->primaryKey]; $this->_setParent($model, $array[$model->alias][$parent]); } } else { foreach ($model->find('all', array('conditions' => $scope, 'fields' => array($model->primaryKey, $parent), 'order' => $left)) as $array) { $path = $this->getpath($model, $array[$model->alias][$model->primaryKey]); if ($path == null || count($path) < 2) { $parentId = null; } else { $parentId = $path[count($path) - 2][$model->alias][$model->primaryKey]; } $model->updateAll(array($parent => $parentId), array($model->escapeField() => $array[$model->alias][$model->primaryKey])); } } return true; }/** * Reorder method. * * Reorders the nodes (and child nodes) of the tree according to the field and direction specified in the parameters. * This method does not change the parent of any node. * * Requires a valid tree, by default it verifies the tree before beginning. * * @param AppModel $model * @param array $options * @return boolean true on success, false on failure */ function reorder(&$model, $options = array()) { $options = array_merge(array('id' => null, 'field' => $model->displayField, 'order' => 'ASC', 'verify' => true), $options); extract($options); if ($verify && !$model->verify()) { return false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -