Completed
Push — master ( 6cb9bf...d960fb )
by ARCANEDEV
07:01
created

Collection::toFlatTree()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
ccs 0
cts 7
cp 0
rs 9.4285
cc 2
eloc 6
nc 2
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
7
/**
8
 * Class     Collection
9
 *
10
 * @package  Arcanedev\Taxonomies\Utilities
11
 * @author   ARCANEDEV <[email protected]>
12
 */
13
class Collection extends EloquentCollection
14
{
15
    /* ------------------------------------------------------------------------------------------------
16
     |  Main Functions
17
     | ------------------------------------------------------------------------------------------------
18
     */
19
    /**
20
     * Fill `parent` and `children` relationships for every node in the collection.
21
     *
22
     * This will overwrite any previously set relations.
23
     *
24
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
25
     */
26 20
    public function linkNodes()
27
    {
28 20
        if ($this->isEmpty()) return $this;
29
30 20
        $groupedNodes = $this->groupBy($this->first()->getParentIdName());
31
32
        /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $node */
33 20
        foreach ($this->items as $node) {
34 20
            if ( ! $node->getParentId()) {
35
                $node->setRelation('parent', null);
36
            }
37
38 20
            $children = $groupedNodes->get($node->getKey(), []);
39
40
            /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $child */
41 20
            foreach ($children as $child) {
42 20
                $child->setRelation('parent', $node);
43 15
            }
44
45 20
            $node->setRelation('children', EloquentCollection::make($children));
46 15
        }
47
48 20
        return $this;
49
    }
50
51
    /**
52
     * Build a tree from a list of nodes. Each item will have set children relation.
53
     * To successfully build tree "id", "_lft" and "parent_id" keys must present.
54
     * If `$root` is provided, the tree will contain only descendants of that node.
55
     *
56
     * @param  mixed  $root
57
     *
58
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
59
     */
60 20
    public function toTree($root = false)
61
    {
62 20
        if ($this->isEmpty()) return new static;
63
64 20
        $this->linkNodes();
65
66 20
        $items = [];
67 20
        $root  = $this->getRootNodeId($root);
68
69
        /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $node */
70 20
        foreach ($this->items as $node) {
71 20
            if ($node->getParentId() == $root) {
72 20
                $items[] = $node;
73 15
            }
74 15
        }
75
76 20
        return new static($items);
77
    }
78
79
    /**
80
     * Build a list of nodes that retain the order that they were pulled from the database.
81
     *
82
     * @param  bool  $root
83
     *
84
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
85
     */
86
    public function toFlatTree($root = false)
87
    {
88
        $result = new static;
89
90
        if ($this->isEmpty()) return $result;
91
92
        return $result->flattenTree(
93
            $this->groupBy($this->first()->getParentIdName()),
0 ignored issues
show
Documentation introduced by
$this->groupBy($this->first()->getParentIdName()) is of type this<Arcanedev\LaravelNe...et\Eloquent\Collection>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
94
            $this->getRootNodeId($root)
95
        );
96
    }
97
98
    /* ------------------------------------------------------------------------------------------------
99
     |  Other Functions
100
     | ------------------------------------------------------------------------------------------------
101
     */
102
    /**
103
     * Get root node id.
104
     *
105
     * @param  mixed  $root
106
     *
107
     * @return int
108
     */
109 20
    protected function getRootNodeId($root = false)
110
    {
111 20
        if (NestedSet::isNode($root)) {
112 4
            return $root->getKey();
113
        }
114
115 20
        if ($root !== false) return $root;
116
117
        // If root node is not specified we take parent id of node with
118
        // least lft value as root node id.
119 12
        $leastValue = null;
120
121
        /** @var  NodeTrait|\Illuminate\Database\Eloquent\Model  $node */
122 12
        foreach ($this->items as $node) {
123 12
            if ($leastValue === null || $node->getLft() < $leastValue) {
124 12
                $leastValue = $node->getLft();
125 12
                $root       = $node->getParentId();
126 9
            }
127 9
        }
128
129 12
        return $root;
130
    }
131
132
    /**
133
     * Flatten a tree into a non recursive array.
134
     *
135
     * @param  \Arcanedev\LaravelNestedSet\Eloquent\Collection  $groupedNodes
136
     * @param  mixed                                            $parentId
137
     *
138
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
139
     */
140
    protected function flattenTree(self $groupedNodes, $parentId)
141
    {
142
        foreach ($groupedNodes->get($parentId, []) as $node) {
143
            $this->push($node);
144
            $this->flattenTree($groupedNodes, $node->getKey());
145
        }
146
147
        return $this;
148
    }
149
}
150