/** * Converts an adjacency list to a nested set * * @param array $nodes * @param array $parents * @param number $parent * @param number $left * @param number $level * @return number */ private static function convertToNestedSet(&$nodes) { static $new_tree; static $parents; static $node; static $left; static $right; static $level; if ($new_tree === null) { $new_tree = new \Tree\NestedSet\NestedSet(); $parents = array(); foreach ($nodes as $node) { $parents[$node->getParentId()][] = $node; } reset($parents); $node = current($parents[0]); $left = 1; $right = 2; $level = 0; } $new_node = array('id' => $node->getId(), 'left' => $left, 'level' => $level); // the right value of this node is the left value + 1 $right = $left + 1; // get all children of this node if (isset($parents[$node->getId()])) { foreach ($parents[$node->getId()] as $node) { $current_id = $node->getId(); $left = $right; $level += 1; self::convertToNestedSet($nodes); $right += 1; $new_node['right'] = $right; } } $new_node['right'] = $right; $new_tree->setNode(\Tree\NestedSet\Node::fromArray($new_node)); // return the right value of this node + 1 return $new_tree; }
/** * Iterate through the tree to tighten up the left and right domains * * @param \Tree\NestedSet\NestedSet $tree * * @return \Tree\NestedSet\NestedSet */ private static function tightenRecursively(&$tree = null) { static $new_tree; static $node; static $left; static $pointer; if ($new_tree === null) { $new_tree = new NestedSet(); $node = $tree->getRootNode(); $left = $node->getLeft(); $pointer = 1; } $node = $tree->getNode($node); $new_node = array(); $descendants = $tree->getDescendants($node->getId()); $number_of_descendants = count($descendants); // If descendants found, we must tighten their values if ($number_of_descendants > 0) { $new_node['id'] = $node->getId(); // Set the pointer to the incorrect node left + 1 if ($node->getLeft() >= $pointer) { $pointer = $node->getLeft() + 1; } // Fix the current node's left and right values based on children $new_node['left'] = $left; if ($left == 1) { // Root node, right should be # of total nodes * 2 $new_node['right'] = ($number_of_descendants + 1) * 2; } else { // Not root node $new_node['right'] = $new_node['left'] + ($number_of_descendants + 1) * 2 - 1; } // Add new node to new tree array $new_tree->setNode(Node::fromArray($new_node)); // For each child node, set the next left to current left + 1 and repair foreach ($descendants as $descendant) { if ($pointer <= $descendant->getLeft()) { $left = $left + 1; $node = $descendant; self::tightenRecursively($tree); } } // Set next left to current left + 1 $left = $left + 1; } else { // Set the pointer to the incorrect node right + 1 if ($node->getLeft() >= $pointer) { $pointer = $node->getRight() + 1; } // Set left/right values of new node $new_node['id'] = $node->getId(); $new_node['left'] = $left; $new_node['right'] = $left + 1; // Set the next correct left value to left + 1 $left = $left + 1; // Add new node to new tree array $new_tree->setNode(Node::fromArray($new_node)); } return $new_tree; }