Passed
Push — master ( 6ed66a...c3d33f )
by Jonas
06:02
created

IsAncestorRelation::getRelationExistenceQuery()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 17
rs 9.9666
cc 3
nc 3
nop 3
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Relations;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
8
trait IsAncestorRelation
9
{
10
    use IsRecursiveRelation;
11
12
    /**
13
     * Set the base constraints on the relation query.
14
     *
15
     * @return void
16
     */
17
    public function addConstraints()
18
    {
19
        if (static::$constraints) {
20
            $constraint = function (Builder $query) {
21
                $key = $this->andSelf ? $this->getParentKey() : $this->getForeignKey();
0 ignored issues
show
Bug introduced by
The method getParentKey() does not exist on Staudenmeir\LaravelAdjac...ions\IsAncestorRelation. 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

21
                $key = $this->andSelf ? $this->/** @scrutinizer ignore-call */ getParentKey() : $this->getForeignKey();
Loading history...
22
23
                $query->where($this->getQualifiedLocalKeyName(), '=', $key);
24
            };
25
26
            $this->addExpression($constraint);
27
        }
28
    }
29
30
    /**
31
     * Set the constraints for an eager load of the relation.
32
     *
33
     * @param array $models
34
     * @return void
35
     */
36
    public function addEagerConstraints(array $models)
37
    {
38
        $whereIn = $this->whereInMethod($this->parent, $this->localKey);
0 ignored issues
show
Bug introduced by
The method whereInMethod() does not exist on Staudenmeir\LaravelAdjac...ions\IsAncestorRelation. 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

38
        /** @scrutinizer ignore-call */ 
39
        $whereIn = $this->whereInMethod($this->parent, $this->localKey);
Loading history...
39
40
        $key = $this->andSelf ? $this->localKey : $this->getForeignKeyName();
0 ignored issues
show
Bug introduced by
The method getForeignKeyName() does not exist on Staudenmeir\LaravelAdjac...ions\IsAncestorRelation. 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

40
        $key = $this->andSelf ? $this->localKey : $this->/** @scrutinizer ignore-call */ getForeignKeyName();
Loading history...
41
42
        $keys = $this->getKeys($models, $key);
43
44
        $constraint = function (Builder $query) use ($whereIn, $keys) {
45
            $query->$whereIn($this->getQualifiedLocalKeyName(), $keys);
46
        };
47
48
        $this->addExpression($constraint);
49
    }
50
51
    /**
52
     * Get all of the primary keys for an array of models.
53
     *
54
     * @param array $models
55
     * @param string $key
56
     * @return array
57
     */
58
    protected function getKeys(array $models, $key = null)
59
    {
60
        $keys = parent::getKeys($models, $key);
61
62
        return array_filter($keys, function ($value) {
63
            return !is_null($value);
64
        });
65
    }
66
67
    /**
68
     * Match the eagerly loaded results to their many parents.
69
     *
70
     * @param array $models
71
     * @param \Illuminate\Database\Eloquent\Collection $results
72
     * @param string $relation
73
     * @param string $type
74
     * @return array
75
     */
76
    public function matchOneOrMany(array $models, Collection $results, $relation, $type)
77
    {
78
        $dictionary = $this->buildDictionary($results);
79
80
        $attribute = $this->andSelf ? $this->localKey : $this->getForeignKeyName();
81
82
        foreach ($models as $model) {
83
            $key = $model->{$attribute};
84
85
            if (isset($dictionary[$key])) {
86
                $value = $this->getRelationValue($dictionary, $key, $type);
0 ignored issues
show
Bug introduced by
The method getRelationValue() does not exist on Staudenmeir\LaravelAdjac...ions\IsAncestorRelation. 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

86
                /** @scrutinizer ignore-call */ 
87
                $value = $this->getRelationValue($dictionary, $key, $type);
Loading history...
87
88
                $model->setRelation($relation, $value);
89
            }
90
        }
91
92
        return $models;
93
    }
94
95
    /**
96
     * Add the constraints for a relationship query.
97
     *
98
     * @param \Illuminate\Database\Eloquent\Builder $query
99
     * @param \Illuminate\Database\Eloquent\Builder $parentQuery
100
     * @param array|mixed $columns
101
     * @return \Illuminate\Database\Eloquent\Builder
102
     */
103
    public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
104
    {
105
        if ($query->getQuery()->from === $parentQuery->getQuery()->from) {
106
            return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
107
        }
108
109
        $key = $this->andSelf ? $this->localKey : $this->getForeignKeyName();
110
111
        $constraint = function (Builder $query) use ($key) {
112
            $query->whereColumn(
113
                $query->getQuery()->from.'.'.$this->localKey,
114
                '=',
115
                $this->parent->qualifyColumn($key)
116
            );
117
        };
118
119
        return $this->addExpression($constraint, $query->select($columns));
0 ignored issues
show
Bug introduced by
It seems like $query->select($columns) can also be of type Illuminate\Database\Query\Builder; however, parameter $query of Staudenmeir\LaravelAdjac...lation::addExpression() does only seem to accept Illuminate\Database\Eloquent\Builder|null, maybe add an additional type check? ( Ignorable by Annotation )

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

119
        return $this->addExpression($constraint, /** @scrutinizer ignore-type */ $query->select($columns));
Loading history...
120
    }
121
122
    /**
123
     * Add the constraints for a relationship query on the same table.
124
     *
125
     * @param \Illuminate\Database\Eloquent\Builder $query
126
     * @param \Illuminate\Database\Eloquent\Builder $parentQuery
127
     * @param array|mixed $columns
128
     * @return \Illuminate\Database\Eloquent\Builder
129
     */
130
    public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
131
    {
132
        $table = $this->getRelationCountHash();
0 ignored issues
show
Bug introduced by
The method getRelationCountHash() does not exist on Staudenmeir\LaravelAdjac...ions\IsAncestorRelation. 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

132
        /** @scrutinizer ignore-call */ 
133
        $table = $this->getRelationCountHash();
Loading history...
133
134
        $from = $query->getModel()->getTable().' as '.$table;
135
136
        $query->getModel()->setTable($table);
137
138
        $key = $this->andSelf ? $this->localKey : $this->getForeignKeyName();
139
140
        $constraint = function (Builder $query) use ($table, $key) {
141
            $query->whereColumn(
142
                $table.'.'.$this->localKey,
143
                '=',
144
                $this->parent->qualifyColumn($key)
145
            );
146
        };
147
148
        return $this->addExpression($constraint, $query->select($columns), $from);
0 ignored issues
show
Bug introduced by
It seems like $query->select($columns) can also be of type Illuminate\Database\Query\Builder; however, parameter $query of Staudenmeir\LaravelAdjac...lation::addExpression() does only seem to accept Illuminate\Database\Eloquent\Builder|null, maybe add an additional type check? ( Ignorable by Annotation )

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

148
        return $this->addExpression($constraint, /** @scrutinizer ignore-type */ $query->select($columns), $from);
Loading history...
149
    }
150
151
    /**
152
     * Add a recursive expression to the query.
153
     *
154
     * @param callable $constraint
155
     * @param \Illuminate\Database\Eloquent\Builder|null $query
156
     * @param string|null $from
157
     * @return \Illuminate\Database\Eloquent\Builder
158
     */
159
    protected function addExpression(callable $constraint, Builder $query = null, $from = null)
160
    {
161
        $query = $query ?: $this->query;
162
163
        $initialDepth = $this->andSelf ? 0 : -1;
164
165
        return $query->withRelationshipExpression('asc', $constraint, $initialDepth, $from);
166
    }
167
168
    /**
169
     * Get the key value of the parent's foreign key.
170
     *
171
     * @return mixed
172
     */
173
    public function getForeignKey()
174
    {
175
        return $this->parent->{$this->getForeignKeyName()};
176
    }
177
}
178