AbstractBelongsToTree   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 19
eloc 59
c 0
b 0
f 0
dl 0
loc 142
ccs 66
cts 66
cp 1
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A getParentKey() 0 3 1
A getEagerModelKeys() 0 13 3
A getResults() 0 5 2
A match() 0 17 5
A addConstraints() 0 10 3
A initRelation() 0 7 2
A getLTreeRelated() 0 6 1
A addEagerConstraints() 0 31 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Umbrellio\LTree\Relations;
6
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Database\Eloquent\Collection;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Eloquent\Relations\Relation;
11
use Illuminate\Database\Query\JoinClause;
12
use Umbrellio\LTree\Interfaces\LTreeModelInterface;
13
use Umbrellio\LTree\Traits\LTreeModelTrait;
14
15
abstract class AbstractBelongsToTree extends Relation
16
{
17
    protected $throughRelationName;
18
    private $foreignKey;
19
    private $ownerKey;
20
21 3
    public function __construct(
22
        Builder $query,
23
        Model $child,
24
        string $throughRelationName,
25
        string $foreignKey,
26
        string $ownerKey
27
    ) {
28 3
        $this->throughRelationName = $throughRelationName;
29 3
        $this->foreignKey = $foreignKey;
30 3
        $this->ownerKey = $ownerKey;
31
32 3
        parent::__construct($query, $child);
33
    }
34
35 3
    public function addConstraints(): void
36
    {
37 3
        if (static::$constraints) {
38
            /** @var Model $relation */
39 3
            $relation = $this->parent->{$this->throughRelationName};
40
41 3
            if ($relation) {
0 ignored issues
show
introduced by
$relation is of type Illuminate\Database\Eloquent\Model, thus it always evaluated to true.
Loading history...
42 3
                $this->query = $this
43 3
                    ->modifyQuery($relation->newQuery(), $relation)
0 ignored issues
show
Bug introduced by
The method newQuery() does not exist on Illuminate\Database\Eloquent\Model. ( Ignorable by Annotation )

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

43
                    ->modifyQuery($relation->/** @scrutinizer ignore-call */ newQuery(), $relation)

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...
44 3
                    ->orderBy($this->getLTreeRelated()->getLtreePathColumn());
45
            }
46
        }
47
    }
48
49 3
    public function addEagerConstraints(array $models): void
50
    {
51 3
        $key = $this->related->getTable() . '.' . $this->ownerKey;
0 ignored issues
show
Bug introduced by
The method getTable() does not exist on Illuminate\Database\Eloquent\Model. It seems like you code against a sub-type of Illuminate\Database\Eloquent\Model such as Illuminate\Database\Eloquent\Relations\Pivot. ( Ignorable by Annotation )

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

51
        $key = $this->related->/** @scrutinizer ignore-call */ getTable() . '.' . $this->ownerKey;
Loading history...
52
53 3
        $whereIn = $this->whereInMethod($this->related, $this->ownerKey);
54
55 3
        $this->query->{$whereIn}($key, $this->getEagerModelKeys($models));
56
57 3
        $table = $this
58 3
            ->getModel()
0 ignored issues
show
Bug introduced by
The method getModel() does not exist on Umbrellio\LTree\Relations\AbstractBelongsToTree. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

58
            ->/** @scrutinizer ignore-call */ getModel()
Loading history...
59 3
            ->getTable();
60 3
        $alias = sprintf('%s_depends', $table);
61
62 3
        $related = $this->getLTreeRelated();
63
64 3
        $this->query->join(
0 ignored issues
show
Bug introduced by
The method join() 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

64
        $this->query->/** @scrutinizer ignore-call */ 
65
                      join(

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...
65 3
            sprintf('%s as %s', $table, $alias),
66 3
            function (JoinClause $query) use ($alias, $table, $related) {
67 3
                $query->whereRaw(sprintf(
68 3
                    '%1$s.%2$s %4$s %3$s.%2$s',
69 3
                    $alias,
70 3
                    $related->getLtreePathColumn(),
71 3
                    $table,
72 3
                    $this->getOperator()
73 3
                ));
74 3
            }
75 3
        );
76
77 3
        $this->query->orderBy($related->getLtreePathColumn());
0 ignored issues
show
Bug introduced by
The method orderBy() 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

77
        $this->query->/** @scrutinizer ignore-call */ 
78
                      orderBy($related->getLtreePathColumn());

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...
78
79 3
        $this->query->selectRaw(sprintf('%s.*, %s.%s as relation_id', $alias, $table, $this->ownerKey));
0 ignored issues
show
Bug introduced by
The method selectRaw() 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

79
        $this->query->/** @scrutinizer ignore-call */ 
80
                      selectRaw(sprintf('%s.*, %s.%s as relation_id', $alias, $table, $this->ownerKey));

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...
80
    }
81
82 3
    public function match(array $models, Collection $results, $relation)
83
    {
84 3
        $dictionary = [];
85
86 3
        foreach ($results as $result) {
87 3
            $dictionary[$result->relation_id][] = $result;
88
        }
89
90 3
        foreach ($models as $model) {
91 3
            foreach ($dictionary as $related => $value) {
92 3
                if ($model->getAttribute($this->foreignKey) === $related) {
93 3
                    $model->setRelation($relation, $this->related->newCollection($value));
0 ignored issues
show
Bug introduced by
The method newCollection() does not exist on Illuminate\Database\Eloquent\Model. It seems like you code against a sub-type of Illuminate\Database\Eloquent\Model such as Umbrellio\LTree\tests\_data\Models\CategoryStub or Umbrellio\LTree\tests\_data\Models\ProductStub or Illuminate\Notifications\DatabaseNotification. ( Ignorable by Annotation )

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

93
                    $model->setRelation($relation, $this->related->/** @scrutinizer ignore-call */ newCollection($value));
Loading history...
94
                }
95
            }
96
        }
97
98 3
        return $models;
99
    }
100
101 3
    public function getResults()
102
    {
103 3
        return $this->getParentKey() !== null
104 3
            ? $this->query->get()
105 3
            : $this->related->newCollection();
106
    }
107
108
109
    /**
110
     * Initialize the relation on a set of models.
111
     *
112
     * @param string $relation
113
     * @return array
114
     */
115 3
    public function initRelation(array $models, $relation)
116
    {
117 3
        foreach ($models as $model) {
118 3
            $model->setRelation($relation, $this->related->newCollection());
119
        }
120
121 3
        return $models;
122
    }
123
124
    /**
125
     * @param Builder|LTreeModelTrait $query
126
     */
127
    abstract protected function modifyQuery($query, Model $model): Builder;
128
129
    abstract protected function getOperator(): string;
130
131 3
    protected function getEagerModelKeys(array $models)
132
    {
133 3
        $keys = [];
134
135 3
        foreach ($models as $model) {
136 3
            if (($value = $model->{$this->foreignKey}) !== null) {
137 3
                $keys[] = $value;
138
            }
139
        }
140
141 3
        sort($keys);
142
143 3
        return array_values(array_unique($keys));
144
    }
145
146 3
    private function getLTreeRelated(): LTreeModelInterface
147
    {
148 3
        return $this
149 3
            ->parent
150 3
            ->{$this->throughRelationName}()
151 3
            ->related;
152
    }
153
154 3
    private function getParentKey()
155
    {
156 3
        return $this->parent->{$this->foreignKey};
157
    }
158
}
159