Completed
Push — master ( 3b8fc6...fa37fa )
by ARCANEDEV
10:04
created

MenuItem::route()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1.008

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 6
ccs 4
cts 5
cp 0.8
rs 9.4285
cc 1
eloc 3
nc 1
nop 4
crap 1.008
1
<?php namespace Arcanedev\Menus\Entities;
2
3
use Arcanedev\Menus\Contracts\Entities\MenuItemInterface;
4
use Closure;
5
6
/**
7
 * Class     MenuItem
8
 *
9
 * @package  Arcanedev\Menus\Entities
10
 * @author   ARCANEDEV <[email protected]>
11
 */
12
class MenuItem implements MenuItemInterface
13
{
14
    /* ------------------------------------------------------------------------------------------------
15
     |  Properties
16
     | ------------------------------------------------------------------------------------------------
17
     */
18
    /**
19
     * Menu item type.
20
     *
21
     * @var string
22
     */
23
    protected $type;
24
25
    /**
26
     * Menu item root status.
27
     *
28
     * @var bool
29
     */
30
    protected $root = false;
31
32
    /**
33
     * Menu item properties.
34
     *
35
     * @var array
36
     */
37
    protected $properties;
38
39
    /**
40
     * Menu item attributes.
41
     *
42
     * @var MenuItemAttributes
43
     */
44
    protected $attributes;
45
46
    /**
47
     * Menu item children.
48
     *
49
     * @var MenuItemCollection
50
     */
51
    protected $children;
52
53
    /* ------------------------------------------------------------------------------------------------
54
     |  Constructor
55
     | ------------------------------------------------------------------------------------------------
56
     */
57
    /**
58
     * Make menu item instance.
59
     *
60
     * @param  array  $properties
61
     */
62 115
    public function __construct(array $properties)
63
    {
64 115
        $this->children = new MenuItemCollection;
65 115
        $this->setProperties($properties);
66 115
    }
67
68
    /* ------------------------------------------------------------------------------------------------
69
     |  Getters & Setters
70
     | ------------------------------------------------------------------------------------------------
71
     */
72
    /**
73
     * Set the menu item type.
74
     *
75
     * @param  array  $properties
76
     *
77
     * @return self
78
     */
79 115
    private function setType(array &$properties)
80
    {
81 115
        $type = array_pull($properties, 'type', null);
82
83 115
        $this->type = is_null($type)
84 115
            ? $this->guessType($properties)
85 100
            : $type;
86
87 115
        return $this;
88
    }
89
90
    /**
91
     * Set the menu item root status.
92
     *
93
     * @param  array  $properties
94
     *
95
     * @return self
96
     */
97 115
    private function setRoot(array &$properties)
98
    {
99 115
        $this->root = array_pull($properties, 'root', false);
100
101 115
        return $this;
102
    }
103
104
    /**
105
     * Get the menu item property.
106
     *
107
     * @param  string      $name
108
     * @param  mixed|null  $default
109
     *
110
     * @return mixed
111
     */
112 75
    public function getProperty($name, $default = null)
113
    {
114 75
        return array_get($this->properties, $name, $default);
115
    }
116
117
    /**
118
     * Set the item properties.
119
     *
120
     * @param  array  $properties
121
     *
122
     * @return self
123
     */
124 115
    private function setProperties(array $properties)
125
    {
126 115
        $this->setType($properties);
127 115
        $this->setRoot($properties);
128 115
        $this->attributes = MenuItemAttributes::make(
129 115
            array_pull($properties, 'attributes', [])
130 115
        );
131 115
        $this->properties = array_only($properties, [
132 115
            'url', 'route', 'action', 'content', 'icon', 'active', 'position',
133 115
        ]);
134
135 115
        return $this;
136
    }
137
138
    /**
139
     * Get the menu item attributes.
140
     *
141
     * @return \Arcanedev\Menus\Entities\MenuItemAttributes
142
     */
143 65
    public function attributes()
144
    {
145 65
        return $this->attributes;
146
    }
147
148
    /**
149
     * Get all sub-items.
150
     *
151
     * @return \Arcanedev\Menus\Entities\MenuItemCollection
152
     */
153 95
    public function children()
154
    {
155 95
        return $this->children;
156
    }
157
158
    /**
159
     * Get the menu item url.
160
     */
161 60
    public function getUrl()
162
    {
163 60
        return $this->hasChildren() ? '#' : $this->dispatchUrl();
164
    }
165
166
    /**
167
     * Get the menu item icon.
168
     *
169
     * @param  string  $tag
170
     *
171
     * @return string
172
     */
173 40
    public function getIcon($tag = 'i')
174
    {
175 40
        $icon = array_get($this->properties, 'icon', null);
176
177 40
        if (is_null($icon)) return '';
178
179 10
        return "<$tag " . MenuItemAttributes::make(['class' => $icon])->render() . "></$tag>";
180
    }
181
182
    /**
183
     * Get the menu item content.
184
     *
185
     * @return string
186
     */
187 45
    public function getContent()
188
    {
189 45
        return $this->getProperty('content', '');
190
    }
191
192
    /* ------------------------------------------------------------------------------------------------
193
     |  Main Functions
194
     | ------------------------------------------------------------------------------------------------
195
     */
196
    /**
197
     * Make MenuItem instance.
198
     *
199
     * @param  array     $properties
200
     * @param  \Closure  $callback
201
     *
202
     * @return \Arcanedev\Menus\Entities\MenuItem
203
     */
204 110
    public static function make($properties, Closure $callback = null)
205
    {
206 110
        $item = new self($properties);
207
208 110
        if (is_callable($callback)) {
209 55
            call_user_func($callback, $item);
210 55
        }
211
212 110
        return $item;
213
    }
214
215
    /**
216
     * Fill the menu item properties.
217
     *
218
     * @param  array  $properties
219
     *
220
     * @return \Arcanedev\Menus\Entities\MenuItem
221
     */
222 5
    public function fill(array $properties)
223
    {
224 5
        $this->setProperties($properties);
225
226 5
        return $this;
227
    }
228
229
    /**
230
     * Add an url sub-item to the parent.
231
     *
232
     * @param  string  $url
233
     * @param  string  $content
234
     * @param  array   $attributes
235
     */
236 20
    public function url($url, $content, array $attributes = [])
237
    {
238 20
        $this->makeSubItem('url', compact('url', 'content', 'attributes'));
239 20
    }
240
241
    /**
242
     * Add a route sub-item to the parent.
243
     *
244
     * @param  string  $route
245
     * @param  string  $content
246
     * @param  array   $parameters
247
     * @param  array   $attributes
248
     */
249 40
    public function route($route, $content, array $parameters = [], array $attributes = [])
250
    {
251 40
        $route = [$route, $parameters];
252
253 40
        $this->makeSubItem('route', compact('route', 'content', 'attributes'));
254 40
    }
255
256
    /**
257
     * Add an action sub-item to parent.
258
     *
259
     * @param  string  $action
260
     * @param  string  $content
261
     * @param  array   $parameters
262
     * @param  array   $attributes
263
     */
264 20
    public function action($action, $content, array $parameters = [], array $attributes = [])
265
    {
266 20
        $action = [$action, $parameters];
267
268 20
        $this->makeSubItem('action', compact('action', 'content', 'attributes'));
269 20
    }
270
271
    /**
272
     * Add a dropdown sub-item to the parent.
273
     *
274
     * @param  string    $content
275
     * @param  \Closure  $callback
276
     * @param  array     $attributes
277
     */
278 20
    public function dropdown($content, Closure $callback, array $attributes = [])
279
    {
280 20
        $this->makeSubItem('dropdown', compact('content', 'attributes'), $callback);
281 20
    }
282
283
    /**
284
     * Add a divider sub-item to the parent.
285
     */
286 20
    public function divider()
287
    {
288 20
        $this->makeSubItem('divider');
289 20
    }
290
291
    /**
292
     * Add a header item to the parent.
293
     *
294
     * @param  string  $content
295
     */
296 20
    public function header($content)
297
    {
298 20
        $this->makeSubItem('header', compact('content'));
299 20
    }
300
301
    /**
302
     * Add an item to the parent.
303
     *
304
     * @param  array     $properties
305
     * @param  \Closure  $callback
306
     */
307 20
    public function add(array $properties, Closure $callback = null)
308
    {
309 20
        $this->makeSubItem(null, $properties, $callback);
310 20
    }
311
312
    /* ------------------------------------------------------------------------------------------------
313
     |  Check Functions
314
     | ------------------------------------------------------------------------------------------------
315
     */
316
    /**
317
     * Check if the menu item is root.
318
     *
319
     * @return bool
320
     */
321 35
    public function isRoot()
322
    {
323 35
        return $this->root;
324
    }
325
326
    /**
327
     * Check if the menu item is a dropdown item.
328
     *
329
     * @return bool
330
     */
331 5
    public function isDropdown()
332
    {
333 5
        return $this->isType('dropdown') || $this->hasChildren();
334
    }
335
336
    /**
337
     * Check if the menu item is a header.
338
     *
339
     * @return bool
340
     */
341 5
    public function isHeader()
342
    {
343 5
        return $this->isType('header');
344
    }
345
346
    /**
347
     * Check if menu item is a divider.
348
     *
349
     * @return bool
350
     */
351 85
    public function isDivider()
352
    {
353 85
        return $this->isType('divider');
354
    }
355
356
    /**
357
     * Check if menu item is active.
358
     *
359
     * @return bool
360
     */
361 75
    public function isActive()
362
    {
363 75
        return (bool) $this->getProperty('active', false);
364
    }
365
366
    /**
367
     * Check if the menu item has sub-items.
368
     *
369
     * @return bool
370
     */
371 90
    public function hasChildren()
372
    {
373 90
        return ! $this->children()->isEmpty();
374
    }
375
376
    /**
377
     * Check the menu item type.
378
     *
379
     * @param  string  $type
380
     *
381
     * @return bool
382
     */
383 90
    private function isType($type)
384
    {
385 90
        return $this->type === $type;
386
    }
387
388
    /* ------------------------------------------------------------------------------------------------
389
     |  Other Functions
390
     | ------------------------------------------------------------------------------------------------
391
     */
392
    /**
393
     * Make an child item and add it to the parent item.
394
     *
395
     * @param  string         $type
396
     * @param  array          $properties
397
     * @param  \Closure|null  $callback
398
     *
399
     * @return self
400
     */
401 55
    private function makeSubItem($type, array $properties = [], Closure $callback = null)
402
    {
403 55
        $item = self::make(array_merge($properties, compact('type')), $callback);
404
405 55
        $this->addChild($item);
406
407 55
        return $item;
408
    }
409
410
    /**
411
     * Add a child item to collection.
412
     *
413
     * @param  self  $item
414
     *
415
     * @return \Arcanedev\Menus\Entities\MenuItem
416
     */
417 55
    private function addChild(MenuItem $item)
418
    {
419 55
        $this->children->push($item);
420
421 55
        return $this;
422
    }
423
424
    /**
425
     * Dispatch menu item url.
426
     *
427
     * @param  string  $default
428
     *
429
     * @return string
430
     */
431 45
    private function dispatchUrl($default = '#')
432
    {
433 45
        if ($this->isType('url')) {
434 20
            return $this->getProperty('url');
435
        }
436
437 30
        if ($this->isType('route')) {
438 5
            list($route, $parameters) = $this->getProperty('route');
439
440 5
            return route($route, $parameters);
441
        }
442
443 25
        if ($this->isType('action')) {
444 5
            list($action, $parameters) = $this->getProperty('action');
445
446 5
            return action($action, $parameters);
447
        }
448
449 20
        return $default;
450
    }
451
452
    /**
453
     * Guess the menu item type.
454
     *
455
     * @param  array  $properties
456
     *
457
     * @return string|null
458
     */
459 100
    private function guessType(array $properties)
460
    {
461 100
        $types = ['url', 'route', 'action'];
462
463 100
        foreach ($types as $type) {
464 100
            if (array_key_exists($type, $properties)) return $type;
465 60
        }
466
467 20
        return null;
468
    }
469
}
470