GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#113)
by
unknown
01:55 queued 48s
created

Menu::sortMenu()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 8.9617
c 0
b 0
f 0
cc 6
nc 2
nop 0
1
<?php
2
3
namespace Spatie\Menu;
4
5
use ArrayIterator;
6
use Countable;
7
use IteratorAggregate;
8
use Spatie\Menu\Helpers\Reflection;
9
use Spatie\Menu\Html\Attributes;
10
use Spatie\Menu\Html\Tag;
11
use Spatie\Menu\Traits\Conditions as ConditionsTrait;
12
use Spatie\Menu\Traits\HasHtmlAttributes as HasHtmlAttributesTrait;
13
use Spatie\Menu\Traits\HasParentAttributes as HasParentAttributesTrait;
14
use Spatie\Menu\Traits\HasPriority as HasPriorityTrait;
15
use Spatie\Menu\Traits\HasTextAttributes as HasAttributesTrait;
16
use Traversable;
17
18
class Menu implements Item, Countable, HasHtmlAttributes, HasParentAttributes, IteratorAggregate
19
{
20
    use HasHtmlAttributesTrait, HasParentAttributesTrait, ConditionsTrait, HasAttributesTrait, HasPriorityTrait;
21
22
    /** @var array */
23
    protected $items = [];
24
25
    /** @var array */
26
    protected $filters = [];
27
28
    /** @var string */
29
    protected $prepend, $append = '';
30
31
    /** @var array */
32
    protected $wrap = [];
33
34
    /** @var string */
35
    protected $activeClass = 'active';
36
37
    /** @var string */
38
    protected $exactActiveClass = 'exact-active';
39
40
    /** @var string */
41
    protected $wrapperTagName = 'ul';
42
43
    /** @var bool */
44
    protected $parentTagName = 'li';
45
46
    /** @var bool */
47
    protected $activeClassOnParent = true;
48
49
    /** @var bool */
50
    protected $activeClassOnLink = false;
51
52
    /** @var \Spatie\Menu\Html\Attributes */
53
    protected $htmlAttributes, $parentAttributes;
54
55
    /** @var callable */
56
    protected $sortCallback;
57
58
    protected function __construct(Item ...$items)
59
    {
60
        $this->items = $items;
61
62
        $this->htmlAttributes = new Attributes();
63
        $this->parentAttributes = new Attributes();
64
    }
65
66
    /**
67
     * Create a new menu, optionally prefilled with items.
68
     *
69
     * @param array $items
70
     *
71
     * @return static
72
     */
73
    public static function new($items = [])
74
    {
75
        return new static(...array_values($items));
76
    }
77
78
    /**
79
     * Build a new menu from an array. The callback receives a menu instance as
80
     * the accumulator, the array item as the second parameter, and the item's
81
     * key as the third.
82
     *
83
     * @param array|\Iterator $items
84
     * @param callable $callback
85
     * @param \Spatie\Menu\Menu|null $initial
86
     *
87
     * @return static
88
     */
89
    public static function build($items, callable $callback, self $initial = null)
90
    {
91
        return ($initial ?: static::new())->fill($items, $callback);
92
    }
93
94
    /**
95
     * Fill a menu from an array. The callback receives a menu instance as
96
     * the accumulator, the array item as the second parameter, and the item's
97
     * key as the third.
98
     *
99
     * @param array|\Iterator $items
100
     * @param callable $callback
101
     *
102
     * @return static
103
     */
104
    public function fill($items, callable $callback)
105
    {
106
        $menu = $this;
107
108
        foreach ($items as $key => $item) {
109
            $menu = $callback($menu, $item, $key) ?: $menu;
110
        }
111
112
        return $menu;
113
    }
114
115
    /**
116
     * Add an item to the menu. This also applies all registered filters to the
117
     * item.
118
     *
119
     * @param \Spatie\Menu\Item $item
120
     *
121
     * @return $this
122
     */
123
    public function add(Item $item)
124
    {
125
        foreach ($this->filters as $filter) {
126
            $this->applyFilter($filter, $item);
127
        }
128
129
        $this->items[] = $item;
130
131
        return $this;
132
    }
133
134
    /**
135
     * Add an item to the menu if a (non-strict) condition is met.
136
     *
137
     * @param bool $condition
138
     * @param \Spatie\Menu\Item $item
139
     *
140
     * @return $this
141
     */
142
    public function addIf($condition, Item $item)
143
    {
144
        if ($this->resolveCondition($condition)) {
145
            $this->add($item);
146
        }
147
148
        return $this;
149
    }
150
151
    /**
152
     * Shortcut function to add a plain link to the menu.
153
     *
154
     * @param string $url
155
     * @param string $text
156
     *
157
     * @return $this
158
     */
159
    public function link(string $url, string $text)
160
    {
161
        return $this->add(Link::to($url, $text));
162
    }
163
164
    /**
165
     * Shortcut function to add an empty item to the menu.
166
     *
167
     * @return $this
168
     */
169
    public function empty()
170
    {
171
        return $this->add(Html::empty());
172
    }
173
174
    /**
175
     * Add a link to the menu if a (non-strict) condition is met.
176
     *
177
     * @param bool $condition
178
     * @param string $url
179
     * @param string $text
180
     *
181
     * @return $this
182
     */
183
    public function linkIf($condition, string $url, string $text)
184
    {
185
        if ($this->resolveCondition($condition)) {
186
            $this->link($url, $text);
187
        }
188
189
        return $this;
190
    }
191
192
    /**
193
     * Shortcut function to add raw html to the menu.
194
     *
195
     * @param string $html
196
     * @param array $parentAttributes
197
     *
198
     * @return $this
199
     */
200
    public function html(string $html, array $parentAttributes = [])
201
    {
202
        return $this->add(Html::raw($html)->setParentAttributes($parentAttributes));
203
    }
204
205
    /**
206
     * Add a chunk of html if a (non-strict) condition is met.
207
     *
208
     * @param bool $condition
209
     * @param string $html
210
     * @param array $parentAttributes
211
     *
212
     * @return $this
213
     */
214
    public function htmlIf($condition, string $html, array $parentAttributes = [])
215
    {
216
        if ($this->resolveCondition($condition)) {
217
            $this->html($html, $parentAttributes);
218
        }
219
220
        return $this;
221
    }
222
223
    /**
224
     * @param callable|\Spatie\Menu\Menu|\Spatie\Menu\Item $header
225
     * @param callable|\Spatie\Menu\Menu|null $menu
226
     *
227
     * @return $this
228
     */
229
    public function submenu($header, $menu = null)
230
    {
231
        [$header, $menu] = $this->parseSubmenuArgs(func_get_args());
232
233
        $menu = $this->createSubmenuMenu($menu);
0 ignored issues
show
Bug introduced by
It seems like $menu can also be of type null; however, Spatie\Menu\Menu::createSubmenuMenu() does only seem to accept callable, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
234
        $header = $this->createSubmenuHeader($header);
0 ignored issues
show
Bug introduced by
It seems like $header can also be of type callable; however, Spatie\Menu\Menu::createSubmenuHeader() does only seem to accept object<Spatie\Menu\Item>|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
235
236
        return $this->add($menu->prependIf($header, $header));
0 ignored issues
show
Documentation introduced by
$header is of type string, but the function expects a boolean.

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...
237
    }
238
239
    /**
240
     * @param bool $condition
241
     * @param callable|\Spatie\Menu\Menu|\Spatie\Menu\Item $header
242
     * @param callable|\Spatie\Menu\Menu|null $menu
243
     *
244
     * @return $this
245
     */
246
    public function submenuIf($condition, $header, $menu = null)
247
    {
248
        if ($condition) {
249
            $this->submenu($header, $menu);
250
        }
251
252
        return $this;
253
    }
254
255
    protected function parseSubmenuArgs($args): array
256
    {
257
        if (count($args) === 1) {
258
            return ['', $args[0]];
259
        }
260
261
        return [$args[0], $args[1]];
262
    }
263
264
    /**
265
     * @param \Spatie\Menu\Menu|callable $menu
266
     *
267
     * @return \Spatie\Menu\Menu
268
     */
269
    protected function createSubmenuMenu($menu): self
270
    {
271
        if (is_callable($menu)) {
272
            $transformer = $menu;
273
            $menu = $this->blueprint();
274
            $transformer($menu);
275
        }
276
277
        return $menu;
278
    }
279
280
    /**
281
     * @param \Spatie\Menu\Item|string $header
282
     *
283
     * @return string
284
     */
285
    protected function createSubmenuHeader($header): string
286
    {
287
        if ($header instanceof Item) {
288
            $header = $header->render();
289
        }
290
291
        return $header;
292
    }
293
294
    /**
295
     * Iterate over all the items and apply a callback. If you typehint the
296
     * item parameter in the callable, it wil only be applied to items of that
297
     * type.
298
     *
299
     * @param callable $callable
300
     *
301
     * @return $this
302
     */
303
    public function each(callable $callable)
304
    {
305
        $type = Reflection::firstParameterType($callable);
306
307
        foreach ($this->items as $item) {
308
            if (! Reflection::itemMatchesType($item, $type)) {
309
                continue;
310
            }
311
312
            $callable($item);
313
        }
314
315
        return $this;
316
    }
317
318
    /**
319
     * Register a filter to the menu. When an item is added, all filters will be
320
     * applied to the item. If you typehint the item parameter in the callable, it
321
     * will only be applied to items of that type.
322
     *
323
     * @param callable $callable
324
     *
325
     * @return $this
326
     */
327
    public function registerFilter(callable $callable)
328
    {
329
        $this->filters[] = $callable;
330
331
        return $this;
332
    }
333
334
    /**
335
     * Apply a filter to an item. Returns the result of the filter.
336
     *
337
     * @param callable $filter
338
     * @param \Spatie\Menu\Item $item
339
     */
340
    protected function applyFilter(callable $filter, Item $item)
341
    {
342
        $type = Reflection::firstParameterType($filter);
343
344
        if (! Reflection::itemMatchesType($item, $type)) {
345
            return;
346
        }
347
348
        $filter($item);
349
    }
350
351
    /**
352
     * Apply a callable to all existing items, and register it as a filter so it
353
     * will get applied to all new items too. If you typehint the item parameter
354
     * in the callable, it wil only be applied to items of that type.
355
     *
356
     * @param callable $callable
357
     *
358
     * @return $this
359
     */
360
    public function applyToAll(callable $callable)
361
    {
362
        $this->each($callable);
363
        $this->registerFilter($callable);
364
365
        return $this;
366
    }
367
368
    /**
369
     * Wrap the entire menu in an html element. This is another level of
370
     * wrapping above the `wrapperTag`.
371
     *
372
     * @param string $element
373
     * @param array $attributes
374
     *
375
     * @return $this
376
     */
377
    public function wrap(string $element, $attributes = [])
378
    {
379
        $this->wrap = [$element, $attributes];
380
381
        return $this;
382
    }
383
384
    /**
385
     * Determine whether the menu is active.
386
     *
387
     * @return bool
388
     */
389
    public function isActive(): bool
390
    {
391
        foreach ($this->items as $item) {
392
            if ($item->isActive()) {
393
                return true;
394
            }
395
        }
396
397
        return false;
398
    }
399
400
    /**
401
     * A menu can be active but not exact-active.
402
     *
403
     * @return bool
404
     */
405
    public function isExactActive(): bool
406
    {
407
        return false;
408
    }
409
410
    /**
411
     * Set multiple items in the menu as active based on a callable that filters
412
     * through items. If you typehint the item parameter in the callable, it will
413
     * only be applied to items of that type.
414
     *
415
     * @param callable|string $urlOrCallable
416
     * @param string $root
417
     *
418
     * @return $this
419
     */
420
    public function setActive($urlOrCallable, string $root = '/')
421
    {
422
        if (is_string($urlOrCallable)) {
423
            return $this->setActiveFromUrl($urlOrCallable, $root);
424
        }
425
426
        if (is_callable($urlOrCallable)) {
427
            return $this->setActiveFromCallable($urlOrCallable);
428
        }
429
430
        throw new \InvalidArgumentException('`setActive` requires a pattern or a callable');
431
    }
432
433
    /**
434
     * Set the class name that will be used on exact-active items for this menu.
435
     *
436
     * @param string $class
437
     *
438
     * @return $this
439
     */
440
    public function setExactActiveClass(string $class)
441
    {
442
        $this->exactActiveClass = $class;
443
444
        return $this;
445
    }
446
447
    /**
448
     * Set all relevant children active based on the current request's URL.
449
     *
450
     * /, /about, /contact => request to /about will set the about link active.
451
     *
452
     * /en, /en/about, /en/contact => request to /en won't set /en active if the
453
     *                                request root is set to /en.
454
     *
455
     * @param string $url  The current request url.
456
     * @param string $root If the link's URL is an exact match with the request
457
     *                     root, the link won't be set active. This behavior is
458
     *                     to avoid having home links active on every request.
459
     *
460
     * @return $this
461
     */
462
    public function setActiveFromUrl(string $url, string $root = '/')
463
    {
464
        $this->applyToAll(function (self $menu) use ($url, $root) {
465
            $menu->setActiveFromUrl($url, $root);
466
        });
467
468
        $this->applyToAll(function (Activatable $item) use ($url, $root) {
469
            $item->determineActiveForUrl($url, $root);
470
        });
471
472
        return $this;
473
    }
474
475
    /**
476
     * @param callable $callable
477
     *
478
     * @return $this
479
     */
480
    public function setActiveFromCallable(callable $callable)
481
    {
482
        $this->applyToAll(function (self $menu) use ($callable) {
483
            $menu->setActiveFromCallable($callable);
484
        });
485
486
        $type = Reflection::firstParameterType($callable);
487
488
        $this->applyToAll(function (Activatable $item) use ($callable, $type) {
489
            if (! Reflection::itemMatchesType($item, $type)) {
0 ignored issues
show
Documentation introduced by
$item is of type object<Spatie\Menu\Activatable>, but the function expects a object<Spatie\Menu\Item>.

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...
490
                return;
491
            }
492
493
            if ($callable($item)) {
494
                $item->setActive();
495
                $item->setExactActive();
496
            }
497
        });
498
499
        return $this;
500
    }
501
502
    /**
503
     * Set the class name that will be used on active items for this menu.
504
     *
505
     * @param string $class
506
     *
507
     * @return $this
508
     */
509
    public function setActiveClass(string $class)
510
    {
511
        $this->activeClass = $class;
512
513
        return $this;
514
    }
515
516
    /**
517
     * Add a class to all items in the menu.
518
     *
519
     * @param string $class
520
     *
521
     * @return $this
522
     */
523
    public function addItemClass(string $class)
524
    {
525
        $this->applyToAll(function (HasHtmlAttributes $link) use ($class) {
526
            $link->addClass($class);
527
        });
528
529
        return $this;
530
    }
531
532
    /**
533
     * Set an attribute on all items in the menu.
534
     *
535
     * @param string $attribute
536
     * @param string $value
537
     *
538
     * @return $this
539
     */
540
    public function setItemAttribute(string $attribute, string $value = '')
541
    {
542
        $this->applyToAll(function (HasHtmlAttributes $link) use ($attribute, $value) {
543
            $link->setAttribute($attribute, $value);
544
        });
545
546
        return $this;
547
    }
548
549
    /**
550
     * Add a parent class to all items in the menu.
551
     *
552
     * @param string $class
553
     *
554
     * @return $this
555
     */
556
    public function addItemParentClass(string $class)
557
    {
558
        $this->applyToAll(function (HasParentAttributes $item) use ($class) {
559
            $item->addParentClass($class);
560
        });
561
562
        return $this;
563
    }
564
565
    /**
566
     * Add a parent attribute to all items in the menu.
567
     *
568
     * @param string $attribute
569
     * @param string $value
570
     *
571
     * @return $this
572
     */
573
    public function setItemParentAttribute(string $attribute, string $value = '')
574
    {
575
        $this->applyToAll(function (HasParentAttributes $item) use ($attribute, $value) {
576
            $item->setParentAttribute($attribute, $value);
577
        });
578
579
        return $this;
580
    }
581
582
    /**
583
     * Set tag for items wrapper.
584
     *
585
     * @param string|null $wrapperTagName
586
     * @return $this
587
     */
588
    public function setWrapperTag($wrapperTagName = null)
589
    {
590
        $this->wrapperTagName = $wrapperTagName;
591
592
        return $this;
593
    }
594
595
    /**
596
     * Set tag for items wrapper.
597
     *
598
     * @param string|null $wrapperTagName
0 ignored issues
show
Bug introduced by
There is no parameter named $wrapperTagName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
599
     * @return $this
600
     */
601
    public function withoutWrapperTag()
602
    {
603
        $this->wrapperTagName = null;
604
605
        return $this;
606
    }
607
608
    /**
609
     * Set the parent tag name.
610
     *
611
     * @param string|null $parentTagName
612
     * @return $this
613
     */
614
    public function setParentTag($parentTagName = null)
615
    {
616
        $this->parentTagName = $parentTagName;
0 ignored issues
show
Documentation Bug introduced by
It seems like $parentTagName can also be of type string. However, the property $parentTagName is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
617
618
        return $this;
619
    }
620
621
    /**
622
     * Render items without a parent tag.
623
     *
624
     * @return $this
625
     */
626
    public function withoutParentTag()
627
    {
628
        $this->parentTagName = null;
629
630
        return $this;
631
    }
632
633
    /**
634
     * Set whether active class should (also) be on link.
635
     *
636
     * @param $activeClassOnLink
637
     * @return $this
638
     */
639
    public function setActiveClassOnLink(bool $activeClassOnLink = true)
640
    {
641
        $this->activeClassOnLink = $activeClassOnLink;
642
643
        return $this;
644
    }
645
646
    /**
647
     * Set whether active class should (also) be on parent.
648
     *
649
     * @param $activeClassOnParent
650
     * @return $this
651
     */
652
    public function setActiveClassOnParent(bool $activeClassOnParent = true)
653
    {
654
        $this->activeClassOnParent = $activeClassOnParent;
655
656
        return $this;
657
    }
658
659
    /**
660
     * @param bool $condition
661
     * @param callable $callable
662
     *
663
     * @return $this
664
     */
665
    public function if(bool $condition, callable $callable)
666
    {
667
        return $condition ? $callable($this) : $this;
668
    }
669
670
    /**
671
     * Create a empty blueprint of the menu (copies `filters` and `activeClass`).
672
     *
673
     * @return static
674
     */
675
    public function blueprint()
676
    {
677
        $clone = new static();
678
679
        $clone->filters = $this->filters;
680
        $clone->activeClass = $this->activeClass;
681
682
        return $clone;
683
    }
684
685
    /**
686
     * Set the function to sort the menu.
687
     *
688
     * @param callable $callable
689
     * @return $this
690
     */
691
    public function setSortcallback($callable)
692
    {
693
        $this->sortCallback = $callable;
694
695
        return $this;
696
    }
697
698
    /**
699
     * Sorts the menu base on its priority using the sortCallback.
700
     *
701
     * @return
702
     */
703
    protected function sortMenu()
704
    {
705
        if (!is_callable($this->sortCallback)) {
706
            $this->sortCallback = function ($a, $b) {
707
                /**
708
                 * Avoid breaking previous version.
709
                 */
710
                if (! method_exists($a, 'getPriority') || ! method_exists($b, 'getPriority')) {
711
                    return 0;
712
                }
713
714
                if ($a->getPriority() == $b->getPriority()) {
715
                    return 0;
716
                }
717
718
                return $a->getPriority() < $b->getPriority() ? -1 : 1;
719
            };
720
        }
721
722
        uasort($this->items, $this->sortCallback);
723
    }
724
725
    /**
726
     * Render the menu.
727
     *
728
     * @return string
729
     */
730
    public function render(): string
731
    {
732
        $this->sortMenu();
733
734
        $tag = $this->wrapperTagName
735
            ? new Tag($this->wrapperTagName, $this->htmlAttributes)
736
            : null;
737
738
        $contents = array_map([$this, 'renderItem'], $this->items);
739
740
        $wrappedContents = $tag ? $tag->withContents($contents) : implode('', $contents);
741
742
        $menu = $this->prepend.$wrappedContents.$this->append;
743
744
        if (! empty($this->wrap)) {
745
            return Tag::make($this->wrap[0], new Attributes($this->wrap[1]))->withContents($menu);
746
        }
747
748
        return $menu;
749
    }
750
751
    protected function renderItem(Item $item): string
752
    {
753
        $attributes = new Attributes();
754
755
        if (method_exists($item, 'beforeRender')) {
756
            $item->beforeRender();
0 ignored issues
show
Bug introduced by
The method beforeRender() does not exist on Spatie\Menu\Item. Did you maybe mean render()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
757
        }
758
759
        if (method_exists($item, 'willRender') && $item->willRender() === false) {
0 ignored issues
show
Bug introduced by
The method willRender() does not exist on Spatie\Menu\Item. Did you maybe mean render()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
760
            return '';
761
        }
762
763
        if ($item->isActive()) {
764
            if ($this->activeClassOnParent) {
765
                $attributes->addClass($this->activeClass);
766
767
                if ($item->isExactActive()) {
768
                    $attributes->addClass($this->exactActiveClass);
769
                }
770
            }
771
772
            if ($this->activeClassOnLink && $item instanceof HasHtmlAttributes) {
773
                $item->addClass($this->activeClass);
774
775
                if ($item->isExactActive()) {
776
                    $item->addClass($this->exactActiveClass);
777
                }
778
            }
779
        }
780
781
        if ($item instanceof HasParentAttributes) {
782
            $attributes->setAttributes($item->parentAttributes());
783
        }
784
785
        if (! $this->parentTagName) {
786
            return $item->render();
787
        }
788
789
        return Tag::make($this->parentTagName, $attributes)->withContents($item->render());
0 ignored issues
show
Documentation introduced by
$this->parentTagName is of type boolean, but the function expects a string.

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...
790
    }
791
792
    /**
793
     * The amount of items in the menu.
794
     *
795
     * @return int
796
     */
797
    public function count(): int
798
    {
799
        return count($this->items);
800
    }
801
802
    /**
803
     * @return string
804
     */
805
    public function __toString(): string
806
    {
807
        return $this->render();
808
    }
809
810
    public function getIterator(): Traversable
811
    {
812
        return new ArrayIterator($this->items);
813
    }
814
}
815