Passed
Push — master ( 44aae2...4bc519 )
by Jonas
09:10
created

unsetRecursiveQueryConstraint()   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 0
Metric Value
eloc 1
c 0
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
    /**
22
     * The additional constraint for the recursive query.
23
     *
24
     * @var callable|null
25
     */
26
    public static $recursiveQueryConstraint;
27
28
    /**
29
     * Get the name of the parent key column.
30
     *
31
     * @return string
32
     */
33 688
    public function getParentKeyName()
34
    {
35 688
        return 'parent_id';
36
    }
37
38
    /**
39
     * Get the qualified parent key column.
40
     *
41
     * @return string
42
     */
43 279
    public function getQualifiedParentKeyName()
44
    {
45 279
        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

45
        return (new static())->/** @scrutinizer ignore-call */ getTable().'.'.$this->getParentKeyName();
Loading history...
46
    }
47
48
    /**
49
     * Get the name of the local key column.
50
     *
51
     * @return string
52
     */
53 653
    public function getLocalKeyName()
54
    {
55 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

55
        return $this->/** @scrutinizer ignore-call */ getKeyName();
Loading history...
56
    }
57
58
    /**
59
     * Get the qualified local key column.
60
     *
61
     * @return string
62
     */
63 326
    public function getQualifiedLocalKeyName()
64
    {
65 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

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

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

127
            /** @scrutinizer ignore-type */ $this,
Loading history...
128 60
            $this->getQualifiedParentKeyName(),
129 60
            $this->getLocalKeyName(),
130 60
            false
131
        );
132
    }
133
134
    /**
135
     * Get the model's ancestors and itself.
136
     *
137
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
138
     */
139 31
    public function ancestorsAndSelf()
140
    {
141 31
        return $this->newAncestors(
142 31
            (new static())->newQuery(),
143
            $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

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

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

201
        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...
202
    }
203
204
    /**
205
     * Get the model's children and itself.
206
     *
207
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
208
     */
209 5
    public function childrenAndSelf()
210
    {
211 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

211
        return $this->descendantsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('<=', 1);
Loading history...
212
    }
213
214
    /**
215
     * Get the model's descendants.
216
     *
217
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
218
     */
219 66
    public function descendants()
220
    {
221 66
        return $this->newDescendants(
222 66
            (new static())->newQuery(),
223
            $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

223
            /** @scrutinizer ignore-type */ $this,
Loading history...
224 66
            $this->getQualifiedParentKeyName(),
225 66
            $this->getLocalKeyName(),
226 66
            false
227
        );
228
    }
229
230
    /**
231
     * Get the model's descendants and itself.
232
     *
233
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
234
     */
235 26
    public function descendantsAndSelf()
236
    {
237 26
        return $this->newDescendants(
238 26
            (new static())->newQuery(),
239
            $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

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

268
        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...
269
    }
270
271
    /**
272
     * Get the model's parent and itself.
273
     *
274
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
275
     */
276 5
    public function parentAndSelf()
277
    {
278 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

278
        return $this->ancestorsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('>=', -1);
Loading history...
279
    }
280
281
    /**
282
     * Get the model's root ancestor.
283
     *
284
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor
285
     */
286 25
    public function rootAncestor()
287
    {
288 25
        return $this->newRootAncestor(
289 25
            (new static())->newQuery(),
290
            $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

290
            /** @scrutinizer ignore-type */ $this,
Loading history...
291 25
            $this->getQualifiedParentKeyName(),
292 25
            $this->getLocalKeyName()
293
        );
294
    }
295
296
    /**
297
     * Instantiate a new RootAncestor relationship.
298
     *
299
     * @param \Illuminate\Database\Eloquent\Builder $query
300
     * @param \Illuminate\Database\Eloquent\Model $parent
301
     * @param string $foreignKey
302
     * @param string $localKey
303
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor
304
     */
305 25
    protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $localKey)
306
    {
307 25
        return new RootAncestor($query, $parent, $foreignKey, $localKey);
308
    }
309
310
    /**
311
     * Get the model's siblings.
312
     *
313
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
314
     */
315 35
    public function siblings()
316
    {
317 35
        return $this->newSiblings(
318 35
            (new static())->newQuery(),
319
            $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

319
            /** @scrutinizer ignore-type */ $this,
Loading history...
320 35
            $this->getQualifiedParentKeyName(),
321 35
            $this->getParentKeyName(),
322 35
            false
323
        );
324
    }
325
326
    /**
327
     * Get the model's siblings and itself.
328
     *
329
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
330
     */
331 30
    public function siblingsAndSelf()
332
    {
333 30
        return $this->newSiblings(
334 30
            (new static())->newQuery(),
335
            $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

335
            /** @scrutinizer ignore-type */ $this,
Loading history...
336 30
            $this->getQualifiedParentKeyName(),
337 30
            $this->getParentKeyName(),
338 30
            true
339
        );
340
    }
341
342
    /**
343
     * Instantiate a new Siblings relationship.
344
     *
345
     * @param \Illuminate\Database\Eloquent\Builder $query
346
     * @param \Illuminate\Database\Eloquent\Model $parent
347
     * @param string $foreignKey
348
     * @param string $localKey
349
     * @param bool $andSelf
350
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
351
     */
352 65
    protected function newSiblings(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
353
    {
354 65
        return new Siblings($query, $parent, $foreignKey, $localKey, $andSelf);
355
    }
356
357
    /**
358
     * Get the first segment of the model's path.
359
     *
360
     * @return string
361
     */
362 60
    public function getFirstPathSegment()
363
    {
364 60
        $path = $this->attributes[$this->getPathName()];
365
366 60
        return explode($this->getPathSeparator(), $path)[0];
367
    }
368
369
    /**
370
     * Determine whether the model's path is nested.
371
     *
372
     * @return bool
373
     */
374 10
    public function hasNestedPath()
375
    {
376 10
        $path = $this->attributes[$this->getPathName()];
377
378 10
        return Str::contains($path, $this->getPathSeparator());
379
    }
380
381
    /**
382
     * Determine if an attribute is an integer.
383
     *
384
     * @param string $attribute
385
     * @return bool
386
     */
387 90
    public function isIntegerAttribute($attribute)
388
    {
389 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

389
        /** @scrutinizer ignore-call */ 
390
        $casts = $this->getCasts();
Loading history...
390
391 90
        return isset($casts[$attribute]) && in_array($casts[$attribute], ['int', 'integer']);
392
    }
393
394
    /**
395
     * Create a new Eloquent query builder for the model.
396
     *
397
     * @param \Illuminate\Database\Query\Builder $query
398
     * @return \Illuminate\Database\Eloquent\Builder|static
399
     */
400 688
    public function newEloquentBuilder($query)
401
    {
402 688
        return new \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder($query);
403
    }
404
405
    /**
406
     * Create a new Eloquent Collection instance.
407
     *
408
     * @param array $models
409
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Collection
410
     */
411 683
    public function newCollection(array $models = [])
412
    {
413 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

413
        return new Collection(/** @scrutinizer ignore-type */ $models);
Loading history...
414
    }
415
416
    /**
417
     * Set an additional constraint for the recursive query.
418
     *
419
     * @param callable $constraint
420
     * @return void
421
     */
422 5
    public static function setRecursiveQueryConstraint(callable $constraint)
423
    {
424 5
        static::$recursiveQueryConstraint = $constraint;
425 5
    }
426
427
    /**
428
     * Unset the additional constraint for the recursive query.
429
     *
430
     * @return void
431
     */
432 5
    public static function unsetRecursiveQueryConstraint()
433
    {
434 5
        static::$recursiveQueryConstraint = null;
435 5
    }
436
437
    /**
438
     * Execute a query with an additional constraint for the recursive query.
439
     *
440
     * @param callable $constraint
441
     * @param callable $query
442
     * @return mixed
443
     */
444 5
    public static function withRecursiveQueryConstraint(callable $constraint, callable $query)
445
    {
446 5
        $previous = static::$recursiveQueryConstraint;
447
448 5
        static::$recursiveQueryConstraint = $constraint;
449
450 5
        $result = $query();
451
452 5
        static::$recursiveQueryConstraint = $previous;
453
454 5
        return $result;
455
    }
456
}
457