GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Branch development (184ec4)
by butschster
06:08
created

TreeRepository::getParentField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SleepingOwl\Admin\Repository;
4
5
use Exception;
6
use Illuminate\Support\Collection;
7
use SleepingOwl\Admin\Contracts\TreeRepositoryInterface;
8
9
class TreeRepository extends BaseRepository implements TreeRepositoryInterface
10
{
11
    /**
12
     * Extrepat/Baum tree type
13
     * https://github.com/etrepat/baum.
14
     */
15
    const TreeTypeBaum = 0;
16
17
    /**
18
     * Lasychaser/Laravel-nestedset tree type
19
     * https://github.com/lazychaser/laravel-nestedset.
20
     */
21
    const TreeTypeKalnoy = 1;
22
23
    /**
24
     * Simple tree type (with `parent_id` and `order` fields).
25
     */
26
    const TreeTypeSimple = 2;
27
28
    /**
29
     * Tree type.
30
     * @var int
31
     */
32
    protected $type;
33
34
    /**
35
     * Parent field name.
36
     * @var string
37
     */
38
    protected $parentField = 'parent_id';
39
40
    /**
41
     * Order field name.
42
     * @var string
43
     */
44
    protected $orderField = 'order';
45
46
    /**
47
     * Root parent id value.
48
     * @var null
49
     */
50
    protected $rootParentId = null;
51
52
    /**
53
     * @param string $class
54
     *
55
     * @return $this
56
     */
57
    public function setClass($class)
58
    {
59
        parent::setClass($class);
60
61
        $this->detectType();
62
63
        return $this;
64
    }
65
66
    /**
67
     * Get tree structure.
68
     *
69
     * @param \Illuminate\Database\Eloquent\Collection $collection
70
     *
71
     * @return mixed
72
     */
73
    public function getTree(\Illuminate\Database\Eloquent\Collection $collection)
74
    {
75
        switch ($this->getType()) {
76
            case static::TreeTypeBaum:
77
                return $collection->toHierarchy();
78
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
79
80
            case static::TreeTypeKalnoy:
81
                return $collection->toTree();
82
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
83
84
            case static::TreeTypeSimple:
85
                return $this->createSimpleTree();
86
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
87
        }
88
    }
89
90
    /**
91
     * Get or set tree type.
92
     *
93
     * @return int
94
     */
95
    public function getType()
96
    {
97
        return $this->type;
98
    }
99
100
    /**
101
     * @param int $type
102
     *
103
     * @return $this
104
     */
105
    public function setType($type)
106
    {
107
        $this->type = $type;
108
109
        return $this;
110
    }
111
112
    /**
113
     * @param int $type
114
     *
115
     * @return bool
116
     */
117
    public function isType($type)
118
    {
119
        return $this->type == $type;
120
    }
121
122
    /**
123
     * Get parent field name.
124
     *
125
     * @return string
126
     */
127
    public function getParentField()
128
    {
129
        return $this->parentField;
130
    }
131
132
    /**
133
     * @param string $parentField
134
     *
135
     * @return $this
136
     */
137
    public function setParentField($parentField)
138
    {
139
        $this->parentField = $parentField;
140
141
        return $this;
142
    }
143
144
    /**
145
     * Get order field name.
146
     *
147
     * @return string
148
     */
149
    public function getOrderField()
150
    {
151
        return $this->orderField;
152
    }
153
154
    /**
155
     * @param string $orderField
156
     *
157
     * @return $this
158
     */
159
    public function setOrderField($orderField)
160
    {
161
        $this->orderField = $orderField;
162
163
        return $this;
164
    }
165
166
    /**
167
     * Get or set parent field name.
168
     *
169
     * @return string
170
     */
171
    public function getRootParentId()
172
    {
173
        return $this->rootParentId;
174
    }
175
176
    /**
177
     * @param string $rootParentId
178
     *
179
     * @return $this
180
     */
181
    public function setRootParentId($rootParentId)
182
    {
183
        $this->rootParentId = $rootParentId;
0 ignored issues
show
Documentation Bug introduced by
It seems like $rootParentId of type string is incompatible with the declared type null of property $rootParentId.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
184
185
        return $this;
186
    }
187
188
    /**
189
     * Reorder tree by $data value.
190
     *
191
     * @param $data
192
     */
193
    public function reorder(array $data)
194
    {
195
        if ($this->isType(static::TreeTypeSimple)) {
196
            $this->recursiveReorderSimple($data, $this->getRootParentId());
197
        } else {
198
            $left = 1;
199
            foreach ($data as $root) {
200
                $left = $this->recursiveReorder($root, null, $left);
201
            }
202
        }
203
    }
204
205
    /**
206
     * Move tree node in nested-set tree type.
207
     *
208
     * @param $id
209
     * @param $parentId
210
     * @param $left
211
     * @param $right
212
     */
213
    protected function move($id, $parentId, $left, $right)
214
    {
215
        $instance = $this->find($id);
216
        $attributes = $instance->getAttributes();
0 ignored issues
show
Bug introduced by
The method getAttributes does only exist in Illuminate\Database\Eloquent\Model, but not in Illuminate\Database\Eloq...ase\Eloquent\Collection.

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...
217
        $attributes[$this->getLeftColumn($instance)] = $left;
218
        $attributes[$this->getRightColumn($instance)] = $right;
219
        $attributes[$this->getParentColumn($instance)] = $parentId;
220
        $instance->setRawAttributes($attributes);
0 ignored issues
show
Bug introduced by
The method setRawAttributes does only exist in Illuminate\Database\Eloquent\Model, but not in Illuminate\Database\Eloq...ase\Eloquent\Collection.

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...
221
        $instance->save();
0 ignored issues
show
Bug introduced by
The method save does only exist in Illuminate\Database\Eloquent\Model, but not in Illuminate\Database\Eloq...ase\Eloquent\Collection.

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...
222
    }
223
224
    /**
225
     * Get left column name.
226
     *
227
     * @param $instance
228
     *
229
     * @return mixed
230
     * @throws Exception
231
     */
232
    protected function getLeftColumn($instance)
233
    {
234
        $methods = [
235
            'getLeftColumnName',
236
            'getLftName',
237
        ];
238
239
        return $this->callMethods($instance, $methods);
240
    }
241
242
    /**
243
     * Get right column name.
244
     *
245
     * @param $instance
246
     *
247
     * @return mixed
248
     * @throws Exception
249
     */
250
    protected function getRightColumn($instance)
251
    {
252
        $methods = [
253
            'getRightColumnName',
254
            'getRgtName',
255
        ];
256
257
        return $this->callMethods($instance, $methods);
258
    }
259
260
    /**
261
     * Get parent column name.
262
     *
263
     * @param $instance
264
     *
265
     * @return mixed
266
     * @throws Exception
267
     */
268
    protected function getParentColumn($instance)
269
    {
270
        $methods = [
271
            'getParentColumnName',
272
            'getParentIdName',
273
        ];
274
275
        return $this->callMethods($instance, $methods);
276
    }
277
278
    /**
279
     * Detect tree type.
280
     * @return $this
281
     */
282
    protected function detectType()
283
    {
284
        $model = $this->getModel();
285
286
        // Check for package baum/baum
287
        if ($model instanceof \Baum\Node) {
0 ignored issues
show
Bug introduced by
The class Baum\Node does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
288
            return $this->setType(static::TreeTypeBaum);
289
        }
290
291
        // Check for package kalnoy/nestedset
292
        if (class_exists('Kalnoy\Nestedset\Node') and $model instanceof \Kalnoy\Nestedset\Node) {
0 ignored issues
show
Bug introduced by
The class Kalnoy\Nestedset\Node does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
293
            return $this->setType(static::TreeTypeKalnoy);
294
        } elseif (function_exists('trait_uses_recursive') and $traits = trait_uses_recursive($model) and in_array('Kalnoy\Nestedset\NodeTrait', $traits)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
295
            return $this->setType(static::TreeTypeKalnoy);
296
        } elseif ($traits = class_uses($model) and in_array('Kalnoy\Nestedset\NodeTrait', $traits)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
297
            return $this->setType(static::TreeTypeKalnoy);
298
        }
299
300
        return $this->setType(static::TreeTypeSimple);
301
    }
302
303
    /**
304
     * Call several methods and get first result.
305
     *
306
     * @param $instance
307
     * @param $methods
308
     *
309
     * @return mixed
310
     * @throws Exception
311
     */
312
    protected function callMethods($instance, $methods)
313
    {
314
        foreach ($methods as $method) {
315
            if (method_exists($instance, $method)) {
316
                return $instance->$method();
317
            }
318
        }
319
320
        throw new Exception('Tree type not supported');
321
    }
322
323
    /**
324
     * Recursive reorder nested-set tree type.
325
     *
326
     * @param $root
327
     * @param $parentId
328
     * @param $left
329
     *
330
     * @return mixed
331
     */
332
    protected function recursiveReorder($root, $parentId, $left)
333
    {
334
        $right = $left + 1;
335
        $children = array_get($root, 'children', []);
336
        foreach ($children as $child) {
337
            $right = $this->recursiveReorder($child, $root['id'], $right);
338
        }
339
        $this->move($root['id'], $parentId, $left, $right);
340
        $left = $right + 1;
341
342
        return $left;
343
    }
344
345
    /**
346
     * Recursive reoder simple tree type.
347
     *
348
     * @param $data
349
     * @param $parentId
350
     */
351
    protected function recursiveReorderSimple(array $data, $parentId)
352
    {
353
        foreach ($data as $order => $item) {
354
            $id = $item['id'];
355
356
            $instance = $this->find($id);
357
            $instance->{$this->getParentField()} = $parentId;
358
            $instance->{$this->getOrderField()} = $order;
359
            $instance->save();
0 ignored issues
show
Bug introduced by
The method save does only exist in Illuminate\Database\Eloquent\Model, but not in Illuminate\Database\Eloq...ase\Eloquent\Collection.

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...
360
361
            if (isset($item['children'])) {
362
                $this->recursiveReorderSimple($item['children'], $id);
363
            }
364
        }
365
    }
366
367
    /**
368
     * Get children for simple tree type structure.
369
     *
370
     * @param $collection
371
     * @param $id
372
     *
373
     * @return Collection
374
     */
375
    protected function getChildren($collection, $id)
376
    {
377
        $parentField = $this->getParentField();
378
        $result = [];
379
        foreach ($collection as $instance) {
380
            if ((int) $instance->$parentField != $id) {
381
                continue;
382
            }
383
384
            $instance->setRelation('children', $this->getChildren($collection, $instance->getKey()));
385
            $result[] = $instance;
386
        }
387
388
        return new Collection($result);
389
    }
390
391
    /**
392
     * Create simple tree type structure.
393
     * @return static
394
     */
395
    protected function createSimpleTree()
396
    {
397
        $collection = $this
0 ignored issues
show
Bug introduced by
The method orderBy() does not exist on Illuminate\Database\Eloquent\Builder. Did you maybe mean enforceOrderBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
398
            ->getQuery()
399
            ->orderBy($this->getParentField(), 'asc')
400
            ->orderBy($this->getOrderField(), 'asc')
401
            ->get();
402
403
        return $this->getChildren(
404
            $collection,
405
            $this->getRootParentId()
406
        );
407
    }
408
}
409