Skip to content

Commit 849b740

Browse files
committed
Refactored tree flattening
1 parent 7575370 commit 849b740

File tree

3 files changed

+40
-26
lines changed

3 files changed

+40
-26
lines changed

README.markdown

+10
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,16 @@ This will output something like this:
417417
- Another root
418418
```
419419

420+
##### Building flat tree
421+
422+
Also, you can build a flat tree: a list of nodes where child nodes are immediately
423+
after parent node. This is helpful when you get nodes with custom order
424+
(i.e. alphabetically) and don't want to use recursion to iterate over your nodes.
425+
426+
```php
427+
$nodes = Category::get()->toFlatTree();
428+
```
429+
420430
##### Getting a subtree
421431

422432
Sometimes you don't need whole tree to be loaded and just some subtree of specific node.

src/Collection.php

+20-26
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public function toTree($root = false)
7777
*
7878
* @return int
7979
*/
80-
protected function getRootNodeId($root)
80+
protected function getRootNodeId($root = false)
8181
{
8282
if (NestedSet::isNode($root)) {
8383
return $root->getKey();
@@ -106,44 +106,38 @@ protected function getRootNodeId($root)
106106
* Build a list of nodes that retain the order that they were pulled from
107107
* the database.
108108
*
109-
* @return Collection|static
109+
* @param bool $root
110+
*
111+
* @return static
110112
*/
111-
public function toFlattenedTree()
113+
public function toFlatTree($root = false)
112114
{
113-
$tree = $this->toTree();
115+
$result = new static;
114116

115-
return $tree->flattenTree();
116-
}
117+
if ($this->isEmpty()) return $result;
117118

118-
/**
119-
* Flatten a tree into a non recursive array
120-
*/
121-
public function flattenTree()
122-
{
123-
$items = [];
124-
125-
foreach ($this->items as $node) {
126-
$items = array_merge($items, $this->flattenNode($node));
127-
}
119+
$groupedNodes = $this->groupBy($this->first()->getParentIdName());
128120

129-
return new static($items);
121+
return $result->flattenTree($groupedNodes, $this->getRootNodeId($root));
130122
}
131123

132124
/**
133-
* Flatten a single node
125+
* Flatten a tree into a non recursive array.
126+
*
127+
* @param Collection $groupedNodes
128+
* @param mixed $parentId
134129
*
135-
* @param $node
136-
* @return array
130+
* @return $this
137131
*/
138-
protected function flattenNode($node)
132+
protected function flattenTree(self $groupedNodes, $parentId)
139133
{
140-
$items = [];
141-
$items[] = $node;
134+
foreach ($groupedNodes->get($parentId, []) as $node) {
135+
$this->push($node);
142136

143-
foreach ($node->children as $childNode) {
144-
$items = array_merge($items, $this->flattenNode($childNode));
137+
$this->flattenTree($groupedNodes, $node->getKey());
145138
}
146139

147-
return $items;
140+
return $this;
148141
}
142+
149143
}

tests/NodeTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,16 @@ public function testRebuildFailsWithInvalidPK()
806806
{
807807
Category::rebuildTree([ [ 'id' => 24 ] ]);
808808
}
809+
810+
public function testFlatTree()
811+
{
812+
$node = $this->findCategory('mobile');
813+
$tree = $node->descendants()->orderBy('name')->get()->toFlatTree();
814+
815+
$this->assertCount(5, $tree);
816+
$this->assertEquals('samsung', $tree[2]->name);
817+
$this->assertEquals('galaxy', $tree[3]->name);
818+
}
809819
}
810820

811821
function all($items)

0 commit comments

Comments
 (0)