Completed
Push — master ( 4ccc94...34cde4 )
by Nicolas
08:38
created

MenuItem::setIconAttribute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 1
crap 2
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 6
    public function __construct($properties = array())
68
    {
69 6
        $this->properties = $properties;
70 6
        $this->fill($properties);
71 6
    }
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 6
    protected static function setIconAttribute(array $properties)
81
    {
82 6
        $icon = array_get($properties, 'attributes.icon');
83 6
        if (!is_null($icon)) {
84 1
            $properties['icon'] = $icon;
85
86 1
            array_forget($properties, 'attributes.icon');
87
88 1
            return $properties;
89
        }
90
91 5
        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);
104
    }
105
106
    /**
107
     * Create new static instance.
108
     *
109
     * @param array $properties
110
     *
111
     * @return static
112
     */
113 6
    public static function make(array $properties)
114
    {
115 6
        $properties = self::setIconAttribute($properties);
116
117 6
        return new static($properties);
118
    }
119
120
    /**
121
     * Fill the attributes.
122
     *
123
     * @param array $attributes
124
     */
125 6
    public function fill($attributes)
126
    {
127 6
        foreach ($attributes as $key => $value) {
128 5
            if (in_array($key, $this->fillable)) {
129 5
                $this->{$key} = $value;
130 5
            }
131 6
        }
132 6
    }
133
134
    /**
135
     * Create new menu child item using array.
136
     *
137
     * @param $attributes
138
     *
139
     * @return $this
140
     */
141
    public function child($attributes)
142
    {
143
        $this->childs[] = static::make($attributes);
144
145
        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 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
        $properties = compact('title', 'order', 'attributes');
159
160
        if (func_num_args() == 3) {
161
            $arguments = func_get_args();
162
163
            $title = array_get($arguments, 0);
164
            $attributes = array_get($arguments, 2);
165
166
            $properties = compact('title', 'attributes');
167
        }
168
169
        $child = static::make($properties);
170
171
        call_user_func($callback, $child);
172
173
        $this->childs[] = $child;
174
175
        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 array
187
     */
188
    public function route($route, $title, $parameters = array(), $order = 0, $attributes = array())
189
    {
190
        if (func_num_args() == 4) {
191
            $arguments = func_get_args();
192
193
            return $this->add([
194
                'route' => [array_get($arguments, 0), array_get($arguments, 2)],
195
                'title' => array_get($arguments, 1),
196
                'attributes' => array_get($arguments, 3),
197
            ]);
198
        }
199
200
        $route = array($route, $parameters);
201
202
        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 array
213
     */
214
    public function url($url, $title, $order = 0, $attributes = array())
215
    {
216 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),
221
                'title' => array_get($arguments, 1),
222
                'attributes' => array_get($arguments, 2),
223
            ]);
224
        }
225
226
        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
    public function add(array $properties)
237
    {
238
        $item = static::make($properties);
239
240
        $this->childs[] = $item;
241
242
        return $item;
243
    }
244
245
    /**
246
     * Add new divider.
247
     *
248
     * @param int $order
249
     *
250
     * @return self
251
     */
252
    public function addDivider($order = null)
253
    {
254
        $item = static::make(array('name' => 'divider', 'order' => $order));
255
256
        $this->childs[] = $item;
257
258
        return $item;
259
    }
260
261
    /**
262
     * Alias method instead "addDivider".
263
     *
264
     * @return MenuItem
265
     */
266
    public function divider()
267
    {
268
        return $this->addDivider();
269
    }
270
271
    /**
272
     * Add dropdown header.
273
     *
274
     * @param $title
275
     *
276
     * @return $this
277
     */
278
    public function addHeader($title)
279
    {
280
        $item = static::make(array(
281
            'name' => 'header',
282
            'title' => $title,
283
        ));
284
285
        $this->childs[] = $item;
286
287
        return $item;
288
    }
289
290
    /**
291
     * Same with "addHeader" method.
292
     *
293
     * @param $title
294
     *
295
     * @return $this
296
     */
297
    public function header($title)
298
    {
299
        return $this->addHeader($title);
300
    }
301
302
    /**
303
     * Get childs.
304
     *
305
     * @return array
306
     */
307
    public function getChilds()
308
    {
309
        if (config('menus.ordering')) {
310
            return collect($this->childs)->sortBy(function ($child) {
311
                return $child->order;
312
            })->all();
313
        }
314
315
        return $this->childs;
316
    }
317
318
    /**
319
     * Get url.
320
     *
321
     * @return string
322
     */
323
    public function getUrl()
324
    {
325
        return !empty($this->route) ? route($this->route[0], $this->route[1]) : url($this->url);
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...
326
    }
327
328
    /**
329
     * Get request url.
330
     *
331
     * @return string
332
     */
333
    public function getRequest()
334
    {
335
        return ltrim(str_replace(url('/'), '', $this->getUrl()), '/');
336
    }
337
338
    /**
339
     * Get icon.
340
     *
341
     * @param null|string $default
342
     *
343
     * @return string
344
     */
345
    public function getIcon($default = null)
346
    {
347
        return !is_null($this->icon) && $this->icon != "" ? '<i class="' . $this->icon . '"></i>' : $default;
348
    }
349
350
    /**
351
     * Get properties.
352
     *
353
     * @return array
354
     */
355 1
    public function getProperties()
356
    {
357 1
        return $this->properties;
358
    }
359
360
    /**
361
     * Get HTML attribute data.
362
     *
363
     * @return mixed
364
     */
365
    public function getAttributes()
366
    {
367
        $attributes = $this->attributes ? $this->attributes : [];
368
369
        array_forget($attributes, ['active', 'icon']);
370
371
        return HTML::attributes($attributes);
372
    }
373
374
    /**
375
     * Check is the current item divider.
376
     *
377
     * @return bool
378
     */
379
    public function isDivider()
380
    {
381
        return $this->is('divider');
382
    }
383
384
    /**
385
     * Check is the current item divider.
386
     *
387
     * @return bool
388
     */
389
    public function isHeader()
390
    {
391
        return $this->is('header');
392
    }
393
394
    /**
395
     * Check is the current item divider.
396
     *
397
     * @param $name
398
     *
399
     * @return bool
400
     */
401
    public function is($name)
402
    {
403
        return $this->name == $name;
404
    }
405
406
    /**
407
     * Check is the current item has sub menu .
408
     *
409
     * @return bool
410
     */
411
    public function hasSubMenu()
412
    {
413
        return !empty($this->childs);
414
    }
415
416
    /**
417
     * Same with hasSubMenu.
418
     *
419
     * @return bool
420
     */
421
    public function hasChilds()
422
    {
423
        return $this->hasSubMenu();
424
    }
425
426
    /**
427
     * Check the active state for current menu.
428
     *
429
     * @return mixed
430
     */
431
    public function hasActiveOnChild()
432
    {
433
        if ($this->inactive()) {
434
            return false;
435
        }
436
437
        return $this->hasChilds() ? $this->getActiveStateFromChilds() : false;
438
    }
439
440
    /**
441
     * Get active state from child menu items.
442
     *
443
     * @return bool
444
     */
445
    public function getActiveStateFromChilds()
446
    {
447
        foreach ($this->getChilds() as $child) {
448
            if ($child->inactive()) {
449
                continue;
450
            } elseif ($child->hasChilds()) {
451
                if ($child->getActiveStateFromChilds()) {
452
                    return true;
453
                }
454
            } elseif ($child->isActive()) {
455
                return true;
456
            } elseif ($child->hasRoute() && $child->getActiveStateFromRoute()) {
457
                return true;
458
            } elseif ($child->getActiveStateFromUrl()) {
459
                return true;
460
            }
461
        }
462
463
        return false;
464
    }
465
466
    /**
467
     * Get inactive state.
468
     *
469
     * @return bool
470
     */
471
    public function inactive()
472
    {
473
        $inactive = $this->getInactiveAttribute();
474
475
        if (is_bool($inactive)) {
476
            return $inactive;
477
        }
478
479
        if ($inactive instanceof \Closure) {
480
            return call_user_func($inactive);
481
        }
482
483
        return false;
484
    }
485
486
    /**
487
     * Get active attribute.
488
     *
489
     * @return string
490
     */
491
    public function getActiveAttribute()
492
    {
493
        return array_get($this->attributes, 'active');
494
    }
495
496
    /**
497
     * Get inactive attribute.
498
     *
499
     * @return string
500
     */
501
    public function getInactiveAttribute()
502
    {
503
        return array_get($this->attributes, 'inactive');
504
    }
505
506
    /**
507
     * Get active state for current item.
508
     *
509
     * @return mixed
510
     */
511
    public function isActive()
512
    {
513
        if ($this->inactive()) {
514
            return false;
515
        }
516
517
        $active = $this->getActiveAttribute();
518
519
        if (is_bool($active)) {
520
            return $active;
521
        }
522
523
        if ($active instanceof \Closure) {
524
            return call_user_func($active);
525
        }
526
527
        if ($this->hasRoute()) {
528
            return $this->getActiveStateFromRoute();
529
        } else {
530
            return $this->getActiveStateFromUrl();
531
        }
532
    }
533
534
    /**
535
     * Determine the current item using route.
536
     *
537
     * @return bool
538
     */
539
    protected function hasRoute()
540
    {
541
        return !empty($this->route);
542
    }
543
544
    /**
545
     * Get active status using route.
546
     *
547
     * @return bool
548
     */
549
    protected function getActiveStateFromRoute()
550
    {
551
        return Request::is(str_replace(url('/') . '/', '', $this->getUrl()));
552
    }
553
554
    /**
555
     * Get active status using request url.
556
     *
557
     * @return bool
558
     */
559
    protected function getActiveStateFromUrl()
560
    {
561
        return Request::is($this->url);
562
    }
563
564
    /**
565
     * Set order value.
566
     *
567
     * @param  int $order
568
     * @return self
569
     */
570
    public function order($order)
571
    {
572
        $this->order = $order;
573
574
        return $this;
575
    }
576
577
    /**
578
     * Set hide condition for current menu item.
579
     *
580
     * @param  Closure
581
     * @return boolean
582
     */
583
    public function hideWhen(Closure $callback)
584
    {
585
        $this->hideWhen = $callback;
586
587
        return $this;
588
    }
589
590
    /**
591
     * Determine whether the menu item is hidden.
592
     *
593
     * @return boolean
594
     */
595
    public function hidden()
596
    {
597
        if (is_null($this->hideWhen)) {
598
            return false;
599
        }
600
601
        return call_user_func($this->hideWhen) == true;
602
    }
603
604
    /**
605
     * Get the instance as an array.
606
     *
607
     * @return array
608
     */
609
    public function toArray()
610
    {
611
        return $this->getProperties();
612
    }
613
614
    /**
615
     * Get property.
616
     *
617
     * @param string $key
618
     *
619
     * @return string|null
620
     */
621
    public function __get($key)
622
    {
623
        return isset($this->$key) ? $this->$key : null;
624
    }
625
}
626