Passed
Push — master ( 7929d2...3112d2 )
by Caen
03:30 queued 12s
created

FindsNavigationDataForPage::makeNavigationData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 4
dl 0
loc 7
rs 10
1
<?php
2
3
namespace Hyde\Framework\Actions\Constructors;
4
5
use Hyde\Framework\Concerns\HydePage;
6
use Hyde\Framework\Contracts\FrontMatter\DocumentationPageSchema;
7
use Hyde\Framework\Models\Navigation\NavigationData;
8
use Hyde\Framework\Models\Pages\DocumentationPage;
9
use Hyde\Framework\Models\Pages\MarkdownPost;
10
use Illuminate\Support\Str;
11
12
/**
13
 * Helper for HydePages to discover data used for navigation menus and the documentation sidebar.
14
 *
15
 * @internal
16
 *
17
 * @see \Hyde\Framework\Testing\Feature\PageModelConstructorsTest
18
 * @see \Hyde\Framework\Concerns\HydePage
19
 */
20
final class FindsNavigationDataForPage
21
{
22
    protected const FALLBACK_PRIORITY = 999;
23
    protected const CONFIG_OFFSET = 500;
24
25
    public static function run(HydePage $page): NavigationData
26
    {
27
        return (new self($page))->constructNavigationData();
28
    }
29
30
    protected function __construct(protected HydePage $page)
31
    {
32
    }
33
34
    protected function constructNavigationData(): NavigationData
35
    {
36
        if ($this->page instanceof DocumentationPageSchema) {
37
            return $this->makeNavigationData(
38
                $this->findNavigationMenuLabel(),
39
                $this->findNavigationMenuHidden(),
40
                $this->page->matter('navigation.priority', $this->findNavigationMenuPriority()),
41
                $this->getDocumentationPageGroup()
42
            );
43
        }
44
45
        return $this->makeNavigationData(
46
            $this->findNavigationMenuLabel(),
47
            $this->findNavigationMenuHidden(),
48
            $this->findNavigationMenuPriority(),
49
        );
50
    }
51
52
    private function makeNavigationData(string $label, bool $hidden, int $priority, ?string $group = null): NavigationData
53
    {
54
        return NavigationData::make([
55
            'label' => $label,
56
            'group' => $group,
57
            'hidden' => $hidden,
58
            'priority' => $priority,
59
        ]);
60
    }
61
62
    private function findNavigationMenuLabel(): string
63
    {
64
        if ($this->page->matter('navigation.label') !== null) {
65
            return $this->page->matter('navigation.label');
66
        }
67
68
        if (isset($this->getNavigationLabelConfig()[$this->page->routeKey])) {
69
            return $this->getNavigationLabelConfig()[$this->page->routeKey];
70
        }
71
72
        return $this->page->matter('title') ?? $this->page->title;
73
    }
74
75
    private function findNavigationMenuHidden(): bool
76
    {
77
        if ($this->page instanceof MarkdownPost) {
78
            return true;
79
        }
80
81
        if ($this->page->matter('navigation.hidden', false)) {
82
            return true;
83
        }
84
85
        if (in_array($this->page->routeKey, config('hyde.navigation.exclude', ['404']))) {
86
            return true;
87
        }
88
89
        return false;
90
    }
91
92
    private function findNavigationMenuPriority(): int
93
    {
94
        if ($this->page->matter('navigation.priority') !== null) {
95
            return $this->page->matter('navigation.priority');
96
        }
97
98
        // Different default return values are to preserve backwards compatibility
99
        return $this->page instanceof DocumentationPage
100
            ? $this->findNavigationMenuPriorityInSidebarConfig(array_flip(config('docs.sidebar_order', []))) ?? self::FALLBACK_PRIORITY
101
            : $this->findNavigationMenuPriorityInNavigationConfig(config('hyde.navigation.order', [])) ?? self::FALLBACK_PRIORITY;
102
    }
103
104
    private function findNavigationMenuPriorityInNavigationConfig(array $config): ?int
105
    {
106
        return array_key_exists($this->page->routeKey, $config) ? (int) $config[$this->page->routeKey] : null;
107
    }
108
109
    private function findNavigationMenuPriorityInSidebarConfig(array $config): ?int
110
    {
111
        // Sidebars uses a special syntax where the keys are just the page identifiers in a flat array
112
113
        // Adding 250 makes so that pages with a front matter priority that is lower can be shown first.
114
        // It's lower than the fallback of 500 so that the config ones still come first.
115
        // This is all to make it easier to mix ways of adding priorities.
116
117
        return isset($config[$this->page->identifier])
118
            ? $config[$this->page->identifier] + (self::CONFIG_OFFSET)
119
            : null;
120
    }
121
122
    private function getNavigationLabelConfig(): array
123
    {
124
        return array_merge([
125
            'index' => 'Home',
126
            'docs/index' => 'Docs',
127
        ], config('hyde.navigation.labels', []));
128
    }
129
130
    private function getDocumentationPageGroup(): ?string
131
    {
132
        // If the documentation page is in a subdirectory,
133
        return str_contains($this->page->identifier, '/')
134
            // then we can use that as the category name.
135
            ? Str::before($this->page->identifier, '/')
136
            // Otherwise, we look in the front matter.
137
            : $this->page->matter('navigation.group', 'other');
138
    }
139
}
140