Example #1
0
 /**
  * Method for validation of status change flow
  *
  * @param AppModel $Model
  * @param array $data
  * @return boolean
  * @access public
  */
 public function validateStatus($Model, $data)
 {
     if ($Model->exists() && ($current = $Model->field('status'))) {
         return in_array($data['status'], $this->settings[$Model->alias]['status'][$current]);
     }
     return false;
 }
Example #2
0
 /**
  * Sets the parent of the given node
  *
  * The force parameter is used to override the "don't change the parent to the current parent" logic in the event
  * of recovering a corrupted table, or creating new nodes. Otherwise it should always be false. In reality this
  * method could be private, since calling save with parent_id set also calls setParent
  *
  * @since 1.2
  * @param AppModel $model
  * @param mixed $parent_id
  * @param boolean $force process even if current parent_id is the same as the value to be saved
  * @return boolean True on success, false on failure
  * @access protected
  */
 function _set_parent(&$model, $parent_id = null, $force = false)
 {
     extract($this->settings[$model->name]);
     if (!$force && $parent_id == $model->field($parent)) {
         return false;
     }
     list($node) = array_values($model->find(array($scope, $model->escapeField() => $model->id), array($model->primaryKey, $parent, $left, $right), null, -1));
     $edge = $this->__get_max($model, $scope, $right);
     if (empty($parent_id)) {
         // No parent specified. Never executed for creations (handled in beforeSave)
         // First, move the node (and subnodes) to the end
         $this->__sync($model, $edge - $node[$left] + 1, '+', "BETWEEN {$node[$left]} AND {$node[$right]}", $scope);
         // Then move everything back so there is no gap
         $this->__sync($model, $node[$right] - $node[$left] + 1, '-', "> {$node[$left]}", $scope);
     } else {
         // A parent has been specified
         list($parentNode) = array_values($model->find(array($scope, $model->escapeField() => $parent_id), array($model->primaryKey, $left, $right), null, -1));
         if (empty($parentNode)) {
             trigger_error(__('Trying to move a node under a none-existant node in ' . __METHOD__, true), E_USER_WARNING);
             return false;
         } elseif ($model->id == $parent_id) {
             trigger_error(__('Trying to set a node to be the parent of itself in ' . __METHOD__, E_USER_WARNING));
             return false;
         } elseif ($node[$left] < $parentNode[$left] && $parentNode[$right] < $node[$right]) {
             trigger_error(__('Trying to move a node under itself in ' . __METHOD__, E_USER_WARNING));
             return false;
         }
         if (empty($node[$left]) && empty($node[$right])) {
             // The node is not yet in the tree, only for creation with parent id
             $this->__sync($model, 2, '+', ">= {$parentNode[$right]}}", $scope);
             $model->save(array($left => $parentNode[$right], $right => $parentNode[$right] + 1, $parent => $parent_id), false);
         } else {
             // Moving an existing node to a new parent
             // First, move the node (and subnodes) to the end of the tree
             $this->__sync($model, $edge - $node[$left] + 1, '+', "BETWEEN {$node[$left]} AND {$node[$right]}", $scope);
             $diff = $node[$right] - $node[$left] + 1;
             if ($node[$left] > $parentNode[$left]) {
                 // If the Node is sequencially after the parent ..
                 if ($node[$right] < $parentNode[$right]) {
                     // .. and it's a reshuffle (promotion/demotion)
                     $this->__sync($model, $diff, '-', "BETWEEN {$node[$right]} AND " . ($parentNode[$right] - 1), $scope);
                     $this->__sync($model, $edge - $parentNode[$right] + $diff + 1, '-', "> {$edge}", $scope);
                 } else {
                     // .. else the Node truely is sequencially after the parent
                     // extend Parent to encompase the hole, and move the displaced node into the hole
                     $this->__sync($model, $diff, '+', "BETWEEN {$parentNode[$right]} AND {$node[$right]}", $scope);
                     $this->__sync($model, $edge - $parentNode[$right] + 1, '-', "> {$edge}", $scope);
                 }
             } else {
                 // .. the node is sequencially before the parent
                 // move Parent back leaving a hole, and move the displaced node into the hole
                 $this->__sync($model, $diff, '-', "BETWEEN {$node[$right]} AND " . ($parentNode[$right] - 1), $scope);
                 $this->__sync($model, $edge - $parentNode[$right] + $diff + 1, '-', "> {$edge}", $scope);
             }
         }
     }
     return true;
 }
Example #3
0
 /**
  * Backward compatible method
  *
  * Returns true if the change is successful.
  *
  * @param AppModel $model
  * @param mixed $parentId The ID to set as the parent of the current node.
  * @return true on success
  * @access public
  */
 function setparent(&$model, $parentId = null, $created = null)
 {
     extract($this->settings[$model->alias]);
     if ($created === false && $parentId == $model->field($parent)) {
         return true;
     }
     return $model->saveField($parent, $parentId);
 }
Example #4
0
 /**
  * Backward compatible method
  *
  * Returns true if the change is successful.
  *
  * @param AppModel $model
  * @param mixed $parentId The ID to set as the parent of the current node.
  * @return true on success
  * @access public
  * @deprecated
  */
 function setparent(&$model, $parentId = null, $created = null)
 {
     trigger_error(__('(TreeBehavior::setParent) Deprecated - save the record with a parent ID instead', true), E_USER_ERROR);
     extract($this->settings[$model->alias]);
     if ($created === false && $parentId == $model->field($parent)) {
         return true;
     }
     return $model->saveField($parent, $parentId, array('callbacks' => false));
 }
Example #5
0
 /**
  * If editing a record, set the oldGroups property to the current group values
  * in the database for each group field for this model.
  *
  * @param AppModel $model
  */
 function setOldGroups(&$model)
 {
     // If no id, we're creating not editing, so there is no old groups
     if (!$model->id) {
         return;
     }
     // If this model does not have any groups, return
     if (!$this->groupFields) {
         return;
     }
     // Set oldGroups property with key of group field and current value of group
     // field from db
     foreach ($this->groupFields as $groupField) {
         $this->oldGroups[$groupField] = $model->field($model->alias . '.' . $groupField);
     }
 }
 /**
  * Moves a node up or down the order of ndoes at a particular level, i.e.
  * affects the relative position of a node with respect to it's siblings.
  *
  * Used as a replacement for the SequenceBehavior for hierarchical models,
  * which the SequenceBehavior is not suitable for.
  *
  * @param AppModel $model The model object that the behavior is attached to
  * @param integer $id ID of the node to affect
  * @param integer $newOrder New position in the sequence
  * @return boolean
  * @access public
  */
 function setOrder(&$model, $id, $newOrder)
 {
     // Validate id supplied
     if (!$id) {
         $this->errors[] = "Id not valid";
         return false;
     }
     // Validate new order
     if (!is_numeric($newOrder)) {
         $this->errors[] = "New order must be numeric";
         return false;
     }
     // Get parent id
     $model->recursive = -1;
     $parentId = $model->field($this->settings[$model->alias]['parent'], array($model->primaryKey => $id));
     // Get all children of node's parent, i.e. it and siblings
     $siblings = $model->find('list', array('conditions' => array($this->settings[$model->alias]['parent'] => $parentId)));
     // Get sibling ids in a numerically indexed array, starting at 0
     $siblingIds = array_keys($siblings);
     // Get the current order the node in question in the array of sibling ids
     $currentOrder = array_search($id, $siblingIds);
     // Get the difference between the new position and old position
     $difference = $newOrder - $currentOrder;
     // Get the number of places to move the node
     $places = abs($difference);
     // Move the node up or down (depending on the sign of the difference) by the
     // appropriate number of places
     if ($difference == 0) {
         return true;
     } elseif ($difference > 0) {
         return $this->movedown($model, $id, $places);
     } else {
         return $this->moveup($model, $id, $places);
     }
 }