LTreeCollection::hasMissingNodes()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 12
ccs 8
cts 8
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Umbrellio\LTree\Collections;
6
7
use Illuminate\Database\Eloquent\Collection;
8
use Illuminate\Database\Eloquent\Model;
9
use Umbrellio\LTree\Helpers\LTreeBuilder;
10
use Umbrellio\LTree\Helpers\LTreeNode;
11
use Umbrellio\LTree\Interfaces\HasLTreeRelations;
12
use Umbrellio\LTree\Interfaces\LTreeInterface;
13
use Umbrellio\LTree\Interfaces\ModelInterface;
14
use Umbrellio\LTree\Traits\LTreeModelTrait;
15
16
/**
17
 * @method LTreeInterface|ModelInterface first()
18
 * @property LTreeInterface[]|ModelInterface[]|HasLTreeRelations[] $items
19
 */
20
class LTreeCollection extends Collection
21
{
22
    private $withLeaves = true;
23
24 23
    public function toTree(bool $usingSort = true, bool $loadMissing = true): LTreeNode
25
    {
26 23
        if (!$model = $this->first()) {
27 1
            return new LTreeNode();
28
        }
29
30 22
        if ($loadMissing) {
31 18
            $this->loadMissingNodes($model);
32
        }
33
34 22
        if (!$this->withLeaves) {
35 1
            $this->excludeLeaves();
36
        }
37
38 22
        $builder = new LTreeBuilder(
39 22
            $model->getLtreePathColumn(),
40 22
            $model->getKeyName(),
41 22
            $model->getLtreeParentColumn()
42 22
        );
43
44 22
        return $builder->build($collection ?? $this, $usingSort);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $collection seems to never exist and therefore isset should always be false.
Loading history...
45
    }
46
47 1
    public function withLeaves(bool $state = true): self
48
    {
49 1
        $this->withLeaves = $state;
50
51 1
        return $this;
52
    }
53
54 18
    public function loadMissingNodes($model): self
55
    {
56 18
        if ($this->hasMissingNodes($model)) {
57 4
            $this->appendAncestors($model);
58
        }
59
60 18
        return $this;
61
    }
62
63 1
    private function excludeLeaves(): void
64
    {
65 1
        foreach ($this->items as $key => $item) {
66
            /** @var LTreeModelTrait $item */
67 1
            if ($item->ltreeChildren->isEmpty() && $item->getLtreeParentId()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $item->getLtreeParentId() of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
68 1
                $this->forget($key);
69
            }
70
        }
71
    }
72
73
    /**
74
     * @param LTreeInterface|ModelInterface $model
75
     */
76 18
    private function hasMissingNodes($model): bool
77
    {
78 18
        $paths = collect();
79
80 18
        foreach ($this->items as $item) {
81 18
            $paths = $paths->merge($item->getLtreePath());
82
        }
83
84 18
        return $paths
85 18
            ->unique()
86 18
            ->diff($this->pluck($model->getKeyName()))
0 ignored issues
show
Bug introduced by
The method getKeyName() does not exist on Umbrellio\LTree\Interfaces\LTreeInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Umbrellio\LTree\Interfaces\LTreeInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
            ->diff($this->pluck($model->/** @scrutinizer ignore-call */ getKeyName()))
Loading history...
87 18
            ->isNotEmpty();
88
    }
89
90
    /**
91
     * @param LTreeInterface|ModelInterface $model
92
     */
93 4
    private function appendAncestors($model): void
94
    {
95 4
        $paths = $this
96 4
            ->pluck($model->getLtreePathColumn())
0 ignored issues
show
Bug introduced by
The method getLtreePathColumn() does not exist on Umbrellio\LTree\Interfaces\ModelInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Umbrellio\LTree\Interfaces\ModelInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

96
            ->pluck($model->/** @scrutinizer ignore-call */ getLtreePathColumn())
Loading history...
97 4
            ->toArray();
98 4
        $ids = $this
99 4
            ->pluck($model->getKeyName())
100 4
            ->toArray();
101
102
        /** @var Model $model */
103 4
        $parents = $model::parentsOf($paths)
0 ignored issues
show
Bug Best Practice introduced by
The method Illuminate\Database\Eloquent\Model::parentsOf() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
        $parents = $model::/** @scrutinizer ignore-call */ parentsOf($paths)
Loading history...
104 4
            ->whereKeyNot($ids)
0 ignored issues
show
Bug introduced by
The method whereKeyNot() does not exist on Illuminate\Database\Eloquent\Builder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

104
            ->/** @scrutinizer ignore-call */ whereKeyNot($ids)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105 4
            ->get();
106
107 4
        foreach ($parents as $item) {
108 3
            $this->add($item);
109
        }
110
    }
111
}
112