Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
12 / 12
CRAP
100.00% covered (success)
100.00%
1 / 1
NavItem
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
12 / 12
14
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 fromRoute
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 forLink
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forRoute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDestination
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLabel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPriority
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isCurrent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRouteGroup
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 normalizeGroupKey
100.00% covered (success)
100.00%
1 / 1
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\Foundation\Facades\Routes;
8use Hyde\Hyde;
9use Hyde\Support\Models\Route;
10use Stringable;
11
12/**
13 * Abstraction for a navigation menu item. Used by the NavigationMenu and DocumentationSidebar classes.
14 *
15 * You have a few options to construct a navigation menu item:
16 *   1. You can supply a Route directly and explicit properties to the constructor
17 *   2. You can use NavItem::fromRoute() to use data from the route
18 *   3. You can use NavItem::forLink() for an external or un-routed link
19 */
20class NavItem implements Stringable
21{
22    public readonly string $destination;
23    public readonly string $label;
24    public readonly int $priority;
25    public readonly ?string $group;
26
27    /**
28     * Create a new navigation menu item.
29     */
30    public function __construct(Route|string $destination, string $label, int $priority = 500, ?string $group = null)
31    {
32        $this->destination = (string) $destination;
33        $this->label = $label;
34        $this->priority = $priority;
35        $this->group = $group;
36    }
37
38    /**
39     * Create a new navigation menu item from a route.
40     */
41    public static function fromRoute(Route $route, ?string $label = null, ?int $priority = null, ?string $group = null): static
42    {
43        return new static(
44            $route->getLink(),
45            $label ?? $route->getPage()->navigationMenuLabel(),
46            $priority ?? $route->getPage()->navigationMenuPriority(),
47            $group ?? static::getRouteGroup($route),
48        );
49    }
50
51    /**
52     * Create a new navigation menu item leading to an external URI.
53     */
54    public static function forLink(string $href, string $label, int $priority = 500): static
55    {
56        return new static($href, $label, $priority);
57    }
58
59    /**
60     * Create a new navigation menu item leading to a Route model.
61     *
62     * @param  \Hyde\Support\Models\Route|string<\Hyde\Support\Models\RouteKey>  $route  Route model or route key
63     * @param  int|null  $priority  Leave blank to use the priority of the route's corresponding page.
64     * @param  string|null  $label  Leave blank to use the label of the route's corresponding page.
65     * @param  string|null  $group  Leave blank to use the group of the route's corresponding page.
66     */
67    public static function forRoute(Route|string $route, ?string $label = null, ?int $priority = null, ?string $group = null): static
68    {
69        return static::fromRoute($route instanceof Route ? $route : Routes::getOrFail($route), $label, $priority, $group);
70    }
71
72    /**
73     * Resolve a link to the navigation item.
74     */
75    public function __toString(): string
76    {
77        return $this->destination;
78    }
79
80    /**
81     * Get the destination link of the navigation item.
82     *
83     * If the navigation item is an external link, this will return the link as is,
84     * if it's for a route, a resolved relative link will be returned.
85     */
86    public function getDestination(): string
87    {
88        return $this->destination;
89    }
90
91    /**
92     * Get the label of the navigation item.
93     */
94    public function getLabel(): string
95    {
96        return $this->label;
97    }
98
99    /**
100     * Get the priority to determine the order of the navigation item.
101     */
102    public function getPriority(): int
103    {
104        return $this->priority;
105    }
106
107    /**
108     * Get the group identifier of the navigation item, if any.
109     *
110     * For sidebars this is the category key, for navigation menus this is the dropdown key.
111     */
112    public function getGroup(): ?string
113    {
114        return $this->group;
115    }
116
117    /**
118     * Check if the NavItem instance is the current page.
119     */
120    public function isCurrent(): bool
121    {
122        return Hyde::currentRoute()->getLink() === $this->destination;
123    }
124
125    protected static function getRouteGroup(Route $route): ?string
126    {
127        /** @var string|null $group */
128        $group = $route->getPage()->data('navigation.group');
129
130        return static::normalizeGroupKey($group);
131    }
132
133    protected static function normalizeGroupKey(?string $group): ?string
134    {
135        return $group ? Hyde::makeSlug($group) : null;
136    }
137}