Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
NavigationMenu
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
8 / 8
18
100.00% covered (success)
100.00%
1 / 1
 generate
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasDropdowns
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getDropdowns
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 moveGroupedItemsIntoDropdowns
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 canAddRoute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 canAddItemToDropdown
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 dropdownsEnabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 hasGroupExplicitlySetInFrontMatter
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Framework\Features\Navigation;
6
7use Hyde\Facades\Config;
8use Hyde\Support\Models\Route;
9use Hyde\Pages\DocumentationPage;
10use BadMethodCallException;
11
12class NavigationMenu extends BaseNavigationMenu
13{
14    private bool $hasDropdowns;
15
16    protected function generate(): void
17    {
18        parent::generate();
19
20        if ($this->dropdownsEnabled()) {
21            $this->moveGroupedItemsIntoDropdowns();
22        }
23    }
24
25    public function hasDropdowns(): bool
26    {
27        return $this->dropdownsEnabled() && count($this->getDropdowns()) >= 1;
28    }
29
30    /** @return array<string, DropdownNavItem> */
31    public function getDropdowns(): array
32    {
33        if (! $this->dropdownsEnabled()) {
34            throw new BadMethodCallException('Dropdowns are not enabled. Enable it by setting `hyde.navigation.subdirectories` to `dropdown`.');
35        }
36
37        return $this->items->filter(function (NavItem $item): bool {
38            return $item instanceof DropdownNavItem;
39        })->values()->all();
40    }
41
42    protected function moveGroupedItemsIntoDropdowns(): void
43    {
44        $dropdowns = [];
45
46        foreach ($this->items as $key => $item) {
47            if ($this->canAddItemToDropdown($item)) {
48                // Buffer the item in the dropdowns array
49                $dropdowns[$item->getGroup()][] = $item;
50
51                // Remove the item from the main items collection
52                $this->items->forget($key);
53            }
54        }
55
56        foreach ($dropdowns as $group => $items) {
57            // Create a new dropdown item containing the buffered items
58            $this->items->add(new DropdownNavItem($group, $items));
59        }
60    }
61
62    protected function canAddRoute(Route $route): bool
63    {
64        return parent::canAddRoute($route) && (! $route->getPage() instanceof DocumentationPage || $route->is(DocumentationPage::homeRouteName()));
65    }
66
67    protected function canAddItemToDropdown(NavItem $item): bool
68    {
69        return $item->getGroup() !== null;
70    }
71
72    protected function dropdownsEnabled(): bool
73    {
74        return (Config::getString('hyde.navigation.subdirectories', 'hidden') === 'dropdown') || $this->hasGroupExplicitlySetInFrontMatter();
75    }
76
77    private function hasGroupExplicitlySetInFrontMatter(): bool
78    {
79        return $this->hasDropdowns ??= $this->items->contains(function (NavItem $item): bool {
80            return ($item->getGroup() !== null) && ($item->destination !== (string) DocumentationPage::home());
81        });
82    }
83}