HasAdjacencyList::bloodline()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 7
rs 10
ccs 1
cts 1
cp 1
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Staudenmeir\LaravelAdjacencyList\Eloquent\Collection;
8
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors;
9
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline;
10
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants;
11
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor;
12
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf;
13
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings;
14
15
trait HasAdjacencyList
16
{
17
    use HasOfDescendantsRelationships;
18
    use HasQueryConstraints;
19
    use HasRecursiveRelationshipHelpers;
20
    use HasRecursiveRelationshipScopes;
21
22
    /**
23
     * Get the name of the parent key column.
24
     *
25
     * @return string
26
     */
27
    public function getParentKeyName()
28
    {
29
        return 'parent_id';
30
    }
31
32 957
    /**
33
     * Get the qualified parent key column.
34 957
     *
35
     * @return string
36
     */
37
    public function getQualifiedParentKeyName()
38
    {
39
        return (new static())->getTable().'.'.$this->getParentKeyName();
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

39
        return (new static())->/** @scrutinizer ignore-call */ getTable().'.'.$this->getParentKeyName();
Loading history...
40
    }
41
42 508
    /**
43
     * Get the name of the local key column.
44 508
     *
45
     * @return string
46
     */
47
    public function getLocalKeyName()
48
    {
49
        return $this->getKeyName();
0 ignored issues
show
Bug introduced by
It seems like getKeyName() 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

49
        return $this->/** @scrutinizer ignore-call */ getKeyName();
Loading history...
50
    }
51
52 915
    /**
53
     * Get the qualified local key column.
54 915
     *
55
     * @return string
56
     */
57
    public function getQualifiedLocalKeyName()
58
    {
59
        return $this->qualifyColumn($this->getLocalKeyName());
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

59
        return $this->/** @scrutinizer ignore-call */ qualifyColumn($this->getLocalKeyName());
Loading history...
60
    }
61
62 571
    /**
63
     * Get the name of the depth column.
64 571
     *
65
     * @return string
66
     */
67
    public function getDepthName()
68
    {
69
        return 'depth';
70
    }
71
72 849
    /**
73
     * Get the name of the path column.
74 849
     *
75
     * @return string
76
     */
77
    public function getPathName()
78
    {
79
        return 'path';
80
    }
81
82 678
    /**
83
     * Get the path separator.
84 678
     *
85
     * @return string
86
     */
87
    public function getPathSeparator()
88
    {
89
        return '.';
90
    }
91
92 608
    /**
93
     * Get the additional custom paths.
94 608
     *
95
     * @return array
96
     */
97
    public function getCustomPaths()
98
    {
99
        return [];
100
    }
101
102 523
    /**
103
     * Get the name of the common table expression.
104 523
     *
105
     * @return string
106
     */
107
    public function getExpressionName()
108
    {
109
        return 'laravel_cte';
110
    }
111
112 849
    /**
113
     * Get the model's ancestors.
114 849
     *
115
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
116
     */
117
    public function ancestors()
118
    {
119
        return $this->newAncestors(
120
            (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

120
            (new static())->/** @scrutinizer ignore-call */ newQuery(),
Loading history...
121
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList 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

121
            /** @scrutinizer ignore-type */ $this,
Loading history...
122 124
            $this->getQualifiedParentKeyName(),
123
            $this->getLocalKeyName(),
124 124
            false
125 124
        );
126 124
    }
127 124
128 124
    /**
129 124
     * Get the model's ancestors and itself.
130 124
     *
131
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
132
     */
133
    public function ancestorsAndSelf()
134
    {
135
        return $this->newAncestors(
136
            (new static())->newQuery(),
137
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList 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

137
            /** @scrutinizer ignore-type */ $this,
Loading history...
138 63
            $this->getQualifiedParentKeyName(),
139
            $this->getLocalKeyName(),
140 63
            true
141 63
        );
142 63
    }
143 63
144 63
    /**
145 63
     * Instantiate a new Ancestors relationship.
146 63
     *
147
     * @param \Illuminate\Database\Eloquent\Builder $query
148
     * @param \Illuminate\Database\Eloquent\Model $parent
149
     * @param string $foreignKey
150
     * @param string $localKey
151
     * @param bool $andSelf
152
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
153
     */
154
    protected function newAncestors(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
155
    {
156
        return new Ancestors($query, $parent, $foreignKey, $localKey, $andSelf);
157
    }
158
159 187
    /**
160
     * Get the model's bloodline.
161 187
     *
162
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<static>
163
     */
164
    public function bloodline()
165
    {
166
        return $this->newBloodline(
167
            (new static())->newQuery(),
168
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ncyList::newBloodline(). ( Ignorable by Annotation )

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

168
            /** @scrutinizer ignore-type */ $this,
Loading history...
169 68
            $this->getQualifiedParentKeyName(),
170
            $this->getLocalKeyName()
171 68
        );
172 68
    }
173 68
174 68
    /**
175 68
     * Instantiate a new Bloodline relationship.
176 68
     *
177
     * @param \Illuminate\Database\Eloquent\Builder $query
178
     * @param \Illuminate\Database\Eloquent\Model $parent
179
     * @param string $foreignKey
180
     * @param string $localKey
181
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<static>
182
     */
183
    protected function newBloodline(Builder $query, Model $parent, $foreignKey, $localKey)
184
    {
185
        return new Bloodline($query, $parent, $foreignKey, $localKey);
186
    }
187
188 68
    /**
189
     * Get the model's children.
190 68
     *
191
     * @return \Illuminate\Database\Eloquent\Relations\HasMany<static>
192
     */
193
    public function children()
194
    {
195
        return $this->hasMany(static::class, $this->getParentKeyName(), $this->getLocalKeyName());
0 ignored issues
show
Bug introduced by
The method hasMany() does not exist on Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList. Did you maybe mean hasManyOfDescendantsAndSelf()? ( Ignorable by Annotation )

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

195
        return $this->/** @scrutinizer ignore-call */ hasMany(static::class, $this->getParentKeyName(), $this->getLocalKeyName());

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...
196
    }
197
198 6
    /**
199
     * Get the model's children and itself.
200 6
     *
201
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
202
     */
203
    public function childrenAndSelf()
204
    {
205
        return $this->descendantsAndSelf()->whereDepth('<=', 1);
0 ignored issues
show
Bug introduced by
The method whereDepth() does not exist on Staudenmeir\LaravelAdjac...t\Relations\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

205
        return $this->descendantsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('<=', 1);
Loading history...
206
    }
207
208 6
    /**
209
     * Get the model's descendants.
210 6
     *
211
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
212
     */
213
    public function descendants()
214
    {
215
        return $this->newDescendants(
216
            (new static())->newQuery(),
217
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList 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

217
            /** @scrutinizer ignore-type */ $this,
Loading history...
218 130
            $this->getQualifiedParentKeyName(),
219
            $this->getLocalKeyName(),
220 130
            false
221 130
        );
222 130
    }
223 130
224 130
    /**
225 130
     * Get the model's descendants and itself.
226 130
     *
227
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
228
     */
229
    public function descendantsAndSelf()
230
    {
231
        return $this->newDescendants(
232
            (new static())->newQuery(),
233
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList 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

233
            /** @scrutinizer ignore-type */ $this,
Loading history...
234 57
            $this->getQualifiedParentKeyName(),
235
            $this->getLocalKeyName(),
236 57
            true
237 57
        );
238 57
    }
239 57
240 57
    /**
241 57
     * Instantiate a new Descendants relationship.
242 57
     *
243
     * @param \Illuminate\Database\Eloquent\Builder $query
244
     * @param \Illuminate\Database\Eloquent\Model $parent
245
     * @param string $foreignKey
246
     * @param string $localKey
247
     * @param bool $andSelf
248
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
249
     */
250
    protected function newDescendants(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
251
    {
252
        return new Descendants($query, $parent, $foreignKey, $localKey, $andSelf);
253
    }
254
255 187
    /**
256
     * Get the model's parent.
257 187
     *
258
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<static, static>
259
     */
260
    public function parent()
261
    {
262
        return $this->belongsTo(static::class, $this->getParentKeyName(), $this->getLocalKeyName());
0 ignored issues
show
Bug introduced by
The method belongsTo() does not exist on Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList. Did you maybe mean belongsToManyOfDescendantsAndSelf()? ( 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 */ belongsTo(static::class, $this->getParentKeyName(), $this->getLocalKeyName());

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...
263
    }
264
265 6
    /**
266
     * Get the model's parent and itself.
267 6
     *
268
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
269
     */
270
    public function parentAndSelf()
271
    {
272
        return $this->ancestorsAndSelf()->whereDepth('>=', -1);
0 ignored issues
show
Bug introduced by
The method whereDepth() does not exist on Staudenmeir\LaravelAdjac...ent\Relations\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

272
        return $this->ancestorsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('>=', -1);
Loading history...
273
    }
274
275 6
    /**
276
     * Get the model's root ancestor.
277 6
     *
278
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<static>
279
     */
280
    public function rootAncestor()
281
    {
282
        return $this->newRootAncestor(
283
            (new static())->newQuery(),
284
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...List::newRootAncestor(). ( Ignorable by Annotation )

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

284
            /** @scrutinizer ignore-type */ $this,
Loading history...
285 28
            $this->getQualifiedParentKeyName(),
286
            $this->getLocalKeyName()
287 28
        );
288 28
    }
289 28
290 28
    /**
291 28
     * Instantiate a new RootAncestor relationship.
292 28
     *
293
     * @param \Illuminate\Database\Eloquent\Builder $query
294
     * @param \Illuminate\Database\Eloquent\Model $parent
295
     * @param string $foreignKey
296
     * @param string $localKey
297
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<static>
298
     */
299
    protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $localKey)
300
    {
301
        return new RootAncestor($query, $parent, $foreignKey, $localKey);
302
    }
303
304 28
    /**
305
     * Get the model's root ancestor or self.
306 28
     *
307
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<static>
308
     */
309
    public function rootAncestorOrSelf(): RootAncestorOrSelf
310
    {
311
        return $this->newRootAncestorOrSelf(
312
            (new static())->newQuery(),
313
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...newRootAncestorOrSelf(). ( Ignorable by Annotation )

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

313
            /** @scrutinizer ignore-type */ $this,
Loading history...
314 41
            $this->getQualifiedParentKeyName(),
315
            $this->getLocalKeyName()
316 41
        );
317 41
    }
318 41
319 41
    /**
320 41
     * Instantiate a new RootAncestorOrSelf relationship.
321 41
     *
322 41
     * @param \Illuminate\Database\Eloquent\Builder $query
323
     * @param \Illuminate\Database\Eloquent\Model $parent
324
     * @param string $foreignKey
325
     * @param string $localKey
326
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<static>
327
     */
328
    protected function newRootAncestorOrSelf(Builder $query, Model $parent, string $foreignKey, string $localKey): RootAncestorOrSelf
329
    {
330 35
        return new RootAncestorOrSelf($query, $parent, $foreignKey, $localKey);
331
    }
332 35
333 35
    /**
334 35
     * Get the model's siblings.
335 35
     *
336 35
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
337 35
     */
338 35
    public function siblings()
339
    {
340
        return $this->newSiblings(
341
            (new static())->newQuery(),
342
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...encyList::newSiblings(). ( Ignorable by Annotation )

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

342
            /** @scrutinizer ignore-type */ $this,
Loading history...
343
            $this->getQualifiedParentKeyName(),
344
            $this->getParentKeyName(),
345
            false
346
        );
347
    }
348
349
    /**
350
     * Get the model's siblings and itself.
351 76
     *
352
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
353 76
     */
354
    public function siblingsAndSelf()
355
    {
356
        return $this->newSiblings(
357
            (new static())->newQuery(),
358
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...Traits\HasAdjacencyList is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...encyList::newSiblings(). ( Ignorable by Annotation )

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

358
            /** @scrutinizer ignore-type */ $this,
Loading history...
359
            $this->getQualifiedParentKeyName(),
360
            $this->getParentKeyName(),
361 72
            true
362
        );
363 72
    }
364
365 72
    /**
366
     * Instantiate a new Siblings relationship.
367
     *
368
     * @param \Illuminate\Database\Eloquent\Builder $query
369
     * @param \Illuminate\Database\Eloquent\Model $parent
370
     * @param string $foreignKey
371
     * @param string $localKey
372
     * @param bool $andSelf
373 12
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
374
     */
375 12
    protected function newSiblings(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
376
    {
377 12
        return new Siblings($query, $parent, $foreignKey, $localKey, $andSelf);
378
    }
379
380
    /**
381
     * Get the first segment of the model's path.
382
     *
383
     * @return string
384
     */
385
    public function getFirstPathSegment()
386 135
    {
387
        $path = $this->attributes[$this->getPathName()];
388 135
389 135
        return explode($this->getPathSeparator(), $path)[0];
390
    }
391 135
392
    /**
393 135
     * Determine whether the model's path is nested.
394
     *
395
     * @return bool
396
     */
397
    public function hasNestedPath()
398
    {
399
        $path = $this->attributes[$this->getPathName()];
400
401
        return str_contains($path, $this->getPathSeparator());
402 957
    }
403
404 957
    /**
405
     * Determine if an attribute is an integer.
406
     *
407
     * @param string $attribute
408
     * @return bool
409
     */
410
    public function isIntegerAttribute($attribute)
411
    {
412
        $segments = explode('.', $attribute);
413 916
        $attribute = end($segments);
414
415 916
        $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

415
        /** @scrutinizer ignore-call */ 
416
        $casts = $this->getCasts();
Loading history...
416
417
        return isset($casts[$attribute]) && in_array($casts[$attribute], ['int', 'integer']);
418
    }
419
420
    /**
421
     * Create a new Eloquent query builder for the model.
422
     *
423
     * @param \Illuminate\Database\Query\Builder $query
424 6
     * @return \Illuminate\Database\Eloquent\Builder|static
425
     */
426 6
    public function newEloquentBuilder($query)
427
    {
428
        return new \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder($query);
429
    }
430
431
    /**
432
     * Create a new Eloquent Collection instance.
433
     *
434 6
     * @param array $models
435
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Collection
436 6
     */
437
    public function newCollection(array $models = [])
438
    {
439
        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

439
        return new Collection(/** @scrutinizer ignore-type */ $models);
Loading history...
440
    }
441
442
    /**
443
     * Execute a query with a maximum depth constraint for the recursive query.
444
     *
445
     * @param int $maxDepth
446 18
     * @param callable $query
447
     * @return mixed
448 18
     */
449
    public static function withMaxDepth(int $maxDepth, callable $query): mixed
450 18
    {
451
        $operator = $maxDepth > 0 ? '<' : '>';
452 18
453
        return static::withRecursiveQueryConstraint(
454 18
            fn (Builder $query) => $query->whereDepth($operator, $maxDepth),
455
            $query
456 18
        );
457
    }
458
}
459