Passed
Branch master (407c50)
by Jonas
02:53
created

HasGraphAdjacencyList::newDescendants()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 19
ccs 2
cts 2
cp 1
rs 9.9666
cc 1
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
8
use Illuminate\Support\Str;
9
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Ancestors;
10
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants;
11
12
trait HasGraphAdjacencyList
13
{
14
    use HasGraphRelationshipScopes;
15
16
    /**
17
     * The additional constraint for the recursive query.
18
     *
19
     * @var callable|null
20
     */
21
    public static $recursiveQueryConstraint;
22
23
    /**
24
     * Get the name of the pivot table.
25
     *
26
     * @return string
27
     */
28
    abstract public function getPivotTableName(): string;
29
30
    /**
31
     * Get the name of the parent key column.
32
     *
33
     * @return string
34
     */
35 214
    public function getParentKeyName(): string
36
    {
37 214
        return 'parent_id';
38
    }
39
40
    /**
41
     * Get the qualified parent key column.
42
     *
43
     * @return string
44
     */
45 206
    public function getQualifiedParentKeyName()
46
    {
47 206
        return $this->getPivotTableName() . '.' . $this->getParentKeyName();
48
    }
49
50
    /**
51
     * Get the name of the child key column.
52
     *
53
     * @return string
54
     */
55 214
    public function getChildKeyName(): string
56
    {
57 214
        return 'child_id';
58
    }
59
60
    /**
61
     * Get the qualified child key column.
62
     *
63
     * @return string
64
     */
65 206
    public function getQualifiedChildKeyName()
66
    {
67 206
        return $this->getPivotTableName() . '.' . $this->getChildKeyName();
68
    }
69
70
    /**
71
     * Get the name of the local key column.
72
     *
73
     * @return string
74
     */
75 214
    public function getLocalKeyName(): string
76
    {
77 214
        return $this->getKeyName();
0 ignored issues
show
Bug introduced by
The method getKeyName() does not exist on Staudenmeir\LaravelAdjac...s\HasGraphAdjacencyList. Did you maybe mean getChildKeyName()? ( Ignorable by Annotation )

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

77
        return $this->/** @scrutinizer ignore-call */ getKeyName();

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...
78
    }
79
80
    /**
81
     * Get the qualified local key column.
82
     *
83
     * @return string
84
     */
85 206
    public function getQualifiedLocalKeyName(): string
86
    {
87 206
        return $this->qualifyColumn(
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

87
        return $this->/** @scrutinizer ignore-call */ qualifyColumn(
Loading history...
88 206
            $this->getLocalKeyName()
89
        );
90
    }
91
92
    /**
93
     * Get the name of the depth column.
94
     *
95
     * @return string
96
     */
97 206
    public function getDepthName(): string
98
    {
99 206
        return 'depth';
100
    }
101
102
    /**
103
     * Get the name of the path column.
104
     *
105
     * @return string
106
     */
107 208
    public function getPathName(): string
108
    {
109 208
        return 'path';
110
    }
111
112
    /**
113
     * Get the path separator.
114
     *
115
     * @return string
116
     */
117 206
    public function getPathSeparator(): string
118
    {
119 206
        return '.';
120
    }
121
122
    /**
123
     * Get the additional custom paths.
124
     *
125
     * @return array
126
     */
127 206
    public function getCustomPaths(): array
128
    {
129 206
        return [];
130
    }
131
132
    /**
133
     * Get the pivot table columns to retrieve.
134
     *
135
     * @return array
136
     */
137 206
    public function getPivotColumns(): array
138
    {
139 206
        return [];
140
    }
141
142
    /**
143
     * Get the name of the common table expression.
144
     *
145
     * @return string
146
     */
147 206
    public function getExpressionName(): string
148
    {
149 206
        return 'laravel_cte';
150
    }
151
152
    /**
153
     * Whether to enable cycle detection.
154
     *
155
     * @return bool
156
     */
157 130
    public function enableCycleDetection(): bool
158
    {
159 130
        return false;
160
    }
161
162
    /**
163
     * Whether to include the first row of the cycle in the query results.
164
     *
165
     * @return bool
166
     */
167 38
    public function includeCycleStart(): bool
168
    {
169 38
        return false;
170
    }
171
172
    /**
173
     * Get the name of the cycle detection column.
174
     *
175
     * @return string
176
     */
177 38
    public function getCycleDetectionColumnName(): string
178
    {
179 38
        return 'is_cycle';
180
    }
181
182
    /**
183
     * Get the model's ancestors.
184
     *
185
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Ancestors
186
     */
187 58
    public function ancestors(): Ancestors
188
    {
189 58
        return $this->newAncestors(
190 58
            (new static())->newQuery(),
0 ignored issues
show
Bug introduced by
It seems like newQuery() 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

190
            (new static())->/** @scrutinizer ignore-call */ newQuery(),
Loading history...
191
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...s\HasGraphAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ncyList::newAncestors(). ( Ignorable by Annotation )

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

191
            /** @scrutinizer ignore-type */ $this,
Loading history...
192 58
            $this->getPivotTableName(),
193 58
            $this->getParentKeyName(),
194 58
            $this->getChildKeyName(),
195 58
            $this->getLocalKeyName(),
196 58
            $this->getLocalKeyName(),
197
            false
198
        );
199
    }
200
201
    /**
202
     * Get the model's ancestors and itself.
203
     *
204
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Ancestors
205
     */
206 41
    public function ancestorsAndSelf(): Ancestors
207
    {
208 41
        return $this->newAncestors(
209 41
            (new static())->newQuery(),
210
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...s\HasGraphAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ncyList::newAncestors(). ( Ignorable by Annotation )

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

210
            /** @scrutinizer ignore-type */ $this,
Loading history...
211 41
            $this->getPivotTableName(),
212 41
            $this->getParentKeyName(),
213 41
            $this->getChildKeyName(),
214 41
            $this->getLocalKeyName(),
215 41
            $this->getLocalKeyName(),
216
            true
217
        );
218
    }
219
220
    /**
221
     * Instantiate a new Ancestors relationship.
222
     *
223
     * @param \Illuminate\Database\Eloquent\Builder $query
224
     * @param \Illuminate\Database\Eloquent\Model $parent
225
     * @param string $table
226
     * @param string $foreignPivotKey
227
     * @param string $relatedPivotKey
228
     * @param string $parentKey
229
     * @param string $relatedKey
230
     * @param bool $andSelf
231
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Ancestors
232
     */
233 99
    protected function newAncestors(
234
        Builder $query,
235
        Model $parent,
236
        string $table,
237
        string $foreignPivotKey,
238
        string $relatedPivotKey,
239
        string $parentKey,
240
        string $relatedKey,
241
        bool $andSelf
242
    ): Ancestors {
243 99
        return new Ancestors(
244
            $query,
245
            $parent,
246
            $table,
247
            $foreignPivotKey,
248
            $relatedPivotKey,
249
            $parentKey,
250
            $relatedKey,
251
            $andSelf
252
        );
253
    }
254
255
    /**
256
     * Get the model's children.
257
     *
258
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
259
     */
260 4
    public function children(): BelongsToMany
261
    {
262 4
        return $this->belongsToMany(
0 ignored issues
show
Bug introduced by
It seems like belongsToMany() 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

262
        return $this->/** @scrutinizer ignore-call */ belongsToMany(
Loading history...
263
            static::class,
264 4
            $this->getPivotTableName(),
265 4
            $this->getParentKeyName(),
266 4
            $this->getChildKeyName(),
267 4
            $this->getLocalKeyName(),
268 4
            $this->getLocalKeyName()
269
        );
270
    }
271
272
    /**
273
     * Get the model's children and itself.
274
     *
275
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants
276
     */
277 4
    public function childrenAndSelf(): Descendants
278
    {
279 4
        return $this->descendantsAndSelf()->whereDepth('<=', 1);
0 ignored issues
show
Bug introduced by
The method whereDepth() does not exist on Staudenmeir\LaravelAdjac...tions\Graph\Descendants. 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

279
        return $this->descendantsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('<=', 1);
Loading history...
280
    }
281
282
    /**
283
     * Get the model's descendants.
284
     *
285
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants
286
     */
287 76
    public function descendants(): Descendants
288
    {
289 76
        return $this->newDescendants(
290 76
            (new static())->newQuery(),
291
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...s\HasGraphAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...yList::newDescendants(). ( Ignorable by Annotation )

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

291
            /** @scrutinizer ignore-type */ $this,
Loading history...
292 76
            $this->getPivotTableName(),
293 76
            $this->getParentKeyName(),
294 76
            $this->getChildKeyName(),
295 76
            $this->getLocalKeyName(),
296 76
            $this->getLocalKeyName(),
297
            false
298
        );
299
    }
300
301
    /**
302
     * Get the model's descendants and itself.
303
     *
304
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants
305
     */
306 47
    public function descendantsAndSelf(): Descendants
307
    {
308 47
        return $this->newDescendants(
309 47
            (new static())->newQuery(),
310
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...s\HasGraphAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...yList::newDescendants(). ( Ignorable by Annotation )

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

310
            /** @scrutinizer ignore-type */ $this,
Loading history...
311 47
            $this->getPivotTableName(),
312 47
            $this->getParentKeyName(),
313 47
            $this->getChildKeyName(),
314 47
            $this->getLocalKeyName(),
315 47
            $this->getLocalKeyName(),
316
            true
317
        );
318
    }
319
320
    /**
321
     * Instantiate a new Descendants relationship.
322
     *
323
     * @param \Illuminate\Database\Eloquent\Builder $query
324
     * @param \Illuminate\Database\Eloquent\Model $parent
325
     * @param string $table
326
     * @param string $foreignPivotKey
327
     * @param string $relatedPivotKey
328
     * @param string $parentKey
329
     * @param string $relatedKey
330
     * @param bool $andSelf
331
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants
332
     */
333 123
    protected function newDescendants(
334
        Builder $query,
335
        Model $parent,
336
        string $table,
337
        string $foreignPivotKey,
338
        string $relatedPivotKey,
339
        string $parentKey,
340
        string $relatedKey,
341
        bool $andSelf
342
    ): Descendants {
343 123
        return new Descendants(
344
            $query,
345
            $parent,
346
            $table,
347
            $foreignPivotKey,
348
            $relatedPivotKey,
349
            $parentKey,
350
            $relatedKey,
351
            $andSelf
352
        );
353
    }
354
355
    /**
356
     * Get the model's parents.
357
     *
358
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
359
     */
360 4
    public function parents(): BelongsToMany
361
    {
362 4
        return $this->belongsToMany(
363
            static::class,
364 4
            $this->getPivotTableName(),
365 4
            $this->getChildKeyName(),
366 4
            $this->getParentKeyName(),
367 4
            $this->getLocalKeyName(),
368 4
            $this->getLocalKeyName()
369
        );
370
    }
371
372
    /**
373
     * Get the model's parents and itself.
374
     *
375
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Ancestors
376
     */
377 4
    public function parentsAndSelf(): Ancestors
378
    {
379 4
        return $this->ancestorsAndSelf()->whereDepth('>=', -1);
0 ignored issues
show
Bug introduced by
The method whereDepth() does not exist on Staudenmeir\LaravelAdjac...lations\Graph\Ancestors. 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

379
        return $this->ancestorsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('>=', -1);
Loading history...
380
    }
381
382
    /**
383
     * Get the first segment of the model's path.
384
     *
385
     * @return string
386
     */
387 64
    public function getFirstPathSegment(): string
388
    {
389 64
        $path = $this->attributes[$this->getPathName()];
390
391 64
        return explode($this->getPathSeparator(), $path)[0];
392
    }
393
394
    /**
395
     * Determine if an attribute is an integer.
396
     *
397
     * @param string $attribute
398
     * @return bool
399
     */
400 58
    public function isIntegerAttribute(string $attribute): bool
401
    {
402 58
        $segments = explode('.', $attribute);
403 58
        $attribute = end($segments);
404
405 58
        $casts = $this->getCasts();
0 ignored issues
show
Bug introduced by
It seems like getCasts() 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

405
        /** @scrutinizer ignore-call */ 
406
        $casts = $this->getCasts();
Loading history...
406
407 58
        return isset($casts[$attribute]) && in_array($casts[$attribute], ['int', 'integer']);
408
    }
409
410
    /**
411
     * Create a new Eloquent query builder for the model.
412
     *
413
     * @param \Illuminate\Database\Query\Builder $query
414
     * @return \Illuminate\Database\Eloquent\Builder|static
415
     */
416 214
    public function newEloquentBuilder($query)
417
    {
418 214
        return new \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder($query);
419
    }
420
421
    /**
422
     * Set an additional constraint for the recursive query.
423
     *
424
     * @param callable $constraint
425
     * @return void
426
     */
427 4
    public static function setRecursiveQueryConstraint(callable $constraint): void
428
    {
429 4
        static::$recursiveQueryConstraint = $constraint;
430
    }
431
432
    /**
433
     * Unset the additional constraint for the recursive query.
434
     *
435
     * @return void
436
     */
437 4
    public static function unsetRecursiveQueryConstraint(): void
438
    {
439 4
        static::$recursiveQueryConstraint = null;
440
    }
441
442
    /**
443
     * Execute a query with an additional constraint for the recursive query.
444
     *
445
     * @param callable $constraint
446
     * @param callable $query
447
     * @return mixed
448
     */
449 4
    public static function withRecursiveQueryConstraint(callable $constraint, callable $query): mixed
450
    {
451 4
        $previous = static::$recursiveQueryConstraint;
452
453 4
        static::$recursiveQueryConstraint = $constraint;
454
455 4
        $result = $query();
456
457 4
        static::$recursiveQueryConstraint = $previous;
458
459 4
        return $result;
460
    }
461
}
462