Completed
Pull Request — master (#42)
by
unknown
03:05
created

MenuItem::hasActiveOnChild()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 0
crap 12
1
<?php
2
3
namespace Nwidart\Menus;
4
5
use Closure;
6
use Collective\Html\HtmlFacade as HTML;
7
use Illuminate\Contracts\Support\Arrayable as ArrayableContract;
8
use Illuminate\Support\Facades\Request;
9
10
/**
11
 * @property string url
12
 * @property string route
13
 * @property string title
14
 * @property string name
15
 * @property string icon
16
 * @property int parent
17
 * @property array attributes
18
 * @property bool active
19
 * @property int order
20
 */
21
class MenuItem implements ArrayableContract
22
{
23
    /**
24
     * Array properties.
25
     *
26
     * @var array
27
     */
28
    protected $properties = [];
29
30
    /**
31
     * The child collections for current menu item.
32
     *
33
     * @var array
34
     */
35
    protected $childs = array();
36
37
    /**
38
     * The fillable attribute.
39
     *
40
     * @var array
41
     */
42
    protected $fillable = array(
43
        'url',
44
        'route',
45
        'title',
46
        'name',
47
        'icon',
48
        'parent',
49
        'attributes',
50
        'active',
51
        'order',
52
        'hideWhen',
53
    );
54
55
    /**
56
     * The hideWhen callback.
57
     *
58
     * @var Closure
59
     */
60
    protected $hideWhen;
61
62
    /**
63
     * Constructor.
64
     *
65
     * @param array $properties
66
     */
67 24
    public function __construct($properties = array())
68
    {
69 24
        $this->properties = $properties;
70 24
        $this->fill($properties);
71 24
    }
72
73
    /**
74
     * Set the icon property when the icon is defined in the link attributes.
75
     *
76
     * @param array $properties
77
     *
78
     * @return array
79
     */
80 24
    protected static function setIconAttribute(array $properties)
81
    {
82 24
        $icon = array_get($properties, 'attributes.icon');
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
83 24
        if (!is_null($icon)) {
84 1
            $properties['icon'] = $icon;
85
86 1
            array_forget($properties, 'attributes.icon');
0 ignored issues
show
Deprecated Code introduced by
The function array_forget() has been deprecated with message: Arr::forget() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
87
88 1
            return $properties;
89
        }
90
91 23
        return $properties;
92
    }
93
94
    /**
95
     * Get random name.
96
     *
97
     * @param array $attributes
98
     *
99
     * @return string
100
     */
101
    protected static function getRandomName(array $attributes)
102
    {
103
        return substr(md5(array_get($attributes, 'title', str_random(6))), 0, 5);
0 ignored issues
show
Deprecated Code introduced by
The function str_random() has been deprecated with message: Str::random() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
104
    }
105
106
    /**
107
     * Create new static instance.
108
     *
109
     * @param array $properties
110
     *
111
     * @return static
112
     */
113 24
    public static function make(array $properties)
114
    {
115 24
        $properties = self::setIconAttribute($properties);
116
117 24
        return new static($properties);
118
    }
119
120
    /**
121
     * Fill the attributes.
122
     *
123
     * @param array $attributes
124
     */
125 24
    public function fill($attributes)
126
    {
127 24
        foreach ($attributes as $key => $value) {
128 23
            if (in_array($key, $this->fillable)) {
129 23
                $this->{$key} = $value;
130
            }
131
        }
132 24
    }
133
134
    /**
135
     * Create new menu child item using array.
136
     *
137
     * @param $attributes
138
     *
139
     * @return $this
140
     */
141 2
    public function child($attributes)
142
    {
143 2
        $this->childs[] = static::make($attributes);
144
145 2
        return $this;
146
    }
147
148
    /**
149
     * Register new child menu with dropdown.
150
     *
151
     * @param $title
152
     * @param callable $callback
153
     *
154
     * @return $this
155
     */
156 9 View Code Duplication
    public function dropdown($title, \Closure $callback, $order = 0, array $attributes = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
    {
158 9
        $properties = compact('title', 'order', 'attributes');
159
160 9
        if (func_num_args() === 3) {
161
            $arguments = func_get_args();
162
163
            $title = array_get($arguments, 0);
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
164
            $attributes = array_get($arguments, 2);
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
165
166
            $properties = compact('title', 'attributes');
167
        }
168
169 9
        $child = static::make($properties);
170
171 9
        call_user_func($callback, $child);
172
173 9
        $this->childs[] = $child;
174
175 9
        return $child;
176
    }
177
178
    /**
179
     * Create new menu item and set the action to route.
180
     *
181
     * @param $route
182
     * @param $title
183
     * @param array $parameters
184
     * @param array $attributes
185
     *
186
     * @return MenuItem
187
     */
188 3
    public function route($route, $title, $parameters = array(), $order = 0, $attributes = array())
189
    {
190 3 View Code Duplication
        if (func_num_args() === 4) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
191
            $arguments = func_get_args();
192
193
            return $this->add([
194
                'route' => [array_get($arguments, 0), array_get($arguments, 2)],
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
195
                'title' => array_get($arguments, 1),
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
196
                'attributes' => array_get($arguments, 3),
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
197
            ]);
198
        }
199
200 3
        $route = array($route, $parameters);
201
202 3
        return $this->add(compact('route', 'title', 'order', 'attributes'));
203
    }
204
205
    /**
206
     * Create new menu item  and set the action to url.
207
     *
208
     * @param $url
209
     * @param $title
210
     * @param array $attributes
211
     *
212
     * @return MenuItem
213
     */
214 6
    public function url($url, $title, $order = 0, $attributes = array())
215
    {
216 6 View Code Duplication
        if (func_num_args() === 3) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
217
            $arguments = func_get_args();
218
219
            return $this->add([
220
                'url' => array_get($arguments, 0),
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
221
                'title' => array_get($arguments, 1),
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
222
                'attributes' => array_get($arguments, 2),
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
223
            ]);
224
        }
225
226 6
        return $this->add(compact('url', 'title', 'order', 'attributes'));
227
    }
228
229
    /**
230
     * Add new child item.
231
     *
232
     * @param array $properties
233
     *
234
     * @return $this
235
     */
236 9
    public function add(array $properties)
237
    {
238 9
        $item = static::make($properties);
239
240 9
        $this->childs[] = $item;
241
242 9
        return $item;
243
    }
244
245
    /**
246
     * Add new divider.
247
     *
248
     * @param int $order
249
     *
250
     * @return self
251
     */
252 1
    public function addDivider($order = null)
253
    {
254 1
        $item = static::make(array('name' => 'divider', 'order' => $order));
255
256 1
        $this->childs[] = $item;
257
258 1
        return $item;
259
    }
260
261
    /**
262
     * Alias method instead "addDivider".
263
     *
264
     * @param int $order
265
     *
266
     * @return MenuItem
267
     */
268 1
    public function divider($order = null)
269
    {
270 1
        return $this->addDivider($order);
271
    }
272
273
    /**
274
     * Add dropdown header.
275
     *
276
     * @param $title
277
     *
278
     * @return $this
279
     */
280 2
    public function addHeader($title)
281
    {
282 2
        $item = static::make(array(
283 2
            'name' => 'header',
284 2
            'title' => $title,
285
        ));
286
287 2
        $this->childs[] = $item;
288
289 2
        return $item;
290
    }
291
292
    /**
293
     * Same with "addHeader" method.
294
     *
295
     * @param $title
296
     *
297
     * @return $this
298
     */
299 2
    public function header($title)
300
    {
301 2
        return $this->addHeader($title);
302
    }
303
304
    /**
305
     * Get childs.
306
     *
307
     * @return array
308
     */
309 10
    public function getChilds()
310
    {
311 10
        if (config('menus.ordering')) {
312 1
            return collect($this->childs)->sortBy('order')->all();
313
        }
314
315 9
        return $this->childs;
316
    }
317
318
    /**
319
     * Get url.
320
     *
321
     * @return string
322
     */
323 3
    public function getUrl()
324
    {
325 3
        if ($this->route !== null) {
326 1
            return route($this->route[0], $this->route[1]);
327
        }
328
        
329 2
        if(empty($this->url))
330
            return url("/#");
331
        
332 2
        return url($this->url);
333
    }
334
335
    /**
336
     * Get request url.
337
     *
338
     * @return string
339
     */
340 1
    public function getRequest()
341
    {
342 1
        return ltrim(str_replace(url('/'), '', $this->getUrl()), '/');
343
    }
344
345
    /**
346
     * Get icon.
347
     *
348
     * @param null|string $default
349
     *
350
     * @return string
351
     */
352 3
    public function getIcon($default = null)
353
    {
354 3
        if ($this->icon !== null && $this->icon !== '') {
355 1
            return '<i class="' . $this->icon . '"></i>';
356
        }
357 2
        if ($default === null) {
358 1
            return $default;
359
        }
360
361 1
        return '<i class="' . $default . '"></i>';
362
    }
363
364
    /**
365
     * Get properties.
366
     *
367
     * @return array
368
     */
369 2
    public function getProperties()
370
    {
371 2
        return $this->properties;
372
    }
373
374
    /**
375
     * Get HTML attribute data.
376
     *
377
     * @return mixed
378
     */
379 1
    public function getAttributes()
380
    {
381 1
        $attributes = $this->attributes ? $this->attributes : [];
382
383 1
        array_forget($attributes, ['active', 'icon']);
0 ignored issues
show
Deprecated Code introduced by
The function array_forget() has been deprecated with message: Arr::forget() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
384
385 1
        return HTML::attributes($attributes);
386
    }
387
388
    /**
389
     * Check is the current item divider.
390
     *
391
     * @return bool
392
     */
393 1
    public function isDivider()
394
    {
395 1
        return $this->is('divider');
396
    }
397
398
    /**
399
     * Check is the current item divider.
400
     *
401
     * @return bool
402
     */
403 1
    public function isHeader()
404
    {
405 1
        return $this->is('header');
406
    }
407
408
    /**
409
     * Check is the current item divider.
410
     *
411
     * @param $name
412
     *
413
     * @return bool
414
     */
415 2
    public function is($name)
416
    {
417 2
        return $this->name == $name;
418
    }
419
420
    /**
421
     * Check is the current item has sub menu .
422
     *
423
     * @return bool
424
     */
425 1
    public function hasSubMenu()
426
    {
427 1
        return !empty($this->childs);
428
    }
429
430
    /**
431
     * Same with hasSubMenu.
432
     *
433
     * @return bool
434
     */
435 1
    public function hasChilds()
436
    {
437 1
        return $this->hasSubMenu();
438
    }
439
440
    /**
441
     * Check the active state for current menu.
442
     *
443
     * @return mixed
444
     */
445
    public function hasActiveOnChild()
446
    {
447
        if ($this->inactive()) {
448
            return false;
449
        }
450
451
        return $this->hasChilds() ? $this->getActiveStateFromChilds() : false;
452
    }
453
454
    /**
455
     * Get active state from child menu items.
456
     *
457
     * @return bool
458
     */
459
    public function getActiveStateFromChilds()
460
    {
461
        foreach ($this->getChilds() as $child) {
462
            if ($child->inactive()) {
463
                continue;
464
            }
465
            if ($child->hasChilds()) {
466
                if ($child->getActiveStateFromChilds()) {
467
                    return true;
468
                }
469
            } elseif ($child->isActive()) {
470
                return true;
471
            } elseif ($child->hasRoute() && $child->getActiveStateFromRoute()) {
472
                return true;
473
            } elseif ($child->getActiveStateFromUrl()) {
474
                return true;
475
            }
476
        }
477
478
        return false;
479
    }
480
481
    /**
482
     * Get inactive state.
483
     *
484
     * @return bool
485
     */
486
    public function inactive()
487
    {
488
        $inactive = $this->getInactiveAttribute();
489
490
        if (is_bool($inactive)) {
491
            return $inactive;
492
        }
493
494
        if ($inactive instanceof \Closure) {
495
            return call_user_func($inactive);
496
        }
497
498
        return false;
499
    }
500
501
    /**
502
     * Get active attribute.
503
     *
504
     * @return string
505
     */
506
    public function getActiveAttribute()
507
    {
508
        return array_get($this->attributes, 'active');
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
509
    }
510
511
    /**
512
     * Get inactive attribute.
513
     *
514
     * @return string
515
     */
516
    public function getInactiveAttribute()
517
    {
518
        return array_get($this->attributes, 'inactive');
0 ignored issues
show
Deprecated Code introduced by
The function array_get() has been deprecated with message: Arr::get() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
519
    }
520
521
    /**
522
     * Get active state for current item.
523
     *
524
     * @return mixed
525
     */
526
    public function isActive()
527
    {
528
        if ($this->inactive()) {
529
            return false;
530
        }
531
532
        $active = $this->getActiveAttribute();
533
534
        if (is_bool($active)) {
535
            return $active;
536
        }
537
538
        if ($active instanceof \Closure) {
539
            return call_user_func($active);
540
        }
541
542
        if ($this->hasRoute()) {
543
            return $this->getActiveStateFromRoute();
544
        }
545
546
        return $this->getActiveStateFromUrl();
547
    }
548
549
    /**
550
     * Determine the current item using route.
551
     *
552
     * @return bool
553
     */
554
    protected function hasRoute()
555
    {
556
        return !empty($this->route);
557
    }
558
559
    /**
560
     * Get active status using route.
561
     *
562
     * @return bool
563
     */
564
    protected function getActiveStateFromRoute()
565
    {
566
        return Request::is(str_replace(url('/') . '/', '', $this->getUrl()));
567
    }
568
569
    /**
570
     * Get active status using request url.
571
     *
572
     * @return bool
573
     */
574
    protected function getActiveStateFromUrl()
575
    {
576
        return Request::is($this->url);
577
    }
578
579
    /**
580
     * Set order value.
581
     *
582
     * @param  int $order
583
     * @return self
584
     */
585
    public function order($order)
586
    {
587
        $this->order = $order;
588
589
        return $this;
590
    }
591
592
    /**
593
     * Set hide condition for current menu item.
594
     *
595
     * @param  Closure
596
     * @return boolean
597
     */
598
    public function hideWhen(Closure $callback)
599
    {
600
        $this->hideWhen = $callback;
601
602
        return $this;
603
    }
604
605
    /**
606
     * Determine whether the menu item is hidden.
607
     *
608
     * @return boolean
609
     */
610
    public function hidden()
611
    {
612
        if (is_null($this->hideWhen)) {
613
            return false;
614
        }
615
616
        return call_user_func($this->hideWhen) == true;
617
    }
618
619
    /**
620
     * Get the instance as an array.
621
     *
622
     * @return array
623
     */
624
    public function toArray()
625
    {
626
        return $this->getProperties();
627
    }
628
629
    /**
630
     * Get property.
631
     *
632
     * @param string $key
633
     *
634
     * @return string|null
635
     */
636 4
    public function __get($key)
637
    {
638 4
        return isset($this->$key) ? $this->$key : null;
639
    }
640
}
641