Test Failed
Pull Request — master (#48)
by
unknown
03:03
created

src/Relations/BelongsToTree.php (6 issues)

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
14
class BelongsToTree extends Relation
15
{
16
    protected $throughRelationName;
17
    private $foreignKey;
18
    private $ownerKey;
19
20
    public function __construct(
21
        Builder $query,
22
        Model $child,
23
        string $throughRelationName,
24
        string $foreignKey,
25
        string $ownerKey
26
    ) {
27
        $this->throughRelationName = $throughRelationName;
28
        $this->foreignKey = $foreignKey;
29
        $this->ownerKey = $ownerKey;
30
31
        parent::__construct($query, $child);
32
    }
33
34
    public function addConstraints(): void
35
    {
36
        if (static::$constraints) {
37
            $relation = $this->parent->{$this->throughRelationName};
38
39
            if ($relation) {
40
                $this->query = $relation
41
                    ->newQuery()
42
                    ->ancestorsOf($relation)
43
                    ->orderBy($this->getLTreeRelated()->getLtreePathColumn());
44
            }
45
        }
46
    }
47
48
    public function addEagerConstraints(array $models): void
49
    {
50
        $key = $this->related->getTable() . '.' . $this->ownerKey;
0 ignored issues
show
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

50
        $key = $this->related->/** @scrutinizer ignore-call */ getTable() . '.' . $this->ownerKey;
Loading history...
51
52
        $whereIn = $this->whereInMethod($this->related, $this->ownerKey);
53
54
        $this->query->{$whereIn}($key, $this->getEagerModelKeys($models));
55
56
        $table = $this
57
            ->getModel()
0 ignored issues
show
The method getModel() does not exist on Umbrellio\LTree\Relations\BelongsToTree. 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

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

63
        $this->query->/** @scrutinizer ignore-call */ 
64
                      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...
64
            sprintf('%s as %s', $table, $alias),
65
            function (JoinClause $query) use ($alias, $table, $related) {
66
                $query->whereRaw(sprintf('%1$s.%2$s @> %3$s.%2$s', $alias, $related->getLtreePathColumn(), $table));
67
            }
68
        );
69
70
        $this->query->orderBy($related->getLtreePathColumn());
0 ignored issues
show
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

70
        $this->query->/** @scrutinizer ignore-call */ 
71
                      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...
71
72
        $this->query->selectRaw(sprintf('%s.*, %s.%s as relation_id', $alias, $table, $this->ownerKey));
0 ignored issues
show
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

72
        $this->query->/** @scrutinizer ignore-call */ 
73
                      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...
73
    }
74
75
    public function match(array $models, Collection $results, $relation)
76
    {
77
        $dictionary = [];
78
79
        foreach ($results as $result) {
80
            $dictionary[$result->relation_id][] = $result;
81
        }
82
83
        foreach ($models as $model) {
84
            foreach ($dictionary as $related => $value) {
85
                if ($model->getAttribute($this->foreignKey) === $related) {
86
                    $model->setRelation($relation, $this->related->newCollection($value));
0 ignored issues
show
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

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