Passed
Push — master ( 8ebaea...4d9ab5 )
by Jonas
03:08
created

addInitialQueryPivotColumns()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 11
c 2
b 0
f 0
dl 0
loc 22
ccs 10
cts 10
cp 1
rs 9.9
cc 4
nc 4
nop 4
crap 4
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Support\Collection;
7
use Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar;
8
9
trait HasGraphRelationshipScopes
10
{
11
    /**
12
     * Add a recursive expression for a custom subgraph to the query.
13
     *
14
     * @param \Illuminate\Database\Eloquent\Builder $query
15
     * @param callable $constraint
16
     * @param int|null $maxDepth
17
     * @return \Illuminate\Database\Eloquent\Builder
18
     */
19 8
    public function scopeSubgraph(Builder $query, callable $constraint, int $maxDepth = null): Builder
20
    {
21 8
        return $query->withRelationshipExpression('desc', $constraint, 0, null, $maxDepth);
22
    }
23
24
    /**
25
     * Limit the query by depth.
26
     *
27
     * @param \Illuminate\Database\Eloquent\Builder $query
28
     * @param mixed $operator
29
     * @param mixed|null $value
30
     * @return \Illuminate\Database\Eloquent\Builder
31
     */
32 28
    public function scopeWhereDepth(Builder $query, mixed $operator, mixed $value = null): Builder
33
    {
34 28
        $arguments = array_slice(func_get_args(), 1);
35
36 28
        return $query->where($this->getDepthName(), ...$arguments);
0 ignored issues
show
Bug introduced by
It seems like getDepthName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

36
        return $query->where($this->/** @scrutinizer ignore-call */ getDepthName(), ...$arguments);
Loading history...
37
    }
38
39
    /**
40
     * Order the query breadth-first.
41
     *
42
     * @param \Illuminate\Database\Eloquent\Builder $query
43
     * @return \Illuminate\Database\Eloquent\Builder
44
     */
45 5
    public function scopeBreadthFirst(Builder $query): Builder
46
    {
47 5
        return $query->orderBy($this->getDepthName());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->orderBy($this->getDepthName()) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
48
    }
49
50
    /**
51
     * Order the query depth-first.
52
     *
53
     * @param \Illuminate\Database\Eloquent\Builder $query
54
     * @return \Illuminate\Database\Eloquent\Builder
55
     */
56 5
    public function scopeDepthFirst(Builder $query): Builder
57
    {
58 5
        $sql = $query->getExpressionGrammar()->compileOrderByPath();
59
60 5
        return $query->orderByRaw($sql);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->orderByRaw($sql) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
61
    }
62
63
    /**
64
     * Add a recursive expression for the relationship to the query.
65
     *
66
     * @param \Illuminate\Database\Eloquent\Builder $query
67
     * @param string $direction
68
     * @param callable $constraint
69
     * @param int $initialDepth
70
     * @param string|null $from
71
     * @param int|null $maxDepth
72
     * @param string $union
73
     * @return \Illuminate\Database\Eloquent\Builder
74
     */
75 270
    public function scopeWithRelationshipExpression(
76
        Builder $query,
77
        string $direction,
78
        callable $constraint,
79
        int $initialDepth,
80
        string $from = null,
81
        int $maxDepth = null,
82
        string $union = 'unionAll'
83
    ): Builder {
84 270
        $from = $from ?: $this->getTable();
0 ignored issues
show
Bug introduced by
It seems like getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

84
        $from = $from ?: $this->/** @scrutinizer ignore-call */ getTable();
Loading history...
85
86 270
        $grammar = $query->getExpressionGrammar();
87
88 270
        $expression = $this->getInitialQuery($grammar, $constraint, $initialDepth, $from)
0 ignored issues
show
Bug introduced by
It seems like $grammar can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $grammar of Staudenmeir\LaravelAdjac...opes::getInitialQuery() does only seem to accept Staudenmeir\LaravelAdjac...mmars\ExpressionGrammar, 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

88
        $expression = $this->getInitialQuery(/** @scrutinizer ignore-type */ $grammar, $constraint, $initialDepth, $from)
Loading history...
89 270
            ->$union(
90 270
                $this->getRecursiveQuery($grammar, $direction, $from, $maxDepth)
0 ignored issues
show
Bug introduced by
It seems like $grammar can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $grammar of Staudenmeir\LaravelAdjac...es::getRecursiveQuery() does only seem to accept Staudenmeir\LaravelAdjac...mmars\ExpressionGrammar, 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

90
                $this->getRecursiveQuery(/** @scrutinizer ignore-type */ $grammar, $direction, $from, $maxDepth)
Loading history...
91 270
            );
92
93 270
        $name = $this->getExpressionName();
0 ignored issues
show
Bug introduced by
It seems like getExpressionName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

93
        /** @scrutinizer ignore-call */ 
94
        $name = $this->getExpressionName();
Loading history...
94
95 270
        $query->getModel()->setTable($name);
96
97 270
        return $query->withRecursiveExpression($name, $expression)->from($name);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->withRecur...xpression)->from($name) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
98
    }
99
100
    /**
101
     * Get the initial query for a relationship expression.
102
     *
103
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
104
     * @param callable $constraint
105
     * @param int $initialDepth
106
     * @param array $pivotColumns
107
     * @param string $from
108
     * @return \Illuminate\Database\Eloquent\Builder $query
109
     */
110 270
    protected function getInitialQuery(
111
        ExpressionGrammar $grammar,
112
        callable $constraint,
113
        int $initialDepth,
114
        string $from
115
    ): Builder {
116 270
        $table = explode(' as ', $from)[1] ?? $from;
117
118 270
        $pivotTable = $this->getPivotTableName();
0 ignored issues
show
Bug introduced by
It seems like getPivotTableName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

118
        /** @scrutinizer ignore-call */ 
119
        $pivotTable = $this->getPivotTableName();
Loading history...
119
120 270
        $depth = $grammar->wrap(
0 ignored issues
show
Bug introduced by
The method wrap() does not exist on Staudenmeir\LaravelAdjac...mmars\ExpressionGrammar. It seems like you code against a sub-type of said class. However, the method does not exist in Staudenmeir\LaravelAdjac...rammars\FirebirdGrammar or Staudenmeir\LaravelAdjac...mars\SingleStoreGrammar. Are you sure you never get one of those? ( Ignorable by Annotation )

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

120
        /** @scrutinizer ignore-call */ 
121
        $depth = $grammar->wrap(
Loading history...
121 270
            $this->getDepthName()
122 270
        );
123
124 270
        $initialPath = $grammar->compileInitialPath(
125 270
            $this->getQualifiedLocalKeyName(),
0 ignored issues
show
Bug introduced by
It seems like getQualifiedLocalKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

125
            $this->/** @scrutinizer ignore-call */ 
126
                   getQualifiedLocalKeyName(),
Loading history...
126 270
            $this->getPathName()
0 ignored issues
show
Bug introduced by
It seems like getPathName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

126
            $this->/** @scrutinizer ignore-call */ 
127
                   getPathName()
Loading history...
127 270
        );
128
129 270
        $query = $this->newModelQuery()
0 ignored issues
show
Bug introduced by
It seems like newModelQuery() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

129
        $query = $this->/** @scrutinizer ignore-call */ newModelQuery()
Loading history...
130 270
            ->select("$table.*")
131 270
            ->selectRaw($initialDepth . ' as ' . $depth)
132 270
            ->selectRaw($initialPath)
133 270
            ->from($from);
134
135 270
        $this->addInitialQueryCustomPaths($query, $grammar);
136
137 270
        $this->addInitialQueryPivotColumns($query, $grammar, $pivotTable, $initialDepth);
138
139 270
        $this->addInitialQueryCycleDetection($query, $grammar);
140
141 270
        $this->addInitialQueryJoins($query, $pivotTable, $initialDepth);
142
143 270
        $constraint($query);
144
145 270
        if (static::$initialQueryConstraint) {
146
            (static::$initialQueryConstraint)($query);
147
        }
148
149
        return $query;
150
    }
151
152
    /**
153
     * Add custom paths to the initial query.
154
     *
155 270
     * @param \Illuminate\Database\Eloquent\Builder $query
156
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
157 270
     * @return void
158 270
     */
159 270
    protected function addInitialQueryCustomPaths(Builder $query, ExpressionGrammar $grammar): void
160 270
    {
161 270
        foreach ($this->getCustomPaths() as $path) {
0 ignored issues
show
Bug introduced by
It seems like getCustomPaths() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

161
        foreach ($this->/** @scrutinizer ignore-call */ getCustomPaths() as $path) {
Loading history...
162 270
            $query->selectRaw(
163 270
                $grammar->compileInitialPath(
164
                    is_string($path['column']) ? $this->qualifyColumn($path['column']) : $path['column'],
0 ignored issues
show
Bug introduced by
It seems like qualifyColumn() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

164
                    is_string($path['column']) ? $this->/** @scrutinizer ignore-call */ qualifyColumn($path['column']) : $path['column'],
Loading history...
165
                    $path['name']
166
                )
167
            );
168
        }
169
    }
170
171
    /**
172
     * Add pivot columns to the initial query for a relationship expression.
173
     *
174
     * @param \Illuminate\Database\Eloquent\Builder $query
175
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
176 270
     * @param string $pivotTable
177
     * @param int $initialDepth
178
     * @return void
179
     */
180
    protected function addInitialQueryPivotColumns(
181
        Builder $query,
182 270
        ExpressionGrammar $grammar,
183
        string $pivotTable,
184 270
        int $initialDepth
185 96
    ): void {
186
        $columns = [$this->getParentKeyName(), $this->getChildKeyName(), ...$this->getPivotColumns()];
0 ignored issues
show
Bug introduced by
It seems like getPivotColumns() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

186
        $columns = [$this->getParentKeyName(), $this->getChildKeyName(), ...$this->/** @scrutinizer ignore-call */ getPivotColumns()];
Loading history...
Bug introduced by
It seems like getParentKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

186
        $columns = [$this->/** @scrutinizer ignore-call */ getParentKeyName(), $this->getChildKeyName(), ...$this->getPivotColumns()];
Loading history...
Bug introduced by
It seems like getChildKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

186
        $columns = [$this->getParentKeyName(), $this->/** @scrutinizer ignore-call */ getChildKeyName(), ...$this->getPivotColumns()];
Loading history...
187
188
        if ($initialDepth === 0) {
189
            $columnDefinitions = (new Collection($query->getConnection()->getSchemaBuilder()->getColumns($pivotTable)))
190
                ->keyBy('name');
191
192
            foreach ($columns as $column) {
193 96
                $columnDefinition = $columnDefinitions[$column];
194 96
195 96
                $null = $grammar->compilePivotColumnNullValue($columnDefinition['type_name'], $columnDefinition['type']);
196 96
197
                $query->selectRaw("$null as " . $grammar->wrap("pivot_$column"));
198 96
            }
199 96
        } else {
200 96
            foreach ($columns as $column) {
201
                $query->addSelect("$pivotTable.$column as pivot_$column");
202 96
            }
203
        }
204
    }
205 96
206
    /**
207 96
     * Add cycle detection to the initial query for a relationship expression.
208 96
     *
209 96
     * @param \Illuminate\Database\Eloquent\Builder $query
210 96
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
211 96
     * @return void
212
     */
213 96
    protected function addInitialQueryCycleDetection(Builder $query, ExpressionGrammar $grammar): void
214
    {
215
        if ($this->enableCycleDetection() && $this->includeCycleStart()) {
0 ignored issues
show
Bug introduced by
It seems like includeCycleStart() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

215
        if ($this->enableCycleDetection() && $this->/** @scrutinizer ignore-call */ includeCycleStart()) {
Loading history...
Bug introduced by
It seems like enableCycleDetection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

215
        if ($this->/** @scrutinizer ignore-call */ enableCycleDetection() && $this->includeCycleStart()) {
Loading history...
216 186
            $query->selectRaw(
217 186
                $grammar->compileCycleDetectionInitialSelect(
218
                    $this->getCycleDetectionColumnName()
0 ignored issues
show
Bug introduced by
It seems like getCycleDetectionColumnName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

218
                    $this->/** @scrutinizer ignore-call */ 
219
                           getCycleDetectionColumnName()
Loading history...
219
                )
220
            );
221
        }
222
    }
223
224
    /**
225
     * Add join clauses to the initial query for a relationship expression.
226
     *
227
     * @param \Illuminate\Database\Eloquent\Builder $query
228
     * @param string $pivotTable
229 270
     * @param int $initialDepth
230
     * @return void
231 270
     */
232 58
    protected function addInitialQueryJoins(Builder $query, string $pivotTable, int $initialDepth): void
233 58
    {
234 58
        if ($initialDepth < 0) {
235 58
            $query->join(
236 58
                $pivotTable,
237
                $this->getQualifiedLocalKeyName(),
238
                '=',
239
                $this->getQualifiedParentKeyName()
0 ignored issues
show
Bug introduced by
It seems like getQualifiedParentKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

239
                $this->/** @scrutinizer ignore-call */ 
240
                       getQualifiedParentKeyName()
Loading history...
240
            );
241
        } elseif ($initialDepth > 0) {
242
            $query->join(
243
                $pivotTable,
244
                $this->getQualifiedLocalKeyName(),
245
                '=',
246
                $this->getQualifiedChildKeyName()
0 ignored issues
show
Bug introduced by
It seems like getQualifiedChildKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

246
                $this->/** @scrutinizer ignore-call */ 
247
                       getQualifiedChildKeyName()
Loading history...
247
            );
248 270
        }
249
    }
250 270
251 87
    /**
252 87
     * Get the recursive query for a relationship expression.
253 87
     *
254 87
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
255 87
     * @param string $direction
256 87
     * @param string $from
257 204
     * @param int|null $maxDepth
258 111
     * @return \Illuminate\Database\Eloquent\Builder $query
259 111
     */
260 111
    protected function getRecursiveQuery(
261 111
        ExpressionGrammar $grammar,
262 111
        string $direction,
263 111
        string $from,
264
        int $maxDepth = null
265
    ): Builder {
266
        $name = $this->getExpressionName();
267
268
        $table = explode(' as ', $from)[1] ?? $from;
269
270
        $pivotTable = $this->getPivotTableName();
271
272
        $depth = $grammar->wrap($this->getDepthName());
273
274
        $joinColumns = [
275
            'asc' => [
276 270
                $name . '.' . $this->getLocalKeyName(),
0 ignored issues
show
Bug introduced by
It seems like getLocalKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

276
                $name . '.' . $this->/** @scrutinizer ignore-call */ getLocalKeyName(),
Loading history...
277
                $this->getQualifiedChildKeyName(),
278
            ],
279
            'desc' => [
280
                $name . '.' . $this->getLocalKeyName(),
281
                $this->getQualifiedParentKeyName(),
282 270
            ],
283
        ];
284 270
285
        $recursiveDepth = $depth . ' ' . ($direction === 'asc' ? '-' : '+') . ' 1';
286 270
287
        $recursivePath = $grammar->compileRecursivePath(
288 270
            $this->getQualifiedLocalKeyName(),
289
            $this->getPathName()
290 270
        );
291 270
292 270
        $recursivePathBindings = $grammar->getRecursivePathBindings($this->getPathSeparator());
0 ignored issues
show
Bug introduced by
It seems like getPathSeparator() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

292
        $recursivePathBindings = $grammar->getRecursivePathBindings($this->/** @scrutinizer ignore-call */ getPathSeparator());
Loading history...
293 270
294 270
        $query = $this->newModelQuery()
295 270
            ->select($table . '.*')
296 270
            ->selectRaw($recursiveDepth . ' as ' . $depth)
297 270
            ->selectRaw($recursivePath, $recursivePathBindings)
298 270
            ->from($from);
299 270
300
        $this->addRecursiveQueryCustomPaths($query, $grammar);
301 270
302
        $this->addRecursiveQueryPivotColumns($query, $pivotTable);
303 270
304 270
        $this->addRecursiveQueryCycleDetection($query, $grammar);
305 270
306 270
        $this->addRecursiveQueryJoinsAndConstraints($query, $pivotTable, $direction, $name, $joinColumns);
307
308 270
        if (!is_null($maxDepth)) {
309
            $query->where($this->getDepthName(), '<', $maxDepth);
310 270
        }
311 270
312 270
        return $query;
313 270
    }
314 270
315
    /**
316 270
     * Add customs path to the recursive query for a relationship expression.
317
     *
318 270
     * @param \Illuminate\Database\Eloquent\Builder $query
319
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
320 270
     * @return void
321
     */
322 270
    protected function addRecursiveQueryCustomPaths(Builder $query, ExpressionGrammar $grammar): void
323
    {
324 270
        foreach ($this->getCustomPaths() as $path) {
325 4
            $query->selectRaw(
326
                $grammar->compileRecursivePath(
327
                    is_string($path['column']) ? $this->qualifyColumn($path['column']) : $path['column'],
328 270
                    $path['name'],
329
                    $path['reverse'] ?? false
330
                ),
331
                $grammar->getRecursivePathBindings($path['separator'])
332
            );
333
        }
334
    }
335
336
    /**
337
     * Add pivot columns to the recursive query for a relationship expression.
338 270
     *
339
     * @param \Illuminate\Database\Eloquent\Builder $query
340 270
     * @param string $pivotTable
341 270
     * @return void
342 270
     */
343 270
    protected function addRecursiveQueryPivotColumns(Builder $query, string $pivotTable): void
344 270
    {
345 270
        $columns = [$this->getParentKeyName(), $this->getChildKeyName(), ...$this->getPivotColumns()];
346 270
347 270
        foreach ($columns as $column) {
348 270
            $query->addSelect("$pivotTable.$column as pivot_$column");
349
        }
350
    }
351
352
    /**
353
     * Add cycle detection to the recursive query for a relationship expression.
354
     *
355
     * @param \Illuminate\Database\Eloquent\Builder $query
356
     * @param \Staudenmeir\LaravelAdjacencyList\Query\Grammars\ExpressionGrammar $grammar
357
     * @return void
358
     */
359 270
    protected function addRecursiveQueryCycleDetection(Builder $query, ExpressionGrammar $grammar): void
360
    {
361 270
        if (!$this->enableCycleDetection()) {
362
            return;
363 270
        }
364 270
365
        $sql = $grammar->compileCycleDetection(
366
            $this->getQualifiedLocalKeyName(),
367
            $this->getPathName()
368
        );
369
370
        $bindings = $grammar->getCycleDetectionBindings(
371
            $this->getPathSeparator()
372
        );
373
374
        if ($this->includeCycleStart()) {
375 270
            $cycleDetectionColumn = $this->getCycleDetectionColumnName();
376
377 270
            $query->selectRaw(
378 116
                $grammar->compileCycleDetectionRecursiveSelect($sql, $cycleDetectionColumn),
379 116
                $bindings
380 116
            );
381 116
382
            $query->whereRaw(
383 116
                $grammar->compileCycleDetectionStopConstraint($cycleDetectionColumn)
384 116
            );
385 116
        } else {
386
            $query->whereRaw("not($sql)", $bindings);
387 116
        }
388 58
    }
389
390 58
    /**
391 58
     * Add join and where clauses to the recursive query for a relationship expression.
392 58
     *
393 58
     * @param \Illuminate\Database\Eloquent\Builder $query
394
     * @param string $pivotTable
395 58
     * @param string $direction
396 58
     * @param string $name
397 58
     * @param array $joinColumns
398
     * @return void
399 58
     */
400
    protected function addRecursiveQueryJoinsAndConstraints(
401
        Builder $query,
402
        string $pivotTable,
403
        string $direction,
404
        string $name,
405
        array $joinColumns
406
    ): void {
407
        if ($direction === 'desc') {
408
            $query->join(
409
                $pivotTable,
410
                $this->getQualifiedLocalKeyName(),
411
                '=',
412
                $this->getQualifiedChildKeyName()
413
            );
414 270
        } else {
415
            $query->join(
416
                $pivotTable,
417
                $this->getQualifiedLocalKeyName(),
418
                '=',
419
                $this->getQualifiedParentKeyName()
420
            );
421 270
        }
422 166
423 166
        $query->join($name, $joinColumns[$direction][0], '=', $joinColumns[$direction][1]);
424 166
425 166
        if (static::$recursiveQueryConstraint) {
426 166
            (static::$recursiveQueryConstraint)($query);
427 166
        }
428
    }
429
}
430