Collection::getRootNodeId()   B
last analyzed

Complexity

Conditions 6
Paths 5

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 22
c 0
b 0
f 0
ccs 12
cts 12
cp 1
rs 8.6737
cc 6
eloc 10
nc 5
nop 1
crap 6
1
<?php namespace Arcanedev\LaravelNestedSet\Eloquent;
2
3
use Arcanedev\LaravelNestedSet\NodeTrait;
4
use Arcanedev\LaravelNestedSet\Utilities\NestedSet;
5
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
6
use Illuminate\Support\Collection as BaseCollection;
7
8
/**
9
 * Class     Collection
10
 *
11
 * @package  Arcanedev\LaravelNestedSet\Eloquent
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class Collection extends EloquentCollection
15
{
16
    /* -----------------------------------------------------------------
17
     |  Main Methods
18
     | -----------------------------------------------------------------
19
     */
20
    /**
21
     * Fill `parent` and `children` relationships for every node in the collection.
22
     *
23
     * This will overwrite any previously set relations.
24
     *
25
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
26
     */
27 15
    public function linkNodes()
28
    {
29 15
        if ($this->isEmpty()) return $this;
30
31 15
        $groupedNodes = $this->groupBy($this->first()->getParentIdName());
32
33
        /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $node */
34 15
        foreach ($this->items as $node) {
35 15
            if ($node->getParentId() === null) $node->setRelation('parent', null);
36
37 15
            $children = $groupedNodes->get($node->getKey(), []);
38
39
            /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $child */
40 15
            foreach ($children as $child) {
41 15
                $child->setRelation('parent', $node);
42 5
            }
43
44 15
            $node->setRelation('children', EloquentCollection::make($children));
45 5
        }
46
47 15
        return $this;
48
    }
49
50
    /**
51
     * Build a tree from a list of nodes. Each item will have set children relation.
52
     * To successfully build tree "id", "_lft" and "parent_id" keys must present.
53
     * If `$root` is provided, the tree will contain only descendants of that node.
54
     *
55
     * @param  mixed  $root
56
     *
57
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
58
     */
59 15
    public function toTree($root = false)
60
    {
61 15
        if ($this->isEmpty()) return new static;
62
63 15
        $this->linkNodes();
64
65 15
        $items = [];
66 15
        $root  = $this->getRootNodeId($root);
67
68
        /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $node */
69 15
        foreach ($this->items as $node) {
70 15
            if ($node->getParentId() == $root) {
71 15
                $items[] = $node;
72 5
            }
73 5
        }
74
75 15
        return new static($items);
76
    }
77
78
    /**
79
     * Build a list of nodes that retain the order that they were pulled from the database.
80
     *
81
     * @param  bool  $root
82
     *
83
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
84
     */
85 3
    public function toFlatTree($root = false)
86
    {
87 3
        $result = new static;
88
89 3
        if ($this->isEmpty()) return $result;
90
91 3
        return $result->flattenTree(
92 3
            $this->groupBy($this->first()->getParentIdName()),
93 3
            $this->getRootNodeId($root)
94 1
        );
95
    }
96
97
    /* -----------------------------------------------------------------
98
     |  Other Methods
99
     | -----------------------------------------------------------------
100
     */
101
    /**
102
     * Get root node id.
103
     *
104
     * @param  mixed  $root
105
     *
106
     * @return int
107
     */
108 18
    protected function getRootNodeId($root = false)
109
    {
110 18
        if (NestedSet::isNode($root)) {
111 3
            return $root->getKey();
112
        }
113
114 18
        if ($root !== false) return $root;
115
116
        // If root node is not specified we take parent id of node with
117
        // least lft value as root node id.
118 12
        $leastValue = null;
119
120
        /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $node */
121 12
        foreach ($this->items as $node) {
122 12
            if ($leastValue === null || $node->getLft() < $leastValue) {
123 12
                $leastValue = $node->getLft();
124 12
                $root       = $node->getParentId();
125 4
            }
126 4
        }
127
128 12
        return $root;
129
    }
130
131
    /**
132
     * Flatten a tree into a non recursive array.
133
     *
134
     * @param  \Illuminate\Support\Collection  $groupedNodes
135
     * @param  mixed                           $parentId
136
     *
137
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
138
     */
139 3
    protected function flattenTree(BaseCollection $groupedNodes, $parentId)
140
    {
141
        /** @var \Arcanedev\LaravelNestedSet\Contracts\Nodeable  $node */
142 3
        foreach ($groupedNodes->get($parentId, []) as $node) {
143 3
            $this->push($node);
144 3
            $this->flattenTree($groupedNodes, $node->getKey());
145 1
        }
146
147 3
        return $this;
148
    }
149
}
150