Completed
Push — master ( a7eafe...12a2e2 )
by Nicolas
03:02
created

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