/** * Validates bounds of the nested tree structure. It will perform checks on * the `lft`, `rgt` and `parent_id` columns. Mainly that they're not null, * rights greater than lefts, and that they're within the bounds of the parent. * * @return boolean */ protected function validateBounds() { $connection = $this->node->getConnection(); $grammar = $connection->getQueryGrammar(); $tableName = $this->node->getTable(); $primaryKeyName = $this->node->getKeyName(); $parentColumn = $this->node->getQualifiedParentColumnName(); $lftCol = $grammar->wrap($this->node->getLeftColumnName()); $rgtCol = $grammar->wrap($this->node->getRightColumnName()); $qualifiedLftCol = $grammar->wrap($this->node->getQualifiedLeftColumnName()); $qualifiedRgtCol = $grammar->wrap($this->node->getQualifiedRightColumnName()); $qualifiedParentCol = $grammar->wrap($this->node->getQualifiedParentColumnName()); $whereStm = "({$qualifiedLftCol} IS NULL OR\n {$qualifiedRgtCol} IS NULL OR\n {$qualifiedLftCol} >= {$qualifiedRgtCol} OR\n ({$qualifiedParentCol} IS NOT NULL AND\n ({$qualifiedLftCol} <= parent.{$lftCol} OR\n {$qualifiedRgtCol} >= parent.{$rgtCol})))"; $query = $this->node->newQuery()->join($connection->raw($grammar->wrap($tableName) . ' AS parent'), $parentColumn, '=', $connection->raw('parent.' . $grammar->wrap($primaryKeyName)), 'left outer')->whereRaw($whereStm); return $query->count() == 0; }
/** * Flattens an array to contain 'id', 'lft', 'rgt', 'depth', 'parent_id' as a valid tree * @param $nestableArray * @param mixed $parent_id * @param int $depth * @param int $bound * @return array */ public function flattenNestable($nodeList, $parent_id = null, $depth = 0, &$bound = 0) { $nodes = array(); foreach ($nodeList as $node) { $lft = ++$bound; $children = array_get($node, $this->childrenKeyName, []); if (!empty($children)) { $children = $this->flattenNestable($children, array_get($node, $this->node->getKeyName()), $depth + 1, $bound); } $rgt = ++$bound; $nodes[] = array($this->node->getKeyName() => array_get($node, $this->node->getKeyName()), $this->node->getParentColumnName() => $parent_id, $this->node->getDepthColumnName() => $depth, $this->node->getLeftColumnName() => $lft, $this->node->getRightColumnName() => $rgt); $nodes = array_merge($nodes, $children); } return $nodes; }
/** * Applies a lock to the rows between the supplied index boundaries. * * @param int $lft * @param int $rgt * @return void */ protected function applyLockBetween($lft, $rgt) { $this->node->newQuery()->where($this->node->getLeftColumnName(), '>=', $lft)->where($this->node->getRightColumnName(), '<=', $rgt)->select($this->node->getKeyName())->lockForUpdate()->get(); }