Completed
Push — master ( d98a4f...240190 )
by ARCANEDEV
04:05
created

src/Eloquent/QueryBuilder.php (34 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php namespace Arcanedev\LaravelNestedSet\Eloquent;
2
3
use Arcanedev\LaravelNestedSet\Traits\NodeTrait;
4
use Arcanedev\LaravelNestedSet\Utilities\NestedSet;
5
use Arcanedev\LaravelNestedSet\Utilities\TreeHelper;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\ModelNotFoundException;
8
use Illuminate\Database\Query\Builder as Query;
9
use Illuminate\Database\Query\Expression;
10
use LogicException;
11
12
/**
13
 * Class     QueryBuilder
14
 *
15
 * @package  Arcanedev\LaravelNestedSet\Eloquent
16
 * @author   ARCANEDEV <[email protected]>
17
 */
18
class QueryBuilder extends Builder
19
{
20
    /* ------------------------------------------------------------------------------------------------
21
     |  Properties
22
     | ------------------------------------------------------------------------------------------------
23
     */
24
    /**
25
     * The model being queried.
26
     *
27
     * @var \Illuminate\Database\Eloquent\Model|\Arcanedev\LaravelNestedSet\Traits\NodeTrait
28
     */
29
    protected $model;
30
31
    /* ------------------------------------------------------------------------------------------------
32
     |  Main Functions
33
     | ------------------------------------------------------------------------------------------------
34
     */
35
    /**
36
     * Get node's `lft` and `rgt` values.
37
     *
38
     * @param  mixed  $id
39
     * @param  bool   $required
40
     *
41
     * @return array
42
     */
43 76
    public function getNodeData($id, $required = false)
44
    {
45 76
        $query = $this->toBase();
46
47 76
        $query->where($this->model->getKeyName(), '=', $id);
48
49 76
        $data  = $query->first([
50 76
            $this->model->getLftName(),
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
51 76
            $this->model->getRgtName(),
0 ignored issues
show
The method getRgtName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
52 57
        ]);
53
54 76
        if ( ! $data && $required) {
55 4
            throw new ModelNotFoundException;
56
        }
57
58 72
        return (array) $data;
59
    }
60
61
    /**
62
     * Get plain node data.
63
     *
64
     * @param  mixed  $id
65
     * @param  bool   $required
66
     *
67
     * @return array
68
     */
69 48
    public function getPlainNodeData($id, $required = false)
70
    {
71 48
        return array_values($this->getNodeData($id, $required));
72
    }
73
74
    /**
75
     * Scope limits query to select just root node.
76
     *
77
     * @return self
78
     */
79 20
    public function whereIsRoot()
80
    {
81 20
        $this->query->whereNull($this->model->getParentIdName());
0 ignored issues
show
The method getParentIdName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
82
83 20
        return $this;
84
    }
85
86
    /**
87
     * Limit results to ancestors of specified node.
88
     *
89
     * @param  mixed  $id
90
     *
91
     * @return self
92
     */
93 20
    public function whereAncestorOf($id)
94
    {
95 20
        $keyName = $this->model->getKeyName();
96
97 20
        if (NestedSet::isNode($id)) {
98 16
            $value = '?';
99
100 16
            $this->query->addBinding($id->getLft());
101
102 16
            $id = $id->getKey();
103 12
        } else {
104 4
            $valueQuery = $this->model
105 4
                ->newQuery()
106 4
                ->toBase()
107 4
                ->select("_.".$this->model->getLftName())
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
108 4
                ->from($this->model->getTable().' as _')
109 4
                ->where($keyName, '=', $id)
110 4
                ->limit(1);
111
112 4
            $this->query->mergeBindings($valueQuery);
113
114 4
            $value = '(' . $valueQuery->toSql() . ')';
115
        }
116
117 20
        list($lft, $rgt) = $this->wrappedColumns();
118
119 20
        $this->query->whereRaw("{$value} between {$lft} and {$rgt}");
120
121
        // Exclude the node
122 20
        $this->where($keyName, '<>', $id);
123
124 20
        return $this;
125
    }
126
127
    /**
128
     * Get ancestors of specified node.
129
     *
130
     * @param  mixed  $id
131
     * @param  array  $columns
132
     *
133
     * @return self
134
     */
135 12
    public function ancestorsOf($id, array $columns = ['*'])
136
    {
137 12
        return $this->whereAncestorOf($id)->get($columns);
138
    }
139
140
    /**
141
     * Add node selection statement between specified range.
142
     *
143
     * @param  array   $values
144
     * @param  string  $boolean
145
     * @param  bool    $not
146
     *
147
     * @return self
148
     */
149 44
    public function whereNodeBetween($values, $boolean = 'and', $not = false)
150
    {
151 44
        $this->query->whereBetween($this->model->getLftName(), $values, $boolean, $not);
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
152
153 44
        return $this;
154
    }
155
156
    /**
157
     * Add node selection statement between specified range joined with `or` operator.
158
     *
159
     * @param  array  $values
160
     *
161
     * @return self
162
     */
163
    public function orWhereNodeBetween($values)
164
    {
165
        return $this->whereNodeBetween($values, 'or');
166
    }
167
168
    /**
169
     * Add constraint statement to descendants of specified node.
170
     *
171
     * @param  mixed   $id
172
     * @param  string  $boolean
173
     * @param  bool    $not
174
     *
175
     * @return self
176
     */
177 48
    public function whereDescendantOf($id, $boolean = 'and', $not = false)
178
    {
179 48
        $data = NestedSet::isNode($id)
180 47
            ? $id->getBounds()
181 48
            : $this->model->newNestedSetQuery()->getPlainNodeData($id, true);
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
182
183
        // Don't include the node
184 44
        ++$data[0];
185
186 44
        return $this->whereNodeBetween($data, $boolean, $not);
187
    }
188
189
    /**
190
     * @param  mixed  $id
191
     *
192
     * @return self
193
     */
194
    public function whereNotDescendantOf($id)
195
    {
196
        return $this->whereDescendantOf($id, 'and', true);
197
    }
198
199
    /**
200
     * @param  mixed  $id
201
     *
202
     * @return self
203
     */
204 4
    public function orWhereDescendantOf($id)
205
    {
206 4
        return $this->whereDescendantOf($id, 'or');
207
    }
208
209
    /**
210
     * @param  mixed  $id
211
     *
212
     * @return self
213
     */
214
    public function orWhereNotDescendantOf($id)
215
    {
216
        return $this->whereDescendantOf($id, 'or', true);
217
    }
218
219
    /**
220
     * Get descendants of specified node.
221
     *
222
     * @param  mixed  $id
223
     * @param  array  $columns
224
     *
225
     * @return \Arcanedev\LaravelNestedSet\Eloquent\Collection
226
     */
227
    public function descendantsOf($id, array $columns = ['*'])
228
    {
229
        try {
230
            return $this->whereDescendantOf($id)->get($columns);
231
        }
232
        catch (ModelNotFoundException $e) {
233
            return $this->model->newCollection();
234
        }
235
    }
236
237
    /**
238
     * @param  mixed   $id
239
     * @param  string  $operator
240
     * @param  string  $boolean
241
     *
242
     * @return self
243
     */
244
    protected function whereIsBeforeOrAfter($id, $operator, $boolean)
245
    {
246
        if (NestedSet::isNode($id)) {
247
            $value = '?';
248
249
            $this->query->addBinding($id->getLft());
250
        } else {
251
            $valueQuery = $this->model
252
                ->newQuery()
253
                ->toBase()
254
                ->select('_n.'.$this->model->getLftName())
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
255
                ->from($this->model->getTable().' as _n')
256
                ->where('_n.'.$this->model->getKeyName(), '=', $id);
257
258
            $this->query->mergeBindings($valueQuery);
259
260
            $value = '('.$valueQuery->toSql().')';
261
        }
262
263
        list($lft,) = $this->wrappedColumns();
264
265
        $this->query->whereRaw("{$lft} {$operator} {$value}", [ ], $boolean);
266
267
        return $this;
268
    }
269
270
    /**
271
     * Constraint nodes to those that are after specified node.
272
     *
273
     * @param  mixed   $id
274
     * @param  string  $boolean
275
     *
276
     * @return self
277
     */
278
    public function whereIsAfter($id, $boolean = 'and')
279
    {
280
        return $this->whereIsBeforeOrAfter($id, '>', $boolean);
281
    }
282
283
    /**
284
     * Constraint nodes to those that are before specified node.
285
     *
286
     * @param  mixed   $id
287
     * @param  string  $boolean
288
     *
289
     * @return self
290
     */
291
    public function whereIsBefore($id, $boolean = 'and')
292
    {
293
        return $this->whereIsBeforeOrAfter($id, '<', $boolean);
294
    }
295
296
    /**
297
     * Include depth level into the result.
298
     *
299
     * @param  string  $as
300
     *
301
     * @return self
302
     */
303 16
    public function withDepth($as = 'depth')
304
    {
305 16
        if ($this->query->columns === null) {
306 16
            $this->query->columns = ['*'];
307 12
        }
308
309 16
        $table = $this->wrappedTable();
310
311 16
        list($lft, $rgt) = $this->wrappedColumns();
312
313 16
        $query = $this->model
0 ignored issues
show
The method newScopedQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
314 16
            ->newScopedQuery('_d')
315 16
            ->toBase()
316 16
            ->selectRaw('count(1) - 1')
317 16
            ->from($this->model->getTable().' as _d')
318 16
            ->whereRaw("{$table}.{$lft} between _d.{$lft} and _d.{$rgt}");
319
320 16
        $this->query->selectSub($query, $as);
321
322 16
        return $this;
323
    }
324
325
    /**
326
     * Get wrapped `lft` and `rgt` column names.
327
     *
328
     * @return array
329
     */
330 48
    protected function wrappedColumns()
331
    {
332 48
        $grammar = $this->query->getGrammar();
333
334
        return [
335 48
            $grammar->wrap($this->model->getLftName()),
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
336 48
            $grammar->wrap($this->model->getRgtName()),
0 ignored issues
show
The method getRgtName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
337 36
        ];
338
    }
339
340
    /**
341
     * Get a wrapped table name.
342
     *
343
     * @return string
344
     */
345 28
    protected function wrappedTable()
346
    {
347 28
        return $this->query->getGrammar()->wrapTable($this->getQuery()->from);
348
    }
349
350
    /**
351
     * Wrap model's key name.
352
     *
353
     * @return string
354
     */
355 12
    protected function wrappedKey()
356
    {
357 12
        return $this->query->getGrammar()->wrap($this->model->getKeyName());
358
    }
359
360
    /**
361
     * Exclude root node from the result.
362
     *
363
     * @return self
364
     */
365 8
    public function withoutRoot()
366
    {
367 8
        $this->query->whereNotNull($this->model->getParentIdName());
0 ignored issues
show
The method getParentIdName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
368
369 8
        return $this;
370
    }
371
372
    /**
373
     * Order by node position.
374
     *
375
     * @param  string  $dir
376
     *
377
     * @return self
378
     */
379 52
    public function defaultOrder($dir = 'asc')
380
    {
381 52
        $this->query->orders = null;
382
383 52
        $this->query->orderBy($this->model->getLftName(), $dir);
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
384
385 52
        return $this;
386
    }
387
388
    /**
389
     * Order by reversed node position.
390
     *
391
     * @return $this
392
     */
393 4
    public function reversed()
394
    {
395 4
        return $this->defaultOrder('desc');
396
    }
397
398
    /**
399
     * Move a node to the new position.
400
     *
401
     * @param  mixed  $key
402
     * @param  int    $position
403
     *
404
     * @return int
405
     */
406 40
    public function moveNode($key, $position)
407
    {
408 40
        list($lft, $rgt) = $this->model->newNestedSetQuery()
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
409 40
                                       ->getPlainNodeData($key, true);
410
411 40
        if ($lft < $position && $position <= $rgt) {
412
            throw new LogicException('Cannot move node into itself.');
413
        }
414
415
        // Get boundaries of nodes that should be moved to new position
416 40
        $from = min($lft, $position);
417 40
        $to   = max($rgt, $position - 1);
418
419
        // The height of node that is being moved
420 40
        $height   = $rgt - $lft + 1;
421
422
        // The distance that our node will travel to reach it's destination
423 40
        $distance = $to - $from + 1 - $height;
424
425
        // If no distance to travel, just return
426 40
        if ($distance === 0) {
427
            return 0;
428
        }
429
430 40
        if ($position > $lft) {
431 32
            $height *= -1;
432 24
        } else {
433 8
            $distance *= -1;
434
        }
435
436 40
        $boundary = [$from, $to];
437
        $query    = $this->toBase()->where(function (Query $inner) use ($boundary) {
438 40
            $inner->whereBetween($this->model->getLftName(), $boundary);
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
439 40
            $inner->orWhereBetween($this->model->getRgtName(), $boundary);
0 ignored issues
show
The method getRgtName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
440 40
        });
441
442 40
        return $query->update($this->patch(
443 40
            compact('lft', 'rgt', 'from', 'to', 'height', 'distance')
444 30
        ));
445
    }
446
447
    /**
448
     * Make or remove gap in the tree. Negative height will remove gap.
449
     *
450
     * @param  int  $cut
451
     * @param  int  $height
452
     *
453
     * @return int
454
     */
455 48
    public function makeGap($cut, $height)
456
    {
457
        $query = $this->toBase()->whereNested(function (Query $inner) use ($cut) {
458 48
            $inner->where($this->model->getLftName(), '>=', $cut);
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
459 48
            $inner->orWhere($this->model->getRgtName(), '>=', $cut);
0 ignored issues
show
The method getRgtName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
460 48
        });
461
462 48
        return $query->update($this->patch(
463 48
            compact('cut', 'height')
464 36
        ));
465
    }
466
467
    /**
468
     * Get patch for columns.
469
     *
470
     * @param  array  $params
471
     *
472
     * @return array
473
     */
474 84
    protected function patch(array $params)
475
    {
476 84
        $grammar = $this->query->getGrammar();
477 84
        $columns = [];
478
479 84
        foreach ([$this->model->getLftName(), $this->model->getRgtName()] as $col) {
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
The method getRgtName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
480 84
            $columns[$col] = $this->columnPatch($grammar->wrap($col), $params);
481 63
        }
482
483 84
        return $columns;
484
    }
485
486
    /**
487
     * Get patch for single column.
488
     *
489
     * @param  string  $col
490
     * @param  array   $params
491
     *
492
     * @return string
493
     */
494 84
    protected function columnPatch($col, array $params)
495
    {
496
        /**
497
         * @var int $height
498
         * @var int $distance
499
         * @var int $lft
500
         * @var int $rgt
501
         * @var int $from
502
         * @var int $to
503
         */
504 84
        extract($params);
505
506 84
        if ($height > 0) $height = '+'.$height;
507
508 84
        if (isset($cut)) {
509 48
            return new Expression("case when {$col} >= {$cut} then {$col}{$height} else {$col} end");
510
        }
511
512 40
        if ($distance > 0) {
513 32
            $distance = '+'.$distance;
514 24
        }
515
516 40
        return new Expression(
517
            "case ".
518 40
            "when {$col} between {$lft} and {$rgt} then {$col}{$distance} ". // Move the node
519 40
            "when {$col} between {$from} and {$to} then {$col}{$height} ". // Move other nodes
520 40
            "else {$col} end"
521 30
        );
522
    }
523
524
    /**
525
     * Get statistics of errors of the tree.
526
     *
527
     * @return array
528
     */
529 12
    public function countErrors()
530
    {
531
        $checks = [
532 12
            'oddness'        => $this->getOddnessQuery(),      // Check if lft and rgt values are ok
533 12
            'duplicates'     => $this->getDuplicatesQuery(),   // Check if lft and rgt values are unique
534 12
            'wrong_parent'   => $this->getWrongParentQuery(),  // Check if parent_id is set correctly
535 12
            'missing_parent' => $this->getMissingParentQuery() // Check for nodes that have missing parent
536 9
        ];
537
538 12
        $query = $this->query->newQuery();
539
540 12
        foreach ($checks as $key => $inner) {
541
            /** @var \Illuminate\Database\Query\Builder $inner */
542 12
            $inner->selectRaw('count(1)');
543
544 12
            $query->selectSub($inner, $key);
545 9
        }
546
547 12
        return (array) $query->first();
548
    }
549
550
    /**
551
     * @return \Illuminate\Database\Query\Builder
552
     */
553 12
    protected function getOddnessQuery()
554
    {
555 12
        return $this->model
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
556 12
            ->newNestedSetQuery()
557 12
            ->toBase()
558
            ->whereNested(function (Query $inner) {
559 12
                list($lft, $rgt) = $this->wrappedColumns();
560
561 12
                $inner->whereRaw("{$lft} >= {$rgt}")
562 12
                      ->orWhereRaw("({$rgt} - {$lft}) % 2 = 0");
563 12
            });
564
    }
565
566
    /**
567
     * @return \Illuminate\Database\Query\Builder
568
     */
569 12
    protected function getDuplicatesQuery()
570
    {
571 12
        $table = $this->wrappedTable();
572
573 12
        $query = $this->model
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
574 12
            ->newNestedSetQuery('c1')
575 12
            ->toBase()
576 12
            ->from($this->query->raw("{$table} c1, {$table} c2"))
577 12
            ->whereRaw("c1.id < c2.id")
578
            ->whereNested(function (Query $inner) {
579 12
                list($lft, $rgt) = $this->wrappedColumns();
580
581 12
                $inner->orWhereRaw("c1.{$lft}=c2.{$lft}")
582 12
                      ->orWhereRaw("c1.{$rgt}=c2.{$rgt}")
583 12
                      ->orWhereRaw("c1.{$lft}=c2.{$rgt}")
584 12
                      ->orWhereRaw("c1.{$rgt}=c2.{$lft}");
585 12
            });
586
587 12
        return $this->model->applyNestedSetScope($query, 'c2');
0 ignored issues
show
The method applyNestedSetScope does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
588
    }
589
590
    /**
591
     * @return \Illuminate\Database\Query\Builder
592
     */
593 12
    protected function getWrongParentQuery()
594
    {
595 12
        $table        = $this->wrappedTable();
596 12
        $keyName      = $this->wrappedKey();
597 12
        $parentIdName = $this->query->raw($this->model->getParentIdName());
0 ignored issues
show
The method getParentIdName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
598 12
        $query        = $this->model
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
599 12
            ->newNestedSetQuery('c')
600 12
            ->toBase()
601 12
            ->from($this->query->raw("{$table} c, {$table} p, $table m"))
602 12
            ->whereRaw("c.{$parentIdName}=p.{$keyName}")
603 12
            ->whereRaw("m.{$keyName} <> p.{$keyName}")
604 12
            ->whereRaw("m.{$keyName} <> c.{$keyName}")
605
            ->whereNested(function (Query $inner) {
606 12
                list($lft, $rgt) = $this->wrappedColumns();
607
608 12
                $inner->whereRaw("c.{$lft} not between p.{$lft} and p.{$rgt}")
609 12
                      ->orWhereRaw("c.{$lft} between m.{$lft} and m.{$rgt}")
610 12
                      ->whereRaw("m.{$lft} between p.{$lft} and p.{$rgt}");
611 12
            });
612
613 12
        $this->model->applyNestedSetScope($query, 'p');
0 ignored issues
show
The method applyNestedSetScope does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
614 12
        $this->model->applyNestedSetScope($query, 'm');
615
616 12
        return $query;
617
    }
618
619
    /**
620
     * @return \Illuminate\Database\Query\Builder
621
     */
622 12
    protected function getMissingParentQuery()
623
    {
624 12
        return $this->model
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
625 12
            ->newNestedSetQuery()
626 12
            ->toBase()
627 12
            ->whereNested(function (Query $inner) {
628 12
                $table = $this->wrappedTable();
629 12
                $keyName = $this->wrappedKey();
630 12
                $parentIdName = $this->query->raw($this->model->getParentIdName());
0 ignored issues
show
The method getParentIdName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
631
632 12
                $existsCheck = $this->model
0 ignored issues
show
The method newNestedSetQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
633 12
                    ->newNestedSetQuery()
634 12
                    ->toBase()
635 12
                    ->selectRaw('1')
636 12
                    ->from($this->query->raw("{$table} p"))
637 12
                    ->whereRaw("{$table}.{$parentIdName} = p.{$keyName}")
638 12
                    ->limit(1);
639
640 12
                $this->model->applyNestedSetScope($existsCheck, 'p');
0 ignored issues
show
The method applyNestedSetScope does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
641
642 12
                $inner->whereRaw("{$parentIdName} is not null")
643 12
                      ->addWhereExistsQuery($existsCheck, 'and', true);
644 12
            });
645
    }
646
647
    /**
648
     * Get the number of total errors of the tree.
649
     *
650
     * @return int
651
     */
652 8
    public function getTotalErrors()
653
    {
654 8
        return array_sum($this->countErrors());
655
    }
656
657
    /**
658
     * Get whether the tree is broken.
659
     *
660
     * @return bool
661
     */
662 8
    public function isBroken()
663
    {
664 8
        return $this->getTotalErrors() > 0;
665
    }
666
667
    /**
668
     * Fixes the tree based on parentage info.
669
     * Nodes with invalid parent are saved as roots.
670
     *
671
     * @return int The number of fixed nodes
672
     */
673 4
    public function fixTree()
674
    {
675
        $columns   = [
676 4
            $this->model->getKeyName(),
677 4
            $this->model->getParentIdName(),
0 ignored issues
show
The method getParentIdName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
678 4
            $this->model->getLftName(),
0 ignored issues
show
The method getLftName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
679 4
            $this->model->getRgtName(),
0 ignored issues
show
The method getRgtName does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
680 3
        ];
681
682 4
        $dictionary = $this->defaultOrder()
683 4
                ->get($columns)
684 4
                ->groupBy($this->model->getParentIdName())
685 4
                ->all();
686
687 4
        return TreeHelper::fixNodes($dictionary);
688
    }
689
690
    /**
691
     * Rebuild the tree based on raw data.
692
     * If item data does not contain primary key, new node will be created.
693
     *
694
     * @param  array  $data
695
     * @param  bool   $delete  Whether to delete nodes that exists but not in the data array
696
     *
697
     * @return int
698
     */
699 8
    public function rebuildTree(array $data, $delete = false)
700
    {
701 8
        $existing   = $this->get()->getDictionary();
702 8
        $dictionary = [];
703 8
        $this->buildRebuildDictionary($dictionary, $data, $existing);
704
705 4
        if ( ! empty($existing)) {
706 4
            if ($delete) {
707 4
                $this->model
0 ignored issues
show
The method newScopedQuery does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
708 4
                    ->newScopedQuery()
709 4
                    ->whereIn($this->model->getKeyName(), array_keys($existing))
710 4
                    ->forceDelete();
711 3
            } else {
712
                /** @var NodeTrait $model */
713
                foreach ($existing as $model) {
714
                    $dictionary[$model->getParentId()][] = $model;
715
                }
716
            }
717 3
        }
718
719 4
        return TreeHelper::fixNodes($dictionary);
720
    }
721
722
    /**
723
     * @param  array  $dictionary
724
     * @param  array  $data
725
     * @param  array  $existing
726
     * @param  mixed  $parentId
727
     */
728 8
    protected function buildRebuildDictionary(
729
        array &$dictionary,
730
        array $data,
731
        array &$existing,
732
        $parentId = null
733
    ) {
734 8
        $keyName = $this->model->getKeyName();
735
736 8
        foreach ($data as $itemData) {
737 8
            if ( ! isset($itemData[$keyName])) {
738 4
                $model = $this->model->newInstance();
739
                // We will save it as raw node since tree will be fixed
740 4
                $model->rawNode(0, 0, $parentId);
741 3
            } else {
742 4
                if ( ! isset($existing[$key = $itemData[$keyName]])) {
743 4
                    throw new ModelNotFoundException;
744
                }
745
                $model = $existing[$key];
746
                unset($existing[$key]);
747
            }
748
749 4
            $model->fill($itemData)->save();
750 4
            $dictionary[$parentId][] = $model;
751
752 4
            if ( ! isset($itemData['children'])) {
753 4
                continue;
754
            }
755
756
            $this->buildRebuildDictionary(
757
                $dictionary,
758
                $itemData['children'],
759
                $existing,
760
                $model->getKey()
761
            );
762 3
        }
763 4
    }
764
765
    /**
766
     * @param  string|null  $table
767
     *
768
     * @return self
769
     */
770
    public function applyNestedSetScope($table = null)
771
    {
772
        return $this->model->applyNestedSetScope($this, $table);
0 ignored issues
show
The method applyNestedSetScope does only exist in Arcanedev\LaravelNestedSet\Traits\NodeTrait, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
773
    }
774
775
    /**
776
     * Get the root node.
777
     *
778
     * @param  array  $columns
779
     *
780
     * @return self
781
     */
782 16
    public function root(array $columns = ['*'])
783
    {
784 16
        return $this->whereIsRoot()->first($columns);
785
    }
786
}
787