This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Nwidart\Menus; |
||
4 | |||
5 | use Countable; |
||
6 | use Illuminate\Contracts\Config\Repository; |
||
7 | use Illuminate\Support\Arr; |
||
8 | use Illuminate\View\Factory as ViewFactory; |
||
9 | |||
10 | class MenuBuilder implements Countable |
||
11 | { |
||
12 | /** |
||
13 | * Menu name. |
||
14 | * |
||
15 | * @var string |
||
16 | */ |
||
17 | protected $menu; |
||
18 | |||
19 | /** |
||
20 | * Array menu items. |
||
21 | * |
||
22 | * @var array |
||
23 | */ |
||
24 | protected $items = []; |
||
25 | |||
26 | /** |
||
27 | * Default presenter class. |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $presenter = Presenters\Bootstrap\NavbarPresenter::class; |
||
32 | |||
33 | /** |
||
34 | * Style name for each presenter. |
||
35 | * |
||
36 | * @var array |
||
37 | */ |
||
38 | protected $styles = []; |
||
39 | |||
40 | /** |
||
41 | * Prefix URL. |
||
42 | * |
||
43 | * @var string|null |
||
44 | */ |
||
45 | protected $prefixUrl; |
||
46 | |||
47 | /** |
||
48 | * The name of view presenter. |
||
49 | * |
||
50 | * @var string |
||
51 | */ |
||
52 | protected $view; |
||
53 | |||
54 | /** |
||
55 | * The laravel view factory instance. |
||
56 | * |
||
57 | * @var \Illuminate\View\Factory |
||
58 | */ |
||
59 | protected $views; |
||
60 | |||
61 | /** |
||
62 | * Determine whether the ordering feature is enabled or not. |
||
63 | * |
||
64 | * @var boolean |
||
65 | */ |
||
66 | protected $ordering = false; |
||
67 | |||
68 | /** |
||
69 | * Resolved item binding map. |
||
70 | * |
||
71 | * @var array |
||
72 | */ |
||
73 | protected $bindings = []; |
||
74 | /** |
||
75 | * @var Repository |
||
76 | */ |
||
77 | private $config; |
||
78 | |||
79 | /** |
||
80 | * Constructor. |
||
81 | * |
||
82 | * @param string $menu |
||
83 | * @param Repository $config |
||
84 | */ |
||
85 | 10 | public function __construct($menu, Repository $config) |
|
86 | { |
||
87 | 10 | $this->menu = $menu; |
|
88 | 10 | $this->config = $config; |
|
89 | 10 | } |
|
90 | |||
91 | /** |
||
92 | * Get menu name. |
||
93 | * |
||
94 | * @return string |
||
95 | */ |
||
96 | 1 | public function getName() |
|
97 | { |
||
98 | 1 | return $this->menu; |
|
99 | } |
||
100 | |||
101 | /** |
||
102 | * Find menu item by given its title. |
||
103 | * |
||
104 | * @param string $title |
||
105 | * @param callable|null $callback |
||
106 | * @return mixed |
||
107 | */ |
||
108 | public function whereTitle($title, callable $callback = null) |
||
109 | { |
||
110 | $item = $this->findBy('title', $title); |
||
111 | |||
112 | if (is_callable($callback)) { |
||
113 | return call_user_func($callback, $item); |
||
114 | } |
||
115 | |||
116 | return $item; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Find menu item by given key and value. |
||
121 | * |
||
122 | * @param string $key |
||
123 | * @param string $value |
||
124 | * @return \Nwidart\Menus\MenuItem |
||
125 | */ |
||
126 | public function findBy($key, $value) |
||
127 | { |
||
128 | return collect($this->items)->filter(function ($item) use ($key, $value) { |
||
129 | return $item->{$key} == $value; |
||
130 | })->first(); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * Set view factory instance. |
||
135 | * |
||
136 | * @param ViewFactory $views |
||
137 | * |
||
138 | * @return $this |
||
139 | */ |
||
140 | 9 | public function setViewFactory(ViewFactory $views) |
|
141 | { |
||
142 | 9 | $this->views = $views; |
|
143 | |||
144 | 9 | return $this; |
|
145 | } |
||
146 | |||
147 | /** |
||
148 | * Set view. |
||
149 | * |
||
150 | * @param string $view |
||
151 | * |
||
152 | * @return $this |
||
153 | */ |
||
154 | public function setView($view) |
||
155 | { |
||
156 | $this->view = $view; |
||
157 | |||
158 | return $this; |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Set Prefix URL. |
||
163 | * |
||
164 | * @param string $prefixUrl |
||
165 | * |
||
166 | * @return $this |
||
167 | */ |
||
168 | public function setPrefixUrl($prefixUrl) |
||
169 | { |
||
170 | $this->prefixUrl = $prefixUrl; |
||
171 | |||
172 | return $this; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Set styles. |
||
177 | * |
||
178 | * @param array $styles |
||
179 | */ |
||
180 | public function setStyles(array $styles) |
||
181 | { |
||
182 | $this->styles = $styles; |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Set new presenter class. |
||
187 | * |
||
188 | * @param string $presenter |
||
189 | */ |
||
190 | public function setPresenter($presenter) |
||
191 | { |
||
192 | $this->presenter = $presenter; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Get presenter instance. |
||
197 | * |
||
198 | * @return \Nwidart\Menus\Presenters\PresenterInterface |
||
199 | */ |
||
200 | 3 | public function getPresenter() |
|
201 | { |
||
202 | 3 | return new $this->presenter(); |
|
203 | } |
||
204 | |||
205 | /** |
||
206 | * Set new presenter class by given style name. |
||
207 | * |
||
208 | * @param string $name |
||
209 | * |
||
210 | * @return self |
||
211 | */ |
||
212 | public function style($name) |
||
213 | { |
||
214 | if ($this->hasStyle($name)) { |
||
215 | $this->setPresenter($this->getStyle($name)); |
||
216 | } |
||
217 | |||
218 | return $this; |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * Determine if the given name in the presenter style. |
||
223 | * |
||
224 | * @param $name |
||
225 | * |
||
226 | * @return bool |
||
227 | */ |
||
228 | 3 | public function hasStyle($name) |
|
229 | { |
||
230 | 3 | return array_key_exists($name, $this->getStyles()); |
|
231 | } |
||
232 | |||
233 | /** |
||
234 | * Get style aliases. |
||
235 | * |
||
236 | * @return mixed |
||
237 | */ |
||
238 | 3 | public function getStyles() |
|
239 | { |
||
240 | 3 | return $this->styles ?: $this->config->get('menus.styles'); |
|
241 | } |
||
242 | |||
243 | /** |
||
244 | * Get the presenter class name by given alias name. |
||
245 | * |
||
246 | * @param $name |
||
247 | * |
||
248 | * @return mixed |
||
249 | */ |
||
250 | public function getStyle($name) |
||
251 | { |
||
252 | $style = $this->getStyles(); |
||
253 | |||
254 | return $style[$name]; |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Set new presenter class from given alias name. |
||
259 | * |
||
260 | * @param $name |
||
261 | */ |
||
262 | public function setPresenterFromStyle($name) |
||
263 | { |
||
264 | $this->setPresenter($this->getStyle($name)); |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Set the resolved item bindings |
||
269 | * |
||
270 | * @param array $bindings |
||
271 | * @return $this |
||
272 | */ |
||
273 | 3 | public function setBindings(array $bindings) |
|
274 | { |
||
275 | 3 | $this->bindings = $bindings; |
|
276 | |||
277 | 3 | return $this; |
|
278 | } |
||
279 | |||
280 | /** |
||
281 | * Resolves a key from the bindings array. |
||
282 | * |
||
283 | * @param string|array $key |
||
284 | * @return mixed |
||
285 | */ |
||
286 | public function resolve($key) |
||
287 | { |
||
288 | if (is_array($key)) { |
||
289 | foreach ($key as $k => $v) { |
||
290 | $key[$k] = $this->resolve($v); |
||
291 | } |
||
292 | } elseif (is_string($key)) { |
||
293 | $matches = array(); |
||
294 | preg_match_all('/{[\s]*?([^\s]+)[\s]*?}/i', $key, $matches, PREG_SET_ORDER); |
||
295 | foreach ($matches as $match) { |
||
296 | if (array_key_exists($match[1], $this->bindings)) { |
||
297 | $key = preg_replace('/' . $match[0] . '/', $this->bindings[$match[1]], $key, 1); |
||
298 | } |
||
299 | } |
||
300 | } |
||
301 | |||
302 | return $key; |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Resolves an array of menu items properties. |
||
307 | * |
||
308 | * @param array &$items |
||
309 | * @return void |
||
310 | */ |
||
311 | 3 | protected function resolveItems(array &$items) |
|
312 | { |
||
313 | $resolver = function ($property) { |
||
314 | return $this->resolve($property) ?: $property; |
||
315 | 3 | }; |
|
316 | |||
317 | 3 | $totalItems = count($items); |
|
318 | 3 | for ($i = 0; $i < $totalItems; $i++) { |
|
319 | $items[$i]->fill(array_map($resolver, $items[$i]->getProperties())); |
||
320 | } |
||
321 | 3 | } |
|
322 | |||
323 | /** |
||
324 | * Add new child menu. |
||
325 | * |
||
326 | * @param array $attributes |
||
327 | * |
||
328 | * @return \Nwidart\Menus\MenuItem |
||
329 | */ |
||
330 | public function add(array $attributes = array()) |
||
331 | { |
||
332 | $item = MenuItem::make($attributes); |
||
333 | |||
334 | $this->items[] = $item; |
||
335 | |||
336 | return $item; |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Create new menu with dropdown. |
||
341 | * |
||
342 | * @param $title |
||
343 | * @param callable $callback |
||
344 | * @param array $attributes |
||
345 | * |
||
346 | * @return $this |
||
347 | */ |
||
348 | View Code Duplication | public function dropdown($title, \Closure $callback, $order = null, array $attributes = array()) |
|
0 ignored issues
–
show
|
|||
349 | { |
||
350 | $properties = compact('title', 'order', 'attributes'); |
||
351 | |||
352 | if (func_num_args() == 3) { |
||
353 | $arguments = func_get_args(); |
||
354 | |||
355 | $title = Arr::get($arguments, 0); |
||
356 | $attributes = Arr::get($arguments, 2); |
||
357 | |||
358 | $properties = compact('title', 'attributes'); |
||
359 | } |
||
360 | |||
361 | $item = MenuItem::make($properties); |
||
362 | |||
363 | call_user_func($callback, $item); |
||
364 | |||
365 | $this->items[] = $item; |
||
366 | |||
367 | return $item; |
||
368 | } |
||
369 | |||
370 | /** |
||
371 | * Register new menu item using registered route. |
||
372 | * |
||
373 | * @param $route |
||
374 | * @param $title |
||
375 | * @param array $parameters |
||
376 | * @param array $attributes |
||
377 | * |
||
378 | * @return static |
||
379 | */ |
||
380 | public function route($route, $title, $parameters = array(), $order = null, $attributes = array()) |
||
381 | { |
||
382 | View Code Duplication | if (func_num_args() == 4) { |
|
0 ignored issues
–
show
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. ![]() |
|||
383 | $arguments = func_get_args(); |
||
384 | |||
385 | return $this->add([ |
||
386 | 'route' => [Arr::get($arguments, 0), Arr::get($arguments, 2)], |
||
387 | 'title' => Arr::get($arguments, 1), |
||
388 | 'attributes' => Arr::get($arguments, 3), |
||
389 | ]); |
||
390 | } |
||
391 | |||
392 | $route = array($route, $parameters); |
||
393 | |||
394 | $item = MenuItem::make( |
||
395 | compact('route', 'title', 'parameters', 'attributes', 'order') |
||
396 | ); |
||
397 | |||
398 | $this->items[] = $item; |
||
399 | |||
400 | return $item; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * Format URL. |
||
405 | * |
||
406 | * @param string $url |
||
407 | * |
||
408 | * @return string |
||
409 | */ |
||
410 | 2 | protected function formatUrl($url) |
|
411 | { |
||
412 | 2 | $uri = !is_null($this->prefixUrl) ? $this->prefixUrl . $url : $url; |
|
413 | |||
414 | 2 | return $uri == '/' ? '/' : ltrim(rtrim($uri, '/'), '/'); |
|
415 | } |
||
416 | |||
417 | /** |
||
418 | * Register new menu item using url. |
||
419 | * |
||
420 | * @param $url |
||
421 | * @param $title |
||
422 | * @param array $attributes |
||
423 | * |
||
424 | * @return static |
||
425 | */ |
||
426 | 2 | public function url($url, $title, $order = 0, $attributes = array()) |
|
427 | { |
||
428 | 2 | View Code Duplication | if (func_num_args() == 3) { |
0 ignored issues
–
show
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. ![]() |
|||
429 | $arguments = func_get_args(); |
||
430 | |||
431 | return $this->add([ |
||
432 | 'url' => $this->formatUrl(Arr::get($arguments, 0)), |
||
433 | 'title' => Arr::get($arguments, 1), |
||
434 | 'attributes' => Arr::get($arguments, 2), |
||
435 | ]); |
||
436 | } |
||
437 | |||
438 | 2 | $url = $this->formatUrl($url); |
|
439 | |||
440 | 2 | $item = MenuItem::make(compact('url', 'title', 'order', 'attributes')); |
|
441 | |||
442 | 2 | $this->items[] = $item; |
|
443 | |||
444 | 2 | return $item; |
|
445 | } |
||
446 | |||
447 | /** |
||
448 | * Add new divider item. |
||
449 | * |
||
450 | * @param int $order |
||
451 | * @return \Nwidart\Menus\MenuItem |
||
452 | */ |
||
453 | public function addDivider($order = null) |
||
454 | { |
||
455 | $this->items[] = new MenuItem(array('name' => 'divider', 'order' => $order)); |
||
456 | |||
457 | return $this; |
||
458 | } |
||
459 | |||
460 | /** |
||
461 | * Add new header item. |
||
462 | * |
||
463 | * @return \Nwidart\Menus\MenuItem |
||
464 | */ |
||
465 | public function addHeader($title, $order = null) |
||
466 | { |
||
467 | $this->items[] = new MenuItem(array( |
||
468 | 'name' => 'header', |
||
469 | 'title' => $title, |
||
470 | 'order' => $order, |
||
471 | )); |
||
472 | |||
473 | return $this; |
||
474 | } |
||
475 | |||
476 | /** |
||
477 | * Alias for "addHeader" method. |
||
478 | * |
||
479 | * @param string $title |
||
480 | * |
||
481 | * @return $this |
||
482 | */ |
||
483 | public function header($title) |
||
484 | { |
||
485 | return $this->addHeader($title); |
||
486 | } |
||
487 | |||
488 | /** |
||
489 | * Alias for "addDivider" method. |
||
490 | * |
||
491 | * @return $this |
||
492 | */ |
||
493 | public function divider() |
||
494 | { |
||
495 | return $this->addDivider(); |
||
496 | } |
||
497 | |||
498 | /** |
||
499 | * Get items count. |
||
500 | * |
||
501 | * @return int |
||
502 | */ |
||
503 | 1 | public function count() |
|
504 | { |
||
505 | 1 | return count($this->items); |
|
506 | } |
||
507 | |||
508 | /** |
||
509 | * Empty the current menu items. |
||
510 | */ |
||
511 | public function destroy() |
||
512 | { |
||
513 | $this->items = array(); |
||
514 | |||
515 | return $this; |
||
516 | } |
||
517 | |||
518 | /** |
||
519 | * Render the menu to HTML tag. |
||
520 | * |
||
521 | * @param string $presenter |
||
522 | * |
||
523 | * @return string |
||
524 | */ |
||
525 | 3 | public function render($presenter = null) |
|
526 | { |
||
527 | 3 | $this->resolveItems($this->items); |
|
528 | |||
529 | 3 | if (!is_null($this->view)) { |
|
530 | return $this->renderView($presenter); |
||
531 | } |
||
532 | |||
533 | 3 | if ($this->hasStyle($presenter)) { |
|
534 | $this->setPresenterFromStyle($presenter); |
||
535 | } |
||
536 | |||
537 | 3 | if (!is_null($presenter) && !$this->hasStyle($presenter)) { |
|
538 | $this->setPresenter($presenter); |
||
539 | } |
||
540 | |||
541 | 3 | return $this->renderMenu(); |
|
542 | } |
||
543 | |||
544 | /** |
||
545 | * Render menu via view presenter. |
||
546 | * |
||
547 | * @return \Illuminate\View\View |
||
548 | */ |
||
549 | public function renderView($presenter = null) |
||
550 | { |
||
551 | return $this->views->make($presenter ?: $this->view, [ |
||
552 | 'items' => $this->getOrderedItems(), |
||
553 | ]); |
||
554 | } |
||
555 | |||
556 | /** |
||
557 | * Get original items. |
||
558 | * |
||
559 | * @return array |
||
560 | */ |
||
561 | public function getItems() |
||
562 | { |
||
563 | return $this->items; |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * Get menu items as laravel collection instance. |
||
568 | * |
||
569 | * @return \Illuminate\Support\Collection |
||
570 | */ |
||
571 | public function toCollection() |
||
572 | { |
||
573 | return collect($this->items); |
||
574 | } |
||
575 | |||
576 | /** |
||
577 | * Get menu items as array. |
||
578 | * |
||
579 | * @return array |
||
580 | */ |
||
581 | public function toArray() |
||
582 | { |
||
583 | return $this->toCollection()->toArray(); |
||
584 | } |
||
585 | |||
586 | /** |
||
587 | * Enable menu ordering. |
||
588 | * |
||
589 | * @return self |
||
590 | */ |
||
591 | public function enableOrdering() |
||
592 | { |
||
593 | $this->ordering = true; |
||
594 | |||
595 | return $this; |
||
596 | } |
||
597 | |||
598 | /** |
||
599 | * Disable menu ordering. |
||
600 | * |
||
601 | * @return self |
||
602 | */ |
||
603 | public function disableOrdering() |
||
604 | { |
||
605 | $this->ordering = false; |
||
606 | |||
607 | return $this; |
||
608 | } |
||
609 | |||
610 | /** |
||
611 | * Get menu items and order it by 'order' key. |
||
612 | * |
||
613 | * @return array |
||
614 | */ |
||
615 | 3 | public function getOrderedItems() |
|
616 | { |
||
617 | 3 | if (config('menus.ordering') || $this->ordering) { |
|
618 | return $this->toCollection()->sortBy(function ($item) { |
||
619 | return $item->order; |
||
620 | })->all(); |
||
621 | } |
||
622 | |||
623 | 3 | return $this->items; |
|
624 | } |
||
625 | |||
626 | /** |
||
627 | * Render the menu. |
||
628 | * |
||
629 | * @return string |
||
630 | */ |
||
631 | 3 | protected function renderMenu() |
|
632 | { |
||
633 | 3 | $presenter = $this->getPresenter(); |
|
634 | 3 | $menu = $presenter->getOpenTagWrapper(); |
|
635 | |||
636 | 3 | foreach ($this->getOrderedItems() as $item) { |
|
637 | if ($item->hidden()) { |
||
638 | continue; |
||
639 | } |
||
640 | |||
641 | if ($item->hasSubMenu()) { |
||
642 | $menu .= $presenter->getMenuWithDropDownWrapper($item); |
||
643 | } elseif ($item->isHeader()) { |
||
644 | $menu .= $presenter->getHeaderWrapper($item); |
||
645 | } elseif ($item->isDivider()) { |
||
646 | $menu .= $presenter->getDividerWrapper(); |
||
647 | } else { |
||
648 | $menu .= $presenter->getMenuWithoutDropdownWrapper($item); |
||
649 | } |
||
650 | } |
||
651 | |||
652 | 3 | $menu .= $presenter->getCloseTagWrapper(); |
|
653 | |||
654 | 3 | return $menu; |
|
655 | } |
||
656 | } |
||
657 |
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.