Passed
Push — master ( 6ed66a...c3d33f )
by Jonas
06:02
created

HasRecursiveRelationships::hasManyOfDescendantsAndSelf()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 14
ccs 0
cts 0
cp 0
rs 9.9666
cc 3
nc 1
nop 3
crap 12
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\Descendants;
10
use Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\HasManyOfDescendants;
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 HasRecursiveRelationshipScopes, QueriesExpressions;
18
19
    /**
20
     * Get the name of the parent key column.
21
     *
22 196
     * @return string
23
     */
24 196
    public function getParentKeyName()
25
    {
26
        return 'parent_id';
27
    }
28
29
    /**
30
     * Get the qualified parent key column.
31
     *
32 160
     * @return string
33
     */
34 160
    public function getQualifiedParentKeyName()
35
    {
36
        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

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

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

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

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

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

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

163
        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...
164
    }
165
166
    /**
167
     * Get the model's children and itself.
168
     *
169 44
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
170
     */
171 44
    public function childrenAndSelf()
172 44
    {
173
        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

173
        return $this->descendantsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('<=', 1);
Loading history...
174 44
    }
175 44
176 44
    /**
177
     * Get the model's descendants.
178
     *
179
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
180
     */
181
    public function descendants()
182
    {
183
        return $this->newDescendants(
184
            (new static)->newQuery(),
185 22
            $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

185
            /** @scrutinizer ignore-type */ $this,
Loading history...
186
            $this->getQualifiedParentKeyName(),
187 22
            $this->getLocalKeyName(),
188 22
            false
189
        );
190 22
    }
191 22
192 22
    /**
193
     * Get the model's descendants and itself.
194
     *
195
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
196
     */
197
    public function descendantsAndSelf()
198
    {
199
        return $this->newDescendants(
200
            (new static)->newQuery(),
201
            $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

201
            /** @scrutinizer ignore-type */ $this,
Loading history...
202
            $this->getQualifiedParentKeyName(),
203
            $this->getLocalKeyName(),
204
            true
205
        );
206 66
    }
207
208 66
    /**
209
     * Instantiate a new Descendants relationship.
210
     *
211
     * @param \Illuminate\Database\Eloquent\Builder $query
212
     * @param \Illuminate\Database\Eloquent\Model $parent
213
     * @param string $foreignKey
214
     * @param string $localKey
215
     * @param bool $andSelf
216 4
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants
217
     */
218 4
    protected function newDescendants(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
219
    {
220
        return new Descendants($query, $parent, $foreignKey, $localKey, $andSelf);
221
    }
222
223
    /**
224
     * Get the model's parent.
225
     *
226 4
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
227
     */
228 4
    public function parent()
229
    {
230
        return $this->belongsTo(static::class, $this->getParentKeyName(), $this->getLocalKeyName());
0 ignored issues
show
Bug introduced by
It seems like belongsTo() 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

230
        return $this->/** @scrutinizer ignore-call */ belongsTo(static::class, $this->getParentKeyName(), $this->getLocalKeyName());
Loading history...
231
    }
232
233
    /**
234
     * Get the model's parent and itself.
235
     *
236 28
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors
237
     */
238 28
    public function parentAndSelf()
239 28
    {
240
        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

240
        return $this->ancestorsAndSelf()->/** @scrutinizer ignore-call */ whereDepth('>=', -1);
Loading history...
241 28
    }
242 28
243 28
    /**
244
     * Get the model's root ancestor.
245
     *
246
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor
247
     */
248
    public function rootAncestor()
249
    {
250
        return $this->newRootAncestor(
251
            (new static)->newQuery(),
252 24
            $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

252
            /** @scrutinizer ignore-type */ $this,
Loading history...
253
            $this->getQualifiedParentKeyName(),
254 24
            $this->getLocalKeyName()
255 24
        );
256
    }
257 24
258 24
    /**
259 24
     * Instantiate a new RootAncestor relationship.
260
     *
261
     * @param \Illuminate\Database\Eloquent\Builder $query
262
     * @param \Illuminate\Database\Eloquent\Model $parent
263
     * @param string $foreignKey
264
     * @param string $localKey
265
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor
266
     */
267
    protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $localKey)
268
    {
269
        return new RootAncestor($query, $parent, $foreignKey, $localKey);
270
    }
271
272
    /**
273 52
     * Get the model's siblings.
274
     *
275 52
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
276
     */
277
    public function siblings()
278
    {
279
        return $this->newSiblings(
280
            (new static)->newQuery(),
281
            $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

281
            /** @scrutinizer ignore-type */ $this,
Loading history...
282
            $this->getQualifiedParentKeyName(),
283 32
            $this->getParentKeyName(),
284
            false
285 32
        );
286
    }
287 32
288
    /**
289
     * Get the model's siblings and itself.
290
     *
291
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
292
     */
293
    public function siblingsAndSelf()
294
    {
295 8
        return $this->newSiblings(
296
            (new static)->newQuery(),
297 8
            $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

297
            /** @scrutinizer ignore-type */ $this,
Loading history...
298
            $this->getQualifiedParentKeyName(),
299 8
            $this->getParentKeyName(),
300
            true
301
        );
302
    }
303
304
    /**
305
     * Instantiate a new Siblings relationship.
306
     *
307
     * @param \Illuminate\Database\Eloquent\Builder $query
308 196
     * @param \Illuminate\Database\Eloquent\Model $parent
309
     * @param string $foreignKey
310 196
     * @param string $localKey
311
     * @param bool $andSelf
312
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings
313
     */
314
    protected function newSiblings(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
315
    {
316
        return new Siblings($query, $parent, $foreignKey, $localKey, $andSelf);
317
    }
318
319
    /**
320
     * Define a one-to-many relationship of the model's descendants.
321
     *
322
     * @param string $related
323
     * @param string|null $foreignKey
324
     * @param string|null $localKey
325
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\HasManyOfDescendants
326
     */
327
    public function hasManyOfDescendants($related, $foreignKey = null, $localKey = null)
328
    {
329
        $instance = $this->newRelatedInstance($related);
0 ignored issues
show
Bug introduced by
It seems like newRelatedInstance() 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

329
        /** @scrutinizer ignore-call */ 
330
        $instance = $this->newRelatedInstance($related);
Loading history...
330
331
        $foreignKey = $foreignKey ?: $this->getForeignKey();
0 ignored issues
show
Bug introduced by
It seems like getForeignKey() 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

331
        $foreignKey = $foreignKey ?: $this->/** @scrutinizer ignore-call */ getForeignKey();
Loading history...
332
333
        $localKey = $localKey ?: $this->getKeyName();
334
335
        return $this->newHasManyOfDescendants(
336
            $instance->newQuery(),
337
            $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...wHasManyOfDescendants(). ( Ignorable by Annotation )

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

337
            /** @scrutinizer ignore-type */ $this,
Loading history...
338
            $instance->qualifyColumn($foreignKey),
339
            $localKey,
340
            false
341
        );
342
    }
343
344
    /**
345
     * Define a one-to-many relationship of the model's descendants and itself.
346
     *
347
     * @param string $related
348
     * @param string|null $foreignKey
349
     * @param string|null $localKey
350
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\HasManyOfDescendants
351
     */
352
    public function hasManyOfDescendantsAndSelf($related, $foreignKey = null, $localKey = null)
353
    {
354
        $instance = $this->newRelatedInstance($related);
355
356
        $foreignKey = $foreignKey ?: $this->getForeignKey();
357
358
        $localKey = $localKey ?: $this->getKeyName();
359
360
        return $this->newHasManyOfDescendants(
361
            $instance->newQuery(),
362
            $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...wHasManyOfDescendants(). ( Ignorable by Annotation )

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

362
            /** @scrutinizer ignore-type */ $this,
Loading history...
363
            $instance->qualifyColumn($foreignKey),
364
            $localKey,
365
            true
366
        );
367
    }
368
369
    /**
370
     * Instantiate a new HasManyOfDescendants relationship.
371
     *
372
     * @param \Illuminate\Database\Eloquent\Builder $query
373
     * @param \Illuminate\Database\Eloquent\Model $parent
374
     * @param string $foreignKey
375
     * @param string $localKey
376
     * @param bool $andSelf
377
     * @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\HasManyOfDescendants
378
     */
379
    protected function newHasManyOfDescendants(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
380
    {
381
        return new HasManyOfDescendants($query, $parent, $foreignKey, $localKey, $andSelf);
382
    }
383
384
    /**
385
     * Get the first segment of the model's path.
386
     *
387
     * @return string
388
     */
389
    public function getFirstPathSegment()
390
    {
391
        $path = $this->attributes[$this->getPathName()];
392
393
        return explode($this->getPathSeparator(), $path)[0];
394
    }
395
396
    /**
397
     * Determine whether the model's path is nested.
398
     *
399
     * @return bool
400
     */
401
    public function hasNestedPath()
402
    {
403
        $path = $this->attributes[$this->getPathName()];
404
405
        return Str::contains($path, $this->getPathSeparator());
406
    }
407
408
    /**
409
     * Create a new Eloquent query builder for the model.
410
     *
411
     * @param \Illuminate\Database\Query\Builder $query
412
     * @return \Illuminate\Database\Eloquent\Builder|static
413
     */
414
    public function newEloquentBuilder($query)
415
    {
416
        return new \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder($query);
417
    }
418
}
419