Completed
Push — develop ( fe6449...98c976 )
by Abdelrahman
11:45
created

MenuItem::if()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Rinvex\Menus\Models;
6
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\Route;
9
use Collective\Html\HtmlFacade as HTML;
10
use Illuminate\Support\Facades\Request;
11
12
class MenuItem
13
{
14
    /**
15
     * The properties array.
16
     *
17
     * @var array
18
     */
19
    public $properties = [];
20
21
    /**
22
     * The childs collection.
23
     *
24
     * @var \Illuminate\Support\Collection
25
     */
26
    protected $childs;
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
27
28
    /**
29
     * The hide callbacks collection.
30
     *
31
     * @var \Illuminate\Support\Collection
32
     */
33
    protected $hideCallbacks;
34
35
    /**
36
     * The active callback.
37
     *
38
     * @var callable
39
     */
40
    protected $activeWhen;
41
42
    /**
43
     * Constructor.
44
     *
45
     * @param array $properties
46
     */
47
    public function __construct($properties = [])
48
    {
49
        $this->fill($properties);
50
51
        $this->hideCallbacks = collect();
52
        $this->childs = collect();
53
    }
54
55
    /**
56
     * Get property.
57
     *
58
     * @param string $key
59
     *
60
     * @return mixed
61
     */
62
    public function __get($key)
63
    {
64
        return data_get($this->properties, $key);
65
    }
66
67
    /**
68
     * Fill the properties.
69
     *
70
     * @param array $properties
71
     *
72
     * @return static
73
     */
74
    public function fill($properties)
75
    {
76
        $this->properties = array_merge($this->properties, $properties);
77
78
        return $this;
79
    }
80
81
    /**
82
     * Create new menu with dropdown.
83
     *
84
     * @param callable $callback
85
     * @param string   $title
86
     * @param int      $order
0 ignored issues
show
Documentation introduced by
Should the type for parameter $order not be null|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
87
     * @param string   $icon
0 ignored issues
show
Documentation introduced by
Should the type for parameter $icon not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
88
     * @param array    $attributes
89
     *
90
     * @return static
91
     */
92
    public function dropdown(callable $callback, string $title, int $order = null, string $icon = null, array $attributes = [])
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 127 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
93
    {
94
        call_user_func($callback, $item = $this->add(compact('title', 'order', 'icon', 'attributes')));
95
96
        return $item;
97
    }
98
99
    /**
100
     * Register new menu item using registered route.
101
     *
102
     * @param string $route
0 ignored issues
show
Documentation introduced by
Should the type for parameter $route not be array? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
103
     * @param string $title
104
     * @param int    $order
0 ignored issues
show
Documentation introduced by
Should the type for parameter $order not be null|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
105
     * @param string $icon
0 ignored issues
show
Documentation introduced by
Should the type for parameter $icon not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
106
     * @param array  $attributes
107
     *
108
     * @return static
109
     */
110
    public function route(array $route, string $title, int $order = null, string $icon = null, array $attributes = [])
111
    {
112
        return $this->add(compact('route', 'title', 'order', 'icon', 'attributes'));
113
    }
114
115
    /**
116
     * Register new menu item using url.
117
     *
118
     * @param string $url
119
     * @param string $title
120
     * @param int    $order
0 ignored issues
show
Documentation introduced by
Should the type for parameter $order not be null|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
121
     * @param string $icon
0 ignored issues
show
Documentation introduced by
Should the type for parameter $icon not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
122
     * @param array  $attributes
123
     *
124
     * @return static
125
     */
126
    public function url(string $url, string $title, int $order = null, string $icon = null, array $attributes = [])
127
    {
128
        return $this->add(compact('url', 'title', 'order', 'icon', 'attributes'));
129
    }
130
131
    /**
132
     * Add new header item.
133
     *
134
     * @param string $title
135
     * @param int    $order
0 ignored issues
show
Documentation introduced by
Should the type for parameter $order not be null|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
136
     * @param string $icon
0 ignored issues
show
Documentation introduced by
Should the type for parameter $icon not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
137
     * @param array  $attributes
138
     *
139
     * @return static
140
     */
141
    public function header(string $title, int $order = null, string $icon = null, array $attributes = [])
142
    {
143
        $type = 'header';
144
145
        return $this->add(compact('type', 'url', 'title', 'order', 'icon', 'attributes'));
146
    }
147
148
    /**
149
     * Add new divider item.
150
     *
151
     * @param int   $order
0 ignored issues
show
Documentation introduced by
Should the type for parameter $order not be null|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
152
     * @param array $attributes
153
     *
154
     * @return static
155
     */
156
    public function divider(int $order = null, array $attributes = [])
157
    {
158
        return $this->add(['type' => 'divider', 'order' => $order, 'attributes' => $attributes]);
159
    }
160
161
    /**
162
     * Get childs.
163
     *
164
     * @return \Illuminate\Support\Collection
165
     */
166
    public function getChilds(): Collection
167
    {
168
        return $this->childs->sortBy('properties.order');
169
    }
170
171
    /**
172
     * Get url.
173
     *
174
     * @return string
175
     */
176
    public function getUrl(): string
177
    {
178
        return $this->route ? route($this->route[0], $this->route[1] ?? []) : ($this->url ? url($this->url) : '');
0 ignored issues
show
Documentation introduced by
The property route does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property url does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
179
    }
180
181
    /**
182
     * Get HTML attribute data.
183
     *
184
     * @return mixed
185
     */
186
    public function getAttributes()
187
    {
188
        return HTML::attributes($this->attributes);
0 ignored issues
show
Documentation introduced by
The property attributes does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
189
    }
190
191
    /**
192
     * Check if the current item is divider.
193
     *
194
     * @return bool
195
     */
196
    public function isDivider(): bool
197
    {
198
        return $this->type === 'divider';
0 ignored issues
show
Documentation introduced by
The property type does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
199
    }
200
201
    /**
202
     * Check if the current item is header.
203
     *
204
     * @return bool
205
     */
206
    public function isHeader(): bool
207
    {
208
        return $this->type === 'header';
0 ignored issues
show
Documentation introduced by
The property type does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
209
    }
210
211
    /**
212
     * Check is the current item has sub menu .
213
     *
214
     * @return bool
215
     */
216
    public function hasChilds(): bool
217
    {
218
        return $this->childs->isNotEmpty();
219
    }
220
221
    /**
222
     * Check the active state for current menu.
223
     *
224
     * @return bool
225
     */
226
    public function hasActiveOnChild(): bool
227
    {
228
        return $this->hasChilds() ? $this->hasActiveStateFromChilds() : false;
229
    }
230
231
    /**
232
     * Set hide callback for current menu item.
233
     *
234
     * @param callable $callback
235
     *
236
     * @return $this
237
     */
238
    public function hideWhen(callable $callback)
239
    {
240
        $this->hideCallbacks->push($callback);
241
242
        return $this;
243
    }
244
245
    /**
246
     * Set authorization callback for current menu item.
247
     *
248
     * @param string $ability
249
     * @param mixed  $params
250
     *
251
     * @return $this
252
     */
253
    public function ifCan(string $ability, $params = null)
254
    {
255
        $this->hideCallbacks->push(function () use ($ability, $params) {
256
            return ! auth()->user()->can($ability, $params);
0 ignored issues
show
Bug introduced by
The method user does only exist in Illuminate\Contracts\Auth\Guard, but not in Illuminate\Contracts\Auth\Factory.

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...
257
        });
258
259
        return $this;
260
    }
261
262
    /**
263
     * Set condition callback for current menu item.
264
     *
265
     * @param mixed $condition
266
     *
267
     * @return $this
268
     */
269
    public function if($condition)
0 ignored issues
show
Coding Style introduced by
Possible parse error: non-abstract method defined as abstract
Loading history...
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
270
    {
271
        $this->hideCallbacks->push(function () use ($condition) {
272
            return ! $condition;
273
        });
274
275
        return $this;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $this.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
276
    }
277
278
    /**
279
     * Set authentication callback for current menu item.
280
     *
281
     * @return $this
282
     */
283
    public function ifUser()
284
    {
285
        $this->hideCallbacks->push(function () {
286
            return ! auth()->user();
0 ignored issues
show
Bug introduced by
The method user does only exist in Illuminate\Contracts\Auth\Guard, but not in Illuminate\Contracts\Auth\Factory.

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...
287
        });
288
289
        return $this;
290
    }
291
292
    /**
293
     * Set authentication callback for current menu item.
294
     *
295
     * @return $this
296
     */
297
    public function ifGuest()
298
    {
299
        $this->hideCallbacks->push(function () {
300
            return auth()->user();
0 ignored issues
show
Bug introduced by
The method user does only exist in Illuminate\Contracts\Auth\Guard, but not in Illuminate\Contracts\Auth\Factory.

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...
301
        });
302
303
        return $this;
304
    }
305
306
    /**
307
     * Check if the menu item is hidden.
308
     *
309
     * @return bool
310
     */
311
    public function isHidden(): bool
312
    {
313
        return (bool) $this->hideCallbacks->first(function ($callback) {
314
            return call_user_func($callback);
315
        });
316
    }
317
318
    /**
319
     * Get active state for current item.
320
     *
321
     * @return bool
322
     */
323
    public function isActive(): bool
324
    {
325
        if (is_callable($activeWhen = $this->activeWhen)) {
326
            return call_user_func($activeWhen);
327
        }
328
329
        if ($this->route) {
0 ignored issues
show
Documentation introduced by
The property route does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
330
            return $this->hasActiveStateFromRoute();
331
        }
332
333
        return $this->hasActiveStateFromUrl();
334
    }
335
336
    /**
337
     * Set active callback.
338
     *
339
     * @param callable $route
0 ignored issues
show
Bug introduced by
There is no parameter named $route. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
340
     *
341
     * @return $this
342
     */
343
    public function activateWhen(callable $callback)
344
    {
345
        $this->activeWhen = $callback;
346
347
        return $this;
348
    }
349
350
    /**
351
     * Set active callback on the given route.
352
     *
353
     * @param string $route
354
     *
355
     * @return $this
356
     */
357
    public function activateOnRoute(string $route)
358
    {
359
        $this->activeWhen = function () use ($route) {
360
            return str_contains(Route::currentRouteName(), $route);
361
        };
362
363
        return $this;
364
    }
365
366
    /**
367
     * Add new child item.
368
     *
369
     * @param array $properties
370
     *
371
     * @return static
372
     */
373
    protected function add(array $properties = [])
374
    {
375
        $properties['attributes']['id'] = $properties['attributes']['id'] ?? md5(json_encode($properties));
376
        $this->childs->push($item = new static($properties));
377
378
        return $item;
379
    }
380
381
    /**
382
     * Get active status using route.
383
     *
384
     * @return bool
385
     */
386
    protected function hasActiveStateFromRoute(): bool
387
    {
388
        return Route::is($this->route[0]);
0 ignored issues
show
Documentation introduced by
The property route does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
389
    }
390
391
    /**
392
     * Get active status using request url.
393
     *
394
     * @return bool
395
     */
396
    protected function hasActiveStateFromUrl(): bool
397
    {
398
        return Request::is($this->url);
0 ignored issues
show
Documentation introduced by
The property url does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
399
    }
400
401
    /**
402
     * Check if the item has active state from childs.
403
     *
404
     * @return bool
405
     */
406
    protected function hasActiveStateFromChilds(): bool
407
    {
408
        return $this->getChilds()->contains(function (MenuItem $child) {
409
            return ($child->hasChilds() && $child->hasActiveStateFromChilds())
410
                       || ($child->route && $child->hasActiveStateFromRoute())
0 ignored issues
show
Documentation introduced by
The property route does not exist on object<Rinvex\Menus\Models\MenuItem>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
411
                       || $child->isActive() || $child->hasActiveStateFromUrl();
412
        }) ?? false;
413
    }
414
}
415