Passed
Push — master ( d2cce1...3ba43b )
by Jonas
16:08 queued 16s
created

HasAdjacencyList::rootAncestorOrSelf()   A

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 0
Metric Value
eloc 5
c 0
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 HasRecursiveRelationshipScopes;
20
21
    /**
22
     * Get the name of the parent key column.
23
     *
24
     * @return string
25
     */
26
    public function getParentKeyName()
27
    {
28
        return 'parent_id';
29
    }
30
31
    /**
32 957
     * Get the qualified parent key column.
33
     *
34 957
     * @return string
35
     */
36
    public function getQualifiedParentKeyName()
37
    {
38
        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

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

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

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

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

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

136
            /** @scrutinizer ignore-type */ $this,
Loading history...
137
            $this->getQualifiedParentKeyName(),
138 63
            $this->getLocalKeyName(),
139
            true
140 63
        );
141 63
    }
142 63
143 63
    /**
144 63
     * Instantiate a new Ancestors relationship.
145 63
     *
146 63
     * @param \Illuminate\Database\Eloquent\Builder $query
147
     * @param \Illuminate\Database\Eloquent\Model $parent
148
     * @param string $foreignKey
149
     * @param string $localKey
150
     * @param bool $andSelf
151
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
152
     */
153
    protected function newAncestors(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
154
    {
155
        return new Ancestors($query, $parent, $foreignKey, $localKey, $andSelf);
156
    }
157
158
    /**
159 187
     * Get the model's bloodline.
160
     *
161 187
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<static>
162
     */
163
    public function bloodline()
164
    {
165
        return $this->newBloodline(
166
            (new static())->newQuery(),
167
            $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

167
            /** @scrutinizer ignore-type */ $this,
Loading history...
168
            $this->getQualifiedParentKeyName(),
169 68
            $this->getLocalKeyName()
170
        );
171 68
    }
172 68
173 68
    /**
174 68
     * Instantiate a new Bloodline relationship.
175 68
     *
176 68
     * @param \Illuminate\Database\Eloquent\Builder $query
177
     * @param \Illuminate\Database\Eloquent\Model $parent
178
     * @param string $foreignKey
179
     * @param string $localKey
180
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<static>
181
     */
182
    protected function newBloodline(Builder $query, Model $parent, $foreignKey, $localKey)
183
    {
184
        return new Bloodline($query, $parent, $foreignKey, $localKey);
185
    }
186
187
    /**
188 68
     * Get the model's children.
189
     *
190 68
     * @return \Illuminate\Database\Eloquent\Relations\HasMany<static>
191
     */
192
    public function children()
193
    {
194
        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

194
        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...
195
    }
196
197
    /**
198 6
     * Get the model's children and itself.
199
     *
200 6
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
201
     */
202
    public function childrenAndSelf()
203
    {
204
        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

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

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

232
            /** @scrutinizer ignore-type */ $this,
Loading history...
233
            $this->getQualifiedParentKeyName(),
234 57
            $this->getLocalKeyName(),
235
            true
236 57
        );
237 57
    }
238 57
239 57
    /**
240 57
     * Instantiate a new Descendants relationship.
241 57
     *
242 57
     * @param \Illuminate\Database\Eloquent\Builder $query
243
     * @param \Illuminate\Database\Eloquent\Model $parent
244
     * @param string $foreignKey
245
     * @param string $localKey
246
     * @param bool $andSelf
247
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
248
     */
249
    protected function newDescendants(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
250
    {
251
        return new Descendants($query, $parent, $foreignKey, $localKey, $andSelf);
252
    }
253
254
    /**
255 187
     * Get the model's parent.
256
     *
257 187
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<static, static>
258
     */
259
    public function parent()
260
    {
261
        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

261
        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...
262
    }
263
264
    /**
265 6
     * Get the model's parent and itself.
266
     *
267 6
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
268
     */
269
    public function parentAndSelf()
270
    {
271
        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

271
        return $this->ancestorsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('>=', -1);
Loading history...
272
    }
273
274
    /**
275 6
     * Get the model's root ancestor.
276
     *
277 6
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<static>
278
     */
279
    public function rootAncestor()
280
    {
281
        return $this->newRootAncestor(
282
            (new static())->newQuery(),
283
            $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

283
            /** @scrutinizer ignore-type */ $this,
Loading history...
284
            $this->getQualifiedParentKeyName(),
285 28
            $this->getLocalKeyName()
286
        );
287 28
    }
288 28
289 28
    /**
290 28
     * Instantiate a new RootAncestor relationship.
291 28
     *
292 28
     * @param \Illuminate\Database\Eloquent\Builder $query
293
     * @param \Illuminate\Database\Eloquent\Model $parent
294
     * @param string $foreignKey
295
     * @param string $localKey
296
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<static>
297
     */
298
    protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $localKey)
299
    {
300
        return new RootAncestor($query, $parent, $foreignKey, $localKey);
301
    }
302
303
    /**
304 28
     * Get the model's root ancestor or self.
305
     *
306 28
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<static>
307
     */
308
    public function rootAncestorOrSelf(): RootAncestorOrSelf
309
    {
310
        return $this->newRootAncestorOrSelf(
311
            (new static())->newQuery(),
312
            $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

312
            /** @scrutinizer ignore-type */ $this,
Loading history...
313
            $this->getQualifiedParentKeyName(),
314 41
            $this->getLocalKeyName()
315
        );
316 41
    }
317 41
318 41
    /**
319 41
     * Instantiate a new RootAncestorOrSelf relationship.
320 41
     *
321 41
     * @param \Illuminate\Database\Eloquent\Builder $query
322 41
     * @param \Illuminate\Database\Eloquent\Model $parent
323
     * @param string $foreignKey
324
     * @param string $localKey
325
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<static>
326
     */
327
    protected function newRootAncestorOrSelf(Builder $query, Model $parent, string $foreignKey, string $localKey): RootAncestorOrSelf
328
    {
329
        return new RootAncestorOrSelf($query, $parent, $foreignKey, $localKey);
330 35
    }
331
332 35
    /**
333 35
     * Get the model's siblings.
334 35
     *
335 35
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
336 35
     */
337 35
    public function siblings()
338 35
    {
339
        return $this->newSiblings(
340
            (new static())->newQuery(),
341
            $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

341
            /** @scrutinizer ignore-type */ $this,
Loading history...
342
            $this->getQualifiedParentKeyName(),
343
            $this->getParentKeyName(),
344
            false
345
        );
346
    }
347
348
    /**
349
     * Get the model's siblings and itself.
350
     *
351 76
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
352
     */
353 76
    public function siblingsAndSelf()
354
    {
355
        return $this->newSiblings(
356
            (new static())->newQuery(),
357
            $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

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

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

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