HasGraphAdjacencyList::newDescendants()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 19
rs 9.9666
ccs 5
cts 5
cp 1
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 Staudenmeir\LaravelAdjacencyList\Eloquent\Graph\Collection;
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
    use HasQueryConstraints;
16
17
    /**
18
     * Get the name of the pivot table.
19
     *
20
     * @return string
21
     */
22
    abstract public function getPivotTableName(): string;
23
24
    /**
25
     * Get the name of the parent key column.
26
     *
27
     * @return string
28
     */
29
    public function getParentKeyName(): string
30
    {
31
        return 'parent_id';
32
    }
33
34 248
    /**
35
     * Get the qualified parent key column.
36 248
     *
37
     * @return string
38
     */
39
    public function getQualifiedParentKeyName()
40
    {
41
        return $this->getPivotTableName() . '.' . $this->getParentKeyName();
42
    }
43
44 270
    /**
45
     * Get the name of the child key column.
46 270
     *
47
     * @return string
48
     */
49
    public function getChildKeyName(): string
50
    {
51
        return 'child_id';
52
    }
53
54 248
    /**
55
     * Get the qualified child key column.
56 248
     *
57
     * @return string
58
     */
59
    public function getQualifiedChildKeyName()
60
    {
61
        return $this->getPivotTableName() . '.' . $this->getChildKeyName();
62
    }
63
64 270
    /**
65
     * Get the name of the local key column.
66 270
     *
67
     * @return string
68
     */
69
    public function getLocalKeyName(): string
70
    {
71
        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

71
        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...
72
    }
73
74 248
    /**
75
     * Get the qualified local key column.
76 248
     *
77
     * @return string
78
     */
79
    public function getQualifiedLocalKeyName(): string
80
    {
81
        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

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

184
            (new static())->/** @scrutinizer ignore-call */ newQuery(),
Loading history...
185
            $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

185
            /** @scrutinizer ignore-type */ $this,
Loading history...
186 87
            $this->getPivotTableName(),
187
            $this->getParentKeyName(),
188 87
            $this->getChildKeyName(),
189 87
            $this->getLocalKeyName(),
190 87
            $this->getLocalKeyName(),
191 87
            false
192 87
        );
193 87
    }
194 87
195 87
    /**
196 87
     * Get the model's ancestors and itself.
197 87
     *
198
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Ancestors<static>
199
     */
200
    public function ancestorsAndSelf(): Ancestors
201
    {
202
        return $this->newAncestors(
203
            (new static())->newQuery(),
204
            $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

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

256
        return $this->/** @scrutinizer ignore-call */ belongsToMany(
Loading history...
257
            static::class,
258
            $this->getPivotTableName(),
259 5
            $this->getParentKeyName(),
260
            $this->getChildKeyName(),
261 5
            $this->getLocalKeyName(),
262 5
            $this->getLocalKeyName()
263 5
        )->withPivot(
264 5
            $this->getPivotColumns()
265 5
        );
266 5
    }
267 5
268 5
    /**
269 5
     * Get the model's children and itself.
270 5
     *
271
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants<static>
272
     */
273
    public function childrenAndSelf(): Descendants
274
    {
275
        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

275
        return $this->descendantsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('<=', 1);
Loading history...
276
    }
277
278 4
    /**
279
     * Get the model's descendants.
280 4
     *
281
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants<static>
282
     */
283
    public function descendants(): Descendants
284
    {
285
        return $this->newDescendants(
286
            (new static())->newQuery(),
287
            $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

287
            /** @scrutinizer ignore-type */ $this,
Loading history...
288 111
            $this->getPivotTableName(),
289
            $this->getParentKeyName(),
290 111
            $this->getChildKeyName(),
291 111
            $this->getLocalKeyName(),
292 111
            $this->getLocalKeyName(),
293 111
            false
294 111
        );
295 111
    }
296 111
297 111
    /**
298 111
     * Get the model's descendants and itself.
299 111
     *
300
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Graph\Descendants<static>
301
     */
302
    public function descendantsAndSelf(): Descendants
303
    {
304
        return $this->newDescendants(
305
            (new static())->newQuery(),
306
            $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

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

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

403
        /** @scrutinizer ignore-call */ 
404
        $casts = $this->getCasts();
Loading history...
404
405 68
        return isset($casts[$attribute]) && in_array($casts[$attribute], ['int', 'integer']);
406 68
    }
407
408 68
    /**
409
     * Create a new Eloquent query builder for the model.
410 68
     *
411
     * @param \Illuminate\Database\Query\Builder $query
412
     * @return \Illuminate\Database\Eloquent\Builder|static
413
     */
414
    public function newEloquentBuilder($query)
415
    {
416
        return new \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder($query);
417
    }
418
419 280
    /**
420
     * Create a new Eloquent Collection instance.
421 280
     *
422
     * @param array $models
423
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Graph\Collection
424
     */
425
    public function newCollection(array $models = [])
426
    {
427
        return new Collection($models);
0 ignored issues
show
Bug introduced by
$models of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Staudenmeir\LaravelAdjac...llection::__construct(). ( Ignorable by Annotation )

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

427
        return new Collection(/** @scrutinizer ignore-type */ $models);
Loading history...
428
    }
429
430 5
    /**
431
     * Execute a query with a maximum depth constraint for the recursive query.
432 5
     *
433
     * @param int $maxDepth
434
     * @param callable $query
435
     * @return mixed
436
     */
437
    public static function withMaxDepth(int $maxDepth, callable $query): mixed
438
    {
439
        $operator = $maxDepth > 0 ? '<' : '>';
440 5
441
        return static::withRecursiveQueryConstraint(
442 5
            fn (Builder $query) => $query->whereDepth($operator, $maxDepth),
443
            $query
444
        );
445
    }
446
}
447