/** * Maps a tree structure into the database without unguarding nor wrapping * inside a transaction. * * @param array|\Illuminate\Support\Contracts\ArrayableInterface * @return boolean */ public function mapTree($nodeList) { $tree = $nodeList instanceof ArrayableInterface ? $nodeList->toArray() : $nodeList; $affectedKeys = array(); $result = $this->mapTreeRecursive($tree, $this->node->getKey(), $affectedKeys); if ($result && count($affectedKeys) > 0) { $this->deleteUnaffected($affectedKeys); } return $result; }
/** * Runs the SQL query associated with the update of the indexes affected * by the move operation. * * @return int */ public function updateStructure() { list($a, $b, $c, $d) = $this->boundaries(); // select the rows between the leftmost & the rightmost boundaries and apply a lock $this->applyLockBetween($a, $d); $connection = $this->node->getConnection(); $grammar = $connection->getQueryGrammar(); $currentId = $this->quoteIdentifier($this->node->getKey()); $parentId = $this->quoteIdentifier($this->parentId()); $leftColumn = $this->node->getLeftColumnName(); $rightColumn = $this->node->getRightColumnName(); $parentColumn = $this->node->getParentColumnName(); $wrappedLeft = $grammar->wrap($leftColumn); $wrappedRight = $grammar->wrap($rightColumn); $wrappedParent = $grammar->wrap($parentColumn); $wrappedId = $grammar->wrap($this->node->getKeyName()); $lftSql = "CASE\n WHEN {$wrappedLeft} BETWEEN {$a} AND {$b} THEN {$wrappedLeft} + {$d} - {$b}\n WHEN {$wrappedLeft} BETWEEN {$c} AND {$d} THEN {$wrappedLeft} + {$a} - {$c}\n ELSE {$wrappedLeft} END"; $rgtSql = "CASE\n WHEN {$wrappedRight} BETWEEN {$a} AND {$b} THEN {$wrappedRight} + {$d} - {$b}\n WHEN {$wrappedRight} BETWEEN {$c} AND {$d} THEN {$wrappedRight} + {$a} - {$c}\n ELSE {$wrappedRight} END"; $parentSql = "CASE\n WHEN {$wrappedId} = {$currentId} THEN {$parentId}\n ELSE {$wrappedParent} END"; $updateConditions = array($leftColumn => $connection->raw($lftSql), $rightColumn => $connection->raw($rgtSql), $parentColumn => $connection->raw($parentSql)); if ($this->node->timestamps) { $updateConditions[$this->node->getUpdatedAtColumn()] = $this->node->freshTimestamp(); } return $this->node->newNestedSetQuery()->where(function ($query) use($leftColumn, $rightColumn, $a, $d) { $query->whereBetween($leftColumn, array($a, $d))->orWhereBetween($rightColumn, array($a, $d)); })->update($updateConditions); }
/** * @param Node $node * @param array $array * @param Key $lo * @param Key $hi */ private function _range(Node $node, array &$array, Key $lo, Key $hi) { if (!$node->getLength()) { return; } $cmpLo = $node->getKey()->compare($lo); $cmpHi = $node->getKey()->compare($hi); if ($cmpLo > 0) { $this->_range($node->getLeft(), $array, $lo, $hi); } if ($cmpLo >= 0 && $cmpHi <= 0) { $array[] = $node; } if ($cmpHi < 0) { $this->_range($node->getRight(), $array, $lo, $hi); } }
/** * Return all children for the specified node. * * @param Tree\Node $node * @return Illuminate\Database\Eloquent\Collection */ public function children($node) { $query = $this->node->newQuery(); $query->where($this->node->getQualifiedParentColumnName(), '=', $node->getKey()); // We must also add the scoped column values to the query to compute valid // left and right indexes. foreach ($this->scopedAttributes($node) as $fld => $value) { $query->where($this->qualify($fld), '=', $value); } $query->orderBy($this->node->getQualifiedLeftColumnName()); $query->orderBy($this->node->getQualifiedRightColumnName()); $query->orderBy($this->node->getQualifiedKeyName()); return $query->get(); }