Skip to content

Commit

Permalink
Refactored tree flattening
Browse files Browse the repository at this point in the history
  • Loading branch information
lazychaser committed Feb 29, 2016
1 parent 7575370 commit 849b740
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
10 changes: 10 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,16 @@ This will output something like this:
- Another root
```

##### Building flat tree

Also, you can build a flat tree: a list of nodes where child nodes are immediately
after parent node. This is helpful when you get nodes with custom order
(i.e. alphabetically) and don't want to use recursion to iterate over your nodes.

```php
$nodes = Category::get()->toFlatTree();
```

##### Getting a subtree

Sometimes you don't need whole tree to be loaded and just some subtree of specific node.
Expand Down
46 changes: 20 additions & 26 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function toTree($root = false)
*
* @return int
*/
protected function getRootNodeId($root)
protected function getRootNodeId($root = false)
{
if (NestedSet::isNode($root)) {
return $root->getKey();
Expand Down Expand Up @@ -106,44 +106,38 @@ protected function getRootNodeId($root)
* Build a list of nodes that retain the order that they were pulled from
* the database.
*
* @return Collection|static
* @param bool $root
*
* @return static
*/
public function toFlattenedTree()
public function toFlatTree($root = false)
{
$tree = $this->toTree();
$result = new static;

return $tree->flattenTree();
}
if ($this->isEmpty()) return $result;

/**
* Flatten a tree into a non recursive array
*/
public function flattenTree()
{
$items = [];

foreach ($this->items as $node) {
$items = array_merge($items, $this->flattenNode($node));
}
$groupedNodes = $this->groupBy($this->first()->getParentIdName());

return new static($items);
return $result->flattenTree($groupedNodes, $this->getRootNodeId($root));
}

/**
* Flatten a single node
* Flatten a tree into a non recursive array.
*
* @param Collection $groupedNodes
* @param mixed $parentId
*
* @param $node
* @return array
* @return $this
*/
protected function flattenNode($node)
protected function flattenTree(self $groupedNodes, $parentId)
{
$items = [];
$items[] = $node;
foreach ($groupedNodes->get($parentId, []) as $node) {
$this->push($node);

foreach ($node->children as $childNode) {
$items = array_merge($items, $this->flattenNode($childNode));
$this->flattenTree($groupedNodes, $node->getKey());
}

return $items;
return $this;
}

}
10 changes: 10 additions & 0 deletions tests/NodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,16 @@ public function testRebuildFailsWithInvalidPK()
{
Category::rebuildTree([ [ 'id' => 24 ] ]);
}

public function testFlatTree()
{
$node = $this->findCategory('mobile');
$tree = $node->descendants()->orderBy('name')->get()->toFlatTree();

$this->assertCount(5, $tree);
$this->assertEquals('samsung', $tree[2]->name);
$this->assertEquals('galaxy', $tree[3]->name);
}
}

function all($items)
Expand Down

0 comments on commit 849b740

Please sign in to comment.