Passed
Push — master ( 482c07...a1f161 )
by Jonas
05:55
created

HasRecursiveRelationships::getPathSeparator()   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\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;
18
    use QueriesExpressions;
19
20
    /**
21
     * Get the name of the parent key column.
22
     *
23
     * @return string
24
     */
25 318
    public function getParentKeyName()
26
    {
27 318
        return 'parent_id';
28
    }
29
30
    /**
31
     * Get the qualified parent key column.
32
     *
33
     * @return string
34
     */
35 192
    public function getQualifiedParentKeyName()
36
    {
37 192
        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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

330
        /** @scrutinizer ignore-call */ 
331
        $instance = $this->newRelatedInstance($related);
Loading history...
331
332 54
        $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

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

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

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