Example #1
0
 /**
  * @param  MPTT|int|array $target 实例或者主键ID
  * @param  bool|int       $leftColumn
  * @param  bool|int       $leftOffset
  * @param  bool|int       $levelOffset
  * @param  bool|int       $allowRootTarget
  * @return $this|bool
  * @throws \Doctrine\DBAL\DBALException
  */
 protected function move($target, $leftColumn, $leftOffset, $levelOffset, $allowRootTarget)
 {
     if (!$this->loaded()) {
         return false;
     }
     // store the changed parent id before reload
     $parentID = $this->{$this->_parentColumn};
     // 保证数据是最新的
     $this->reload();
     if (!$target instanceof $this) {
         $target = new self($target);
         if (!$target->loaded()) {
             return false;
         }
     } else {
         $target->reload();
     }
     // Stop $this being moved into a descendant or itself or disallow if target is root
     if ($target->isDescendant($this) || $this->pk() === $target->pk() || $allowRootTarget === false && $target->isRoot()) {
         return false;
     }
     if ($levelOffset > 0) {
         // We're moving to a child node so add 1 to left offset.
         $leftOffset = $leftColumn === true ? $target->left() + 1 : $target->right() + $leftOffset;
     } else {
         $leftOffset = $leftColumn === true ? $target->left() : $target->right() + $leftOffset;
     }
     $levelOffset = $target->level() - $this->level() + $levelOffset;
     $size = $this->size();
     $this->createSpace($leftOffset, $size);
     $this->reload();
     $offset = $leftOffset - $this->left();
     $this->db()->createQueryBuilder()->update($this->_tableName)->set($this->_leftColumn, $this->_leftColumn . '+' . $offset)->set($this->_rightColumn, $this->_rightColumn . '+' . $offset)->set($this->_levelColumn, $this->_levelColumn . '+' . $levelOffset)->set($this->_scopeColumn, $target->scope())->where($this->_leftColumn . '>=' . $this->left())->andWhere($this->_rightColumn . '<=' . $this->right())->andWhere($this->_scopeColumn . '=' . $this->scope())->execute();
     $this->deleteSpace($this->left(), $size);
     // all went well so save the parent_id if changed
     if ($parentID != $this->{$this->_parentColumn}) {
         $this->{$this->_parentColumn} = $parentID;
         $this->save();
     }
     $this->reload();
     return $this;
 }
 private function removeIn(RedBlackTree $t, $key)
 {
     if ($this->compare($key, $t->key()) < 0) {
         if (!$this->isRed($t->left()) && !$this->isRed($t->left()->left())) {
             $t = $this->moveRedLeft($t);
         }
         $t = new self($t->key(), $t->value(), $t->left()->remove($key), $t->right(), $t->color(), $t->isRoot());
     } else {
         if ($this->isRed($t->left())) {
             $t = $this->rotateRight($t);
         }
         if ($this->compare($key, $t->key()) === 0 && $t->right()->isEmpty()) {
             return self::createEmpty();
         }
         if (!$this->isRed($t->right()) && !$this->isRed($t->right()->left())) {
             $t = $this->moveRedRight($t);
         }
         if ($this->compare($key, $t->key()) === 0) {
             $min = $this->minIn($t->right());
             $t = new self($min->key(), $min->value(), $t->left(), $this->removeMinIn($t->right()), $t->color(), $t->isRoot());
         } else {
             $t = new self($t->key(), $t->value(), $t->left(), $t->right()->remove($key), $t->color(), $t->isRoot());
         }
     }
     return $this->balance($t);
 }