Passed
Push — master ( 266f6d...355071 )
by Jonas
12:15
created

IsRecursiveRelation   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 10
eloc 33
c 2
b 0
f 0
dl 0
loc 137
ccs 37
cts 37
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A addEagerExpression() 0 19 4
A shouldSelect() 0 3 1
A buildDictionary() 0 5 1
A replaceTableHash() 0 11 1
A __call() 0 19 2
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Query\Expression;
9
10
trait IsRecursiveRelation
11
{
12
    /**
13
     * Whether to include the parent model.
14
     *
15
     * @var bool
16
     */
17
    protected bool $andSelf;
18
19
    /**
20
     * Create a new recursive pivot relationship instance.
21
     *
22
     * @param \Illuminate\Database\Eloquent\Builder $query
23
     * @param \Illuminate\Database\Eloquent\Model $parent
24
     * @param string $table
25
     * @param string $foreignPivotKey
26
     * @param string $relatedPivotKey
27
     * @param string $parentKey
28
     * @param string $relatedKey
29
     * @param bool $andSelf
30
     * @return void
31
     */
32 230
    public function __construct(
33
        Builder $query,
34
        Model $parent,
35
        string $table,
36
        string $foreignPivotKey,
37
        string $relatedPivotKey,
38
        string $parentKey,
39
        string $relatedKey,
40
        bool $andSelf
41
    ) {
42 230
        $this->andSelf = $andSelf;
43
44 230
        parent::__construct($query, $parent, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey);
45
    }
46
47
    /**
48
     * Add the recursive expression for an eager load of the relation.
49
     *
50
     * @param array $models
51
     * @param string $column
52
     * @return void
53
     */
54 72
    protected function addEagerExpression(array $models, string $column): void
55
    {
56 72
        $whereIn = $this->whereInMethod($this->parent, $this->parentKey);
0 ignored issues
show
Bug introduced by
The method whereInMethod() does not exist on Staudenmeir\LaravelAdjac...its\IsRecursiveRelation. 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

56
        /** @scrutinizer ignore-call */ 
57
        $whereIn = $this->whereInMethod($this->parent, $this->parentKey);
Loading history...
57
58 72
        $keys = $this->getKeys($models, $this->parentKey);
0 ignored issues
show
Bug introduced by
The method getKeys() does not exist on Staudenmeir\LaravelAdjac...its\IsRecursiveRelation. 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 */ 
59
        $keys = $this->getKeys($models, $this->parentKey);
Loading history...
59
60 72
        $constraint = function (Builder $query) use ($models, $whereIn, $column, $keys) {
0 ignored issues
show
Unused Code introduced by
The import $models is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
61 72
            $query->$whereIn($column, $keys);
62
        };
63
64 72
        $supportsUnion = $this->query->getExpressionGrammar()->supportsUnionInRecursiveExpression();
65
66 72
        $union = $this->andSelf || !$supportsUnion ? 'unionAll' : 'union';
67
68 72
        if (!$supportsUnion) {
69 8
            $this->query->getQuery()->distinct();
70
        }
71
72 72
        $this->addExpression($constraint, null, null, $union);
0 ignored issues
show
Bug introduced by
The method addExpression() does not exist on Staudenmeir\LaravelAdjac...its\IsRecursiveRelation. 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

72
        $this->/** @scrutinizer ignore-call */ 
73
               addExpression($constraint, null, null, $union);
Loading history...
73
    }
74
75
    /**
76
     * Build model dictionary.
77
     *
78
     * @param \Illuminate\Database\Eloquent\Collection $results
79
     * @return array
80
     */
81 32
    protected function buildDictionary(Collection $results)
82
    {
83 32
        return $results->mapToDictionary(function (Model $result) {
84 32
            return [$result->getFirstPathSegment() => $result];
85 32
        })->all();
86
    }
87
88
    /**
89
     * Handle dynamic method calls to the relationship.
90
     *
91
     * @param string $method
92
     * @param array $parameters
93
     * @return mixed
94
     */
95 118
    public function __call($method, $parameters)
96
    {
97 118
        $methods = ['update', 'increment', 'decrement', 'delete', 'forceDelete'];
98
99 118
        if (in_array($method, $methods)) {
100 8
            $expression = $this->query->getQuery()->from;
101
102 8
            $table = $this->parent->getTable();
103
104 8
            $this->query->getQuery()->from = $table;
105
106 8
            $this->query->getModel()->setTable($table);
107
108 8
            $keys = $this->query->getQuery()->newQuery()->from($expression)->select($this->parentKey);
109
110 8
            return $this->query->whereIn($this->parentKey, $keys)->$method(...$parameters);
111
        }
112
113 110
        return parent::__call($method, $parameters);
114
    }
115
116
    /**
117
     * Replace table hash with expression name in self-relation aggregate queries.
118
     *
119
     * @param \Illuminate\Database\Eloquent\Builder $query
120
     * @param \Illuminate\Database\Query\Expression $expression
121
     * @return \Illuminate\Database\Query\Expression
122
     */
123 18
    protected function replaceTableHash(Builder $query, Expression $expression): Expression
124
    {
125 18
        return new Expression(
126 18
            str_replace(
127 18
                $query->getGrammar()->wrap(
0 ignored issues
show
Bug introduced by
It seems like $query->getGrammar()->wr...lationCountHash(false)) can also be of type Illuminate\Database\Eloquent\Builder and Illuminate\Database\Query\Grammars\Grammar; however, parameter $search of str_replace() does only seem to accept string|string[], 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

127
                /** @scrutinizer ignore-type */ $query->getGrammar()->wrap(
Loading history...
128 18
                    $this->getRelationCountHash(false)
0 ignored issues
show
Bug introduced by
The method getRelationCountHash() does not exist on Staudenmeir\LaravelAdjac...its\IsRecursiveRelation. 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

128
                    $this->/** @scrutinizer ignore-call */ 
129
                           getRelationCountHash(false)
Loading history...
129
                ),
130 18
                $query->getGrammar()->wrap(
0 ignored issues
show
Bug introduced by
It seems like $query->getGrammar()->wr...)->getExpressionName()) can also be of type Illuminate\Database\Eloquent\Builder and Illuminate\Database\Query\Grammars\Grammar; however, parameter $replace of str_replace() does only seem to accept string|string[], 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

130
                /** @scrutinizer ignore-type */ $query->getGrammar()->wrap(
Loading history...
131 18
                    $query->getModel()->getExpressionName()
132
                ),
133 18
                $expression->getValue(),
134
            )
135
        );
136
    }
137
138
    /**
139
     * Get the select columns for the relation query.
140
     *
141
     * @param array $columns
142
     * @return array
143
     */
144 198
    protected function shouldSelect(array $columns = ['*'])
145
    {
146 198
        return $columns;
147
    }
148
}
149