IsAncestorRelation   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
eloc 49
c 0
b 0
f 0
dl 0
loc 172
ccs 62
cts 62
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A matchOneOrMany() 0 17 4
A getForeignKey() 0 3 1
A addExpression() 0 7 3
A getKeys() 0 6 1
A getRelationExistenceQuery() 0 17 3
A addEagerConstraints() 0 13 2
A addConstraints() 0 10 3
A getRelationExistenceQueryForSelfRelation() 0 23 3
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\Query\Expression;
8
9
trait IsAncestorRelation
10
{
11
    use IsRecursiveRelation;
12
13
    /**
14
     * Set the base constraints on the relation query.
15
     *
16
     * @return void
17
     */
18 215
    public function addConstraints()
19
    {
20 215
        if (static::$constraints) {
21 113
            $constraint = function (Builder $query) {
22 113
                $key = $this->andSelf ? $this->getParentKey() : $this->getForeignKey();
0 ignored issues
show
Bug introduced by
The method getParentKey() does not exist on Staudenmeir\LaravelAdjac...aits\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

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

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

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

87
                /** @scrutinizer ignore-call */ 
88
                $value = $this->getRelationValue($dictionary, $key, $type);
Loading history...
88
89 36
                $model->setRelation($relation, $value);
90
            }
91
        }
92
93 36
        return $models;
94
    }
95
96
    /**
97
     * Add the constraints for a relationship query.
98
     *
99
     * @param \Illuminate\Database\Eloquent\Builder $query
100
     * @param \Illuminate\Database\Eloquent\Builder $parentQuery
101
     * @param array|mixed $columns
102
     * @return \Illuminate\Database\Eloquent\Builder
103
     */
104 36
    public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
105
    {
106 36
        if ($query->getQuery()->from === $parentQuery->getQuery()->from) {
107 21
            return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
108
        }
109
110 15
        $key = $this->andSelf ? $this->localKey : $this->getForeignKeyName();
111
112 15
        $constraint = function (Builder $query) use ($key) {
113 15
            $query->whereColumn(
114 15
                $query->getQuery()->from.'.'.$this->localKey,
0 ignored issues
show
Bug introduced by
Are you sure $query->getQuery()->from of type Illuminate\Database\Query\Expression|string can be used in concatenation? ( Ignorable by Annotation )

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

114
                /** @scrutinizer ignore-type */ $query->getQuery()->from.'.'.$this->localKey,
Loading history...
115 15
                '=',
116 15
                $this->parent->qualifyColumn($key)
117 15
            );
118 15
        };
119
120 15
        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

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

137
        /** @scrutinizer ignore-call */ 
138
        $table = $this->getRelationCountHash();
Loading history...
138
139 21
        $from = $query->getModel()->getTable().' as '.$table;
140
141 21
        $query->getModel()->setTable($table);
142
143 21
        $key = $this->andSelf ? $this->localKey : $this->getForeignKeyName();
144
145 21
        $constraint = function (Builder $query) use ($table, $key) {
146 21
            $query->whereColumn(
147 21
                $table.'.'.$this->localKey,
148 21
                '=',
149 21
                $this->parent->qualifyColumn($key)
150 21
            );
151 21
        };
152
153 21
        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

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