Completed
Pull Request — master (#17)
by Nauris
03:58 queued 02:21
created

MenuItem::is()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
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 bool auth
20
 * @property int order
21
 */
22
class MenuItem implements ArrayableContract
23
{
24
    /**
25
     * Array properties.
26
     *
27
     * @var array
28
     */
29
    protected $properties = [];
30
31
    /**
32
     * The child collections for current menu item.
33
     *
34
     * @var array
35
     */
36
    protected $childs = array();
37
38
    /**
39
     * The fillable attribute.
40
     *
41
     * @var array
42
     */
43
    protected $fillable = array(
44
        'url',
45
        'route',
46
        'title',
47
        'name',
48
        'icon',
49
        'parent',
50
        'attributes',
51
        'active',
52
        'order',
53
        'hideWhen',
54
        'auth',
55
    );
56
57
    /**
58
     * The hideWhen callback.
59
     *
60
     * @var Closure
61
     */
62
    protected $hideWhen;
63
64
    /**
65
     * Constructor.
66
     *
67
     * @param array $properties
68
     */
69 25
    public function __construct($properties = array())
70
    {
71 25
        $this->properties = $properties;
72 25
        $this->fill($properties);
73 25
    }
74
75
    /**
76
     * Set the icon property when the icon is defined in the link attributes.
77
     *
78
     * @param array $properties
79
     *
80
     * @return array
81
     */
82 25 View Code Duplication
    protected static function setIconAttribute(array $properties)
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...
83
    {
84 25
        $icon = array_get($properties, 'attributes.icon');
85 25
        if (!is_null($icon)) {
86 1
            $properties['icon'] = $icon;
87
88 1
            array_forget($properties, 'attributes.icon');
89
90 1
            return $properties;
91
        }
92
93 24
        return $properties;
94
    }
95
96
    /**
97
     * Get random name.
98
     *
99
     * @param array $attributes
100
     *
101
     * @return string
102
     */
103
    protected static function getRandomName(array $attributes)
104
    {
105
        return substr(md5(array_get($attributes, 'title', str_random(6))), 0, 5);
106
    }
107
108
    /**
109
     * Create new static instance.
110
     *
111
     * @param array $properties
112
     *
113
     * @return static
114
     */
115 25
    public static function make(array $properties)
116
    {
117 25
        $properties = self::setIconAttribute($properties);
118 25
        $properties = self::setAuthAttribute($properties);
119
120 25
        return new static($properties);
121
    }
122
123
    /**
124
     * Fill the attributes.
125
     *
126
     * @param array $attributes
127
     */
128 25
    public function fill($attributes)
129
    {
130 25
        foreach ($attributes as $key => $value) {
131 24
            if (in_array($key, $this->fillable)) {
132 24
                $this->{$key} = $value;
133
            }
134
        }
135 25
    }
136
137
    /**
138
     * Create new menu child item using array.
139
     *
140
     * @param $attributes
141
     *
142
     * @return $this
143
     */
144 2
    public function child($attributes)
145
    {
146 2
        $this->childs[] = static::make($attributes);
147
148 2
        return $this;
149
    }
150
151
    /**
152
     * Register new child menu with dropdown.
153
     *
154
     * @param $title
155
     * @param callable $callback
156
     *
157
     * @return $this
158
     */
159 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...
160
    {
161 9
        $properties = compact('title', 'order', 'attributes');
162
163 9
        if (func_num_args() === 3) {
164
            $arguments = func_get_args();
165
166
            $title = array_get($arguments, 0);
167
            $attributes = array_get($arguments, 2);
168
169
            $properties = compact('title', 'attributes');
170
        }
171
172 9
        $child = static::make($properties);
173
174 9
        call_user_func($callback, $child);
175
176 9
        $this->childs[] = $child;
177
178 9
        return $child;
179
    }
180
181
    /**
182
     * Create new menu item and set the action to route.
183
     *
184
     * @param $route
185
     * @param $title
186
     * @param array $parameters
187
     * @param array $attributes
188
     *
189
     * @return MenuItem
190
     */
191 3
    public function route($route, $title, $parameters = array(), $order = 0, $attributes = array())
192
    {
193 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...
194
            $arguments = func_get_args();
195
196
            return $this->add([
197
                'route' => [array_get($arguments, 0), array_get($arguments, 2)],
198
                'title' => array_get($arguments, 1),
199
                'attributes' => array_get($arguments, 3),
200
            ]);
201
        }
202
203 3
        $route = array($route, $parameters);
204
205 3
        return $this->add(compact('route', 'title', 'order', 'attributes'));
206
    }
207
208
    /**
209
     * Create new menu item  and set the action to url.
210
     *
211
     * @param $url
212
     * @param $title
213
     * @param array $attributes
214
     *
215
     * @return MenuItem
216
     */
217 6
    public function url($url, $title, $order = 0, $attributes = array())
218
    {
219 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...
220
            $arguments = func_get_args();
221
222
            return $this->add([
223
                'url' => array_get($arguments, 0),
224
                'title' => array_get($arguments, 1),
225
                'attributes' => array_get($arguments, 2),
226
            ]);
227
        }
228
229 6
        return $this->add(compact('url', 'title', 'order', 'attributes'));
230
    }
231
232
    /**
233
     * Add new child item.
234
     *
235
     * @param array $properties
236
     *
237
     * @return $this
238
     */
239 9
    public function add(array $properties)
240
    {
241 9
        $item = static::make($properties);
242
243 9
        $this->childs[] = $item;
244
245 9
        return $item;
246
    }
247
248
    /**
249
     * Add new divider.
250
     *
251
     * @param int $order
252
     *
253
     * @return self
254
     */
255 1
    public function addDivider($order = null)
256
    {
257 1
        $item = static::make(array('name' => 'divider', 'order' => $order));
258
259 1
        $this->childs[] = $item;
260
261 1
        return $item;
262
    }
263
264
    /**
265
     * Alias method instead "addDivider".
266
     *
267
     * @param int $order
268
     *
269
     * @return MenuItem
270
     */
271 1
    public function divider($order = null)
272
    {
273 1
        return $this->addDivider($order);
274
    }
275
276
    /**
277
     * Add dropdown header.
278
     *
279
     * @param $title
280
     *
281
     * @return $this
282
     */
283 2
    public function addHeader($title)
284
    {
285 2
        $item = static::make(array(
286 2
            'name' => 'header',
287 2
            'title' => $title,
288
        ));
289
290 2
        $this->childs[] = $item;
291
292 2
        return $item;
293
    }
294
295
    /**
296
     * Same with "addHeader" method.
297
     *
298
     * @param $title
299
     *
300
     * @return $this
301
     */
302 2
    public function header($title)
303
    {
304 2
        return $this->addHeader($title);
305
    }
306
307
    /**
308
     * Get childs.
309
     *
310
     * @return array
311
     */
312 10
    public function getChilds()
313
    {
314 10
        if (config('menus.ordering')) {
315 1
            return collect($this->childs)->sortBy('order')->all();
316
        }
317
318 9
        return $this->childs;
319
    }
320
321
    /**
322
     * Get url.
323
     *
324
     * @return string
325
     */
326 3
    public function getUrl()
327
    {
328 3
        if ($this->route !== null) {
329 1
            return route($this->route[0], $this->route[1]);
0 ignored issues
show
Documentation introduced by
$this->route[1] is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
330
        }
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', 'auth']);
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');
509
    }
510
511
    /**
512
     * Get inactive attribute.
513
     *
514
     * @return string
515
     */
516
    public function getInactiveAttribute()
517
    {
518
        return array_get($this->attributes, 'inactive');
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
    /**
642
     * Set the auth property when the auth is defined in the link attributes.
643
     *
644
     * @param array $properties
645
     *
646
     * @return array
647
     */
648 25 View Code Duplication
    protected static function setAuthAttribute(array $properties)
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...
649
    {
650 25
        $auth = array_get($properties, 'attributes.auth');
651 25
        if ($auth) {
652 1
            $properties['auth'] = (bool) $auth;
653
654 1
            array_forget($properties, 'attributes.auth');
655
656 1
            return $properties;
657
        }
658
659 24
        return $properties;
660
    }
661
}
662