Passed
Push — master ( ad2957...44aae2 )
by Jonas
05:03 queued 02:57
created

HasRecursiveRelationships::getParentKeyName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Staudenmeir\LaravelAdjacencyList\Eloquent;
4
5
use Illuminate\Database\Eloquent\Builder;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Staudenmeir\LaravelAdjacencyList\Eloquent\Builder. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Str;
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\Siblings;
13
use Staudenmeir\LaravelCte\Eloquent\QueriesExpressions;
14
15
trait HasRecursiveRelationships
16
{
17
    use HasOfDescendantsRelationships;
18
    use HasRecursiveRelationshipScopes;
19
    use QueriesExpressions;
20
21
    /** @var null|callable */
22
    public static $recursiveQueryDecoratingFunction;
23
24
    /**
25
     * Allows to make a query with decorating function
26
     *
27
     * @param callable $decoratingFunction
28
     * @param callable $callback
29
     * @return mixed
30
     */
31 5
    public static function withRecursiveQueryDecoratingFunction(callable $decoratingFunction, callable $callback)
32
    {
33 5
        $previous = static::$recursiveQueryDecoratingFunction;
34
35 5
        static::$recursiveQueryDecoratingFunction = $decoratingFunction;
36
37 5
        $result = $callback();
38
39 5
        static::$recursiveQueryDecoratingFunction = $previous;
40
41 5
        return $result;
42
    }
43
44
    /**
45
     * Set function for decorating recursive query
46
     *
47
     * @param callable $function
48
     * @return void
49
     */
50 5
    public function setRecursiveQueryDecoratingFunction(callable $function) {
51 5
        static::$recursiveQueryDecoratingFunction = $function;
52 5
    }
53
54
    /**
55
     * Unset function for decorating recursive query
56
     *
57
     * @return void
58
     */
59 5
    public function unsetRecursiveQueryDecoratingFunction() {
60 5
        static::$recursiveQueryDecoratingFunction = null;
61 5
    }
62
63
    /**
64
     * Get the name of the parent key column.
65
     *
66
     * @return string
67
     */
68 688
    public function getParentKeyName()
69
    {
70 688
        return 'parent_id';
71
    }
72
73
    /**
74
     * Get the qualified parent key column.
75
     *
76
     * @return string
77
     */
78 289
    public function getQualifiedParentKeyName()
79
    {
80 289
        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

80
        return (new static())->/** @scrutinizer ignore-call */ getTable().'.'.$this->getParentKeyName();
Loading history...
81
    }
82
83
    /**
84
     * Get the name of the local key column.
85
     *
86
     * @return string
87
     */
88 653
    public function getLocalKeyName()
89
    {
90 653
        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

90
        return $this->/** @scrutinizer ignore-call */ getKeyName();
Loading history...
91
    }
92
93
    /**
94
     * Get the qualified local key column.
95
     *
96
     * @return string
97
     */
98 326
    public function getQualifiedLocalKeyName()
99
    {
100 326
        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

100
        return $this->/** @scrutinizer ignore-call */ qualifyColumn($this->getLocalKeyName());
Loading history...
101
    }
102
103
    /**
104
     * Get the name of the depth column.
105
     *
106
     * @return string
107
     */
108 603
    public function getDepthName()
109
    {
110 603
        return 'depth';
111
    }
112
113
    /**
114
     * Get the name of the path column.
115
     *
116
     * @return string
117
     */
118 431
    public function getPathName()
119
    {
120 431
        return 'path';
121
    }
122
123
    /**
124
     * Get the path separator.
125
     *
126
     * @return string
127
     */
128 362
    public function getPathSeparator()
129
    {
130 362
        return '.';
131
    }
132
133
    /**
134
     * Get the additional custom paths.
135
     *
136
     * @return array
137
     */
138 282
    public function getCustomPaths()
139
    {
140 282
        return [];
141
    }
142
143
    /**
144
     * Get the name of the common table expression.
145
     *
146
     * @return string
147
     */
148 603
    public function getExpressionName()
149
    {
150 603
        return 'laravel_cte';
151
    }
152
153
    /**
154
     * Get the model's ancestors.
155
     *
156
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
157
     */
158 60
    public function ancestors()
159
    {
160 60
        return $this->newAncestors(
161 60
            (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

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

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

162
            /** @scrutinizer ignore-type */ $this,
Loading history...
163 60
            $this->getQualifiedParentKeyName(),
164 60
            $this->getLocalKeyName(),
165 60
            false
166
        );
167
    }
168
169
    /**
170
     * Get the model's ancestors and itself.
171
     *
172
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
173
     */
174 31
    public function ancestorsAndSelf()
175
    {
176 31
        return $this->newAncestors(
177 31
            (new static())->newQuery(),
178
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...onships::newAncestors(). ( Ignorable by Annotation )

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

178
            /** @scrutinizer ignore-type */ $this,
Loading history...
179 31
            $this->getQualifiedParentKeyName(),
180 31
            $this->getLocalKeyName(),
181 31
            true
182
        );
183
    }
184
185
    /**
186
     * Instantiate a new Ancestors relationship.
187
     *
188
     * @param \Illuminate\Database\Eloquent\Builder $query
189
     * @param \Illuminate\Database\Eloquent\Model $parent
190
     * @param string $foreignKey
191
     * @param string $localKey
192
     * @param bool $andSelf
193
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
194
     */
195 91
    protected function newAncestors(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
196
    {
197 91
        return new Ancestors($query, $parent, $foreignKey, $localKey, $andSelf);
198
    }
199
200
    /**
201
     * Get the model's bloodline.
202
     *
203
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline
204
     */
205 29
    public function bloodline()
206
    {
207 29
        return $this->newBloodline(
208 29
            (new static())->newQuery(),
209
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...onships::newBloodline(). ( Ignorable by Annotation )

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

209
            /** @scrutinizer ignore-type */ $this,
Loading history...
210 29
            $this->getQualifiedParentKeyName(),
211 29
            $this->getLocalKeyName()
212
        );
213
    }
214
215
    /**
216
     * Instantiate a new Bloodline relationship.
217
     *
218
     * @param \Illuminate\Database\Eloquent\Builder $query
219
     * @param \Illuminate\Database\Eloquent\Model $parent
220
     * @param string $foreignKey
221
     * @param string $localKey
222
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline
223
     */
224 29
    protected function newBloodline(Builder $query, Model $parent, $foreignKey, $localKey)
225
    {
226 29
        return new Bloodline($query, $parent, $foreignKey, $localKey);
227
    }
228
229
    /**
230
     * Get the model's children.
231
     *
232
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
233
     */
234 5
    public function children()
235
    {
236 5
        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...sRecursiveRelationships. 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

236
        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...
237
    }
238
239
    /**
240
     * Get the model's children and itself.
241
     *
242
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
243
     */
244 5
    public function childrenAndSelf()
245
    {
246 5
        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

246
        return $this->descendantsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('<=', 1);
Loading history...
247
    }
248
249
    /**
250
     * Get the model's descendants.
251
     *
252
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
253
     */
254 66
    public function descendants()
255
    {
256 66
        return $this->newDescendants(
257 66
            (new static())->newQuery(),
258
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ships::newDescendants(). ( Ignorable by Annotation )

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

258
            /** @scrutinizer ignore-type */ $this,
Loading history...
259 66
            $this->getQualifiedParentKeyName(),
260 66
            $this->getLocalKeyName(),
261 66
            false
262
        );
263
    }
264
265
    /**
266
     * Get the model's descendants and itself.
267
     *
268
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
269
     */
270 36
    public function descendantsAndSelf()
271
    {
272 36
        return $this->newDescendants(
273 36
            (new static())->newQuery(),
274
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ships::newDescendants(). ( Ignorable by Annotation )

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

274
            /** @scrutinizer ignore-type */ $this,
Loading history...
275 36
            $this->getQualifiedParentKeyName(),
276 36
            $this->getLocalKeyName(),
277 36
            true
278
        );
279
    }
280
281
    /**
282
     * Instantiate a new Descendants relationship.
283
     *
284
     * @param \Illuminate\Database\Eloquent\Builder $query
285
     * @param \Illuminate\Database\Eloquent\Model $parent
286
     * @param string $foreignKey
287
     * @param string $localKey
288
     * @param bool $andSelf
289
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
290
     */
291 102
    protected function newDescendants(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
292
    {
293 102
        return new Descendants($query, $parent, $foreignKey, $localKey, $andSelf);
294
    }
295
296
    /**
297
     * Get the model's parent.
298
     *
299
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
300
     */
301 5
    public function parent()
302
    {
303 5
        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...sRecursiveRelationships. 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

303
        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...
304
    }
305
306
    /**
307
     * Get the model's parent and itself.
308
     *
309
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
310
     */
311 5
    public function parentAndSelf()
312
    {
313 5
        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

313
        return $this->ancestorsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('>=', -1);
Loading history...
314
    }
315
316
    /**
317
     * Get the model's root ancestor.
318
     *
319
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor
320
     */
321 25
    public function rootAncestor()
322
    {
323 25
        return $this->newRootAncestor(
324 25
            (new static())->newQuery(),
325
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...hips::newRootAncestor(). ( Ignorable by Annotation )

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

325
            /** @scrutinizer ignore-type */ $this,
Loading history...
326 25
            $this->getQualifiedParentKeyName(),
327 25
            $this->getLocalKeyName()
328
        );
329
    }
330
331
    /**
332
     * Instantiate a new RootAncestor relationship.
333
     *
334
     * @param \Illuminate\Database\Eloquent\Builder $query
335
     * @param \Illuminate\Database\Eloquent\Model $parent
336
     * @param string $foreignKey
337
     * @param string $localKey
338
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor
339
     */
340 25
    protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $localKey)
341
    {
342 25
        return new RootAncestor($query, $parent, $foreignKey, $localKey);
343
    }
344
345
    /**
346
     * Get the model's siblings.
347
     *
348
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
349
     */
350 35
    public function siblings()
351
    {
352 35
        return $this->newSiblings(
353 35
            (new static())->newQuery(),
354
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ionships::newSiblings(). ( Ignorable by Annotation )

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

354
            /** @scrutinizer ignore-type */ $this,
Loading history...
355 35
            $this->getQualifiedParentKeyName(),
356 35
            $this->getParentKeyName(),
357 35
            false
358
        );
359
    }
360
361
    /**
362
     * Get the model's siblings and itself.
363
     *
364
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
365
     */
366 30
    public function siblingsAndSelf()
367
    {
368 30
        return $this->newSiblings(
369 30
            (new static())->newQuery(),
370
            $this,
0 ignored issues
show
Bug introduced by
$this of type Staudenmeir\LaravelAdjac...sRecursiveRelationships is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Staudenmeir\LaravelAdjac...ionships::newSiblings(). ( Ignorable by Annotation )

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

370
            /** @scrutinizer ignore-type */ $this,
Loading history...
371 30
            $this->getQualifiedParentKeyName(),
372 30
            $this->getParentKeyName(),
373 30
            true
374
        );
375
    }
376
377
    /**
378
     * Instantiate a new Siblings relationship.
379
     *
380
     * @param \Illuminate\Database\Eloquent\Builder $query
381
     * @param \Illuminate\Database\Eloquent\Model $parent
382
     * @param string $foreignKey
383
     * @param string $localKey
384
     * @param bool $andSelf
385
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
386
     */
387 65
    protected function newSiblings(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
388
    {
389 65
        return new Siblings($query, $parent, $foreignKey, $localKey, $andSelf);
390
    }
391
392
    /**
393
     * Get the first segment of the model's path.
394
     *
395
     * @return string
396
     */
397 60
    public function getFirstPathSegment()
398
    {
399 60
        $path = $this->attributes[$this->getPathName()];
400
401 60
        return explode($this->getPathSeparator(), $path)[0];
402
    }
403
404
    /**
405
     * Determine whether the model's path is nested.
406
     *
407
     * @return bool
408
     */
409 10
    public function hasNestedPath()
410
    {
411 10
        $path = $this->attributes[$this->getPathName()];
412
413 10
        return Str::contains($path, $this->getPathSeparator());
414
    }
415
416
    /**
417
     * Determine if an attribute is an integer.
418
     *
419
     * @param string $attribute
420
     * @return bool
421
     */
422 90
    public function isIntegerAttribute($attribute)
423
    {
424 90
        $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

424
        /** @scrutinizer ignore-call */ 
425
        $casts = $this->getCasts();
Loading history...
425
426 90
        return isset($casts[$attribute]) && in_array($casts[$attribute], ['int', 'integer']);
427
    }
428
429
    /**
430
     * Create a new Eloquent query builder for the model.
431
     *
432
     * @param \Illuminate\Database\Query\Builder $query
433
     * @return \Illuminate\Database\Eloquent\Builder|static
434
     */
435 688
    public function newEloquentBuilder($query)
436
    {
437 688
        return new \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder($query);
438
    }
439
440
    /**
441
     * Create a new Eloquent Collection instance.
442
     *
443
     * @param array $models
444
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Collection
445
     */
446 683
    public function newCollection(array $models = [])
447
    {
448 683
        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

448
        return new Collection(/** @scrutinizer ignore-type */ $models);
Loading history...
449
    }
450
}
451