Skip to content

Commit 59dd7b7

Browse files
authored
Merge pull request #751 from hydephp/refactor-navigation-data
Refactor the navigation data factory
2 parents 916e404 + a7e292f commit 59dd7b7

File tree

7 files changed

+102
-71
lines changed

7 files changed

+102
-71
lines changed

config/docs.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
| default to sort alphabetically. You can reorder the page identifiers
7575
| in the list below, and the links will get sorted in that order.
7676
|
77-
| Internally, the items listed will get a position priority of 250 + the order its found in the list.
77+
| Internally, the items listed will get a position priority of 500 + the order its found in the list.
7878
| Link items without an entry here will have fall back to the default priority of 999, putting them last.
7979
|
8080
| You can also set explicit priorities in front matter.

config/hyde.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
// This configuration sets the priorities used to determine the order of the menu.
154154
// The default values have been added below for reference and easy editing.
155155
// The array key should match the page's route key (slug).
156+
// Lower values show up first in the menu.
156157
'order' => [
157158
'index' => 0,
158159
'posts' => 10,
@@ -162,8 +163,8 @@
162163
// In case you want to customize the labels for the menu items, you can do so here.
163164
// Simply add the route key (slug) as the key, and the label as the value.
164165
'labels' => [
165-
// 'index' => 'Start',
166-
// 'docs/index' => 'Documentation',
166+
'index' => 'Home',
167+
'docs/index' => 'Docs',
167168
],
168169

169170
// These are the pages that should not show up in the navigation menu.

packages/framework/config/docs.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
| default to sort alphabetically. You can reorder the page identifiers
7575
| in the list below, and the links will get sorted in that order.
7676
|
77-
| Internally, the items listed will get a position priority of 250 + the order its found in the list.
77+
| Internally, the items listed will get a position priority of 500 + the order its found in the list.
7878
| Link items without an entry here will have fall back to the default priority of 999, putting them last.
7979
|
8080
| You can also set explicit priorities in front matter.

packages/framework/config/hyde.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
// This configuration sets the priorities used to determine the order of the menu.
154154
// The default values have been added below for reference and easy editing.
155155
// The array key should match the page's route key (slug).
156+
// Lower values show up first in the menu.
156157
'order' => [
157158
'index' => 0,
158159
'posts' => 10,
@@ -162,8 +163,8 @@
162163
// In case you want to customize the labels for the menu items, you can do so here.
163164
// Simply add the route key (slug) as the key, and the label as the value.
164165
'labels' => [
165-
// 'index' => 'Start',
166-
// 'docs/index' => 'Documentation',
166+
'index' => 'Home',
167+
'docs/index' => 'Docs',
167168
],
168169

169170
// These are the pages that should not show up in the navigation menu.

packages/framework/src/Framework/Factories/NavigationDataFactory.php

Lines changed: 79 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
namespace Hyde\Framework\Factories;
66

77
use function array_flip;
8-
use function array_key_exists;
9-
use function array_merge;
108
use function config;
119
use Hyde\Framework\Concerns\InteractsWithFrontMatter;
1210
use Hyde\Framework\Factories\Concerns\CoreDataObject;
1311
use Hyde\Markdown\Contracts\FrontMatter\SubSchemas\NavigationSchema;
1412
use Hyde\Markdown\Models\FrontMatter;
1513
use Hyde\Pages\DocumentationPage;
1614
use Hyde\Pages\MarkdownPost;
15+
use Illuminate\Support\Arr;
1716
use Illuminate\Support\Str;
1817
use function in_array;
1918
use function is_a;
@@ -71,115 +70,132 @@ public function toArray(): array
7170

7271
protected function makeLabel(): ?string
7372
{
74-
return $this->matter('navigation.label')
73+
return $this->searchForLabelInFrontMatter()
7574
?? $this->searchForLabelInConfig()
7675
?? $this->matter('title')
7776
?? $this->title;
7877
}
7978

8079
protected function makeGroup(): ?string
8180
{
82-
if ($this->isInstanceOf(DocumentationPage::class)) {
83-
return $this->getDocumentationPageGroup();
84-
}
85-
86-
if (Str::contains($this->identifier, '/') && $this->getSubdirectoryConfiguration() === 'dropdown') {
87-
return Str::before($this->identifier, '/');
81+
if ($this->pageIsInSubdirectory() && $this->canUseSubdirectoryForGroups()) {
82+
return $this->getSubdirectoryName();
8883
}
8984

90-
// TODO Check in front matter for group?
91-
92-
return null;
85+
return $this->searchForGroupInFrontMatter() ?? $this->defaultGroup();
9386
}
9487

9588
protected function makeHidden(): ?bool
9689
{
97-
if ($this->isInstanceOf(MarkdownPost::class)) {
98-
return true;
99-
}
90+
return $this->isInstanceOf(MarkdownPost::class)
91+
|| $this->searchForHiddenInFrontMatter()
92+
|| in_array($this->routeKey, config('hyde.navigation.exclude', ['404']))
93+
|| $this->pageIsInSubdirectory() && ($this->getSubdirectoryConfiguration() === 'hidden');
94+
}
10095

101-
if ($this->matter('navigation.hidden', false)) {
102-
return true;
103-
}
96+
protected function makePriority(): int
97+
{
98+
return $this->searchForPriorityInFrontMatter()
99+
?? $this->searchForPriorityInConfigs()
100+
?? self::FALLBACK_PRIORITY;
101+
}
104102

105-
if (in_array($this->routeKey, config('hyde.navigation.exclude', ['404']))) {
106-
return true;
107-
}
103+
private function searchForLabelInFrontMatter(): ?string
104+
{
105+
return $this->matter('navigation.label')
106+
?? $this->matter('navigation.title');
107+
}
108108

109-
if (Str::contains($this->identifier, '/') && $this->getSubdirectoryConfiguration() === 'hidden') {
110-
return true;
111-
}
109+
private function searchForGroupInFrontMatter(): ?string
110+
{
111+
return $this->matter('navigation.group')
112+
?? $this->matter('navigation.category');
113+
}
112114

113-
return false;
115+
private function searchForHiddenInFrontMatter(): ?bool
116+
{
117+
return $this->matter('navigation.hidden')
118+
?? $this->invert($this->matter('navigation.visible'));
114119
}
115120

116-
protected function makePriority(): ?int
121+
private function searchForPriorityInFrontMatter(): ?int
117122
{
118-
if ($this->matter('navigation.priority') !== null) {
119-
return $this->matter('navigation.priority');
120-
}
123+
return $this->matter('navigation.priority')
124+
?? $this->matter('navigation.order');
125+
}
121126

122-
return $this->isInstanceOf(DocumentationPage::class)
123-
? $this->findPriorityInSidebarConfig(array_flip(config('docs.sidebar_order', []))) ?? self::FALLBACK_PRIORITY
124-
: $this->findPriorityInNavigationConfig(config('hyde.navigation.order', [])) ?? self::FALLBACK_PRIORITY;
127+
private function searchForLabelInConfig(): ?string
128+
{
129+
return Arr::get(config('hyde.navigation.labels', [
130+
'index' => 'Home',
131+
'docs/index' => 'Docs',
132+
]), $this->routeKey);
125133
}
126134

127-
private function findPriorityInNavigationConfig(array $config): ?int
135+
private function searchForPriorityInConfigs(): ?int
128136
{
129-
return array_key_exists($this->routeKey, $config) ? (int) $config[$this->routeKey] : null;
137+
return $this->isInstanceOf(DocumentationPage::class)
138+
? $this->searchForPriorityInSidebarConfig()
139+
: $this->searchForPriorityInNavigationConfig();
130140
}
131141

132-
private function findPriorityInSidebarConfig(array $config): ?int
142+
private function searchForPriorityInSidebarConfig(): ?int
133143
{
134-
// Sidebars uses a special syntax where the keys are just the page identifiers in a flat array
144+
// Sidebars uses a special syntax where the keys are just the page identifiers in a flat array.
145+
// TODO: In the future we could normalize this with the standard navigation config so both strategies can be auto-detected and used.
135146

136-
// Adding 250 makes so that pages with a front matter priority that is lower can be shown first.
137-
// It's lower than the fallback of 500 so that the config ones still come first.
147+
// Adding an offset makes so that pages with a front matter priority that is lower can be shown first.
138148
// This is all to make it easier to mix ways of adding priorities.
139149

140-
return isset($config[$this->identifier])
141-
? $config[$this->identifier] + (self::CONFIG_OFFSET)
142-
: null;
150+
return $this->offset(Arr::get(
151+
array_flip(config('docs.sidebar_order', [])), $this->identifier),
152+
self::CONFIG_OFFSET
153+
);
143154
}
144155

145-
private function getDocumentationPageGroup(): ?string
156+
private function searchForPriorityInNavigationConfig(): ?int
146157
{
147-
// If the documentation page is in a subdirectory,
148-
return str_contains($this->identifier, '/')
149-
// then we can use that as the category name.
150-
? Str::before($this->identifier, '/')
151-
// Otherwise, we look in the front matter.
152-
: $this->findGroupFromMatter();
158+
return config("hyde.navigation.order.$this->routeKey");
153159
}
154160

155-
protected function searchForLabelInConfig(): ?string
161+
private function canUseSubdirectoryForGroups(): bool
156162
{
157-
$labelConfig = array_merge([
158-
'index' => 'Home',
159-
'docs/index' => 'Docs',
160-
], config('hyde.navigation.labels', []));
163+
return $this->getSubdirectoryConfiguration() === 'dropdown'
164+
|| $this->isInstanceOf(DocumentationPage::class);
165+
}
161166

162-
if (isset($labelConfig[$this->routeKey])) {
163-
return $labelConfig[$this->routeKey];
164-
}
167+
private function defaultGroup(): ?string
168+
{
169+
return $this->isInstanceOf(DocumentationPage::class) ? 'other' : null;
170+
}
165171

166-
return null;
172+
private function pageIsInSubdirectory(): bool
173+
{
174+
return Str::contains($this->identifier, '/');
175+
}
176+
177+
private function getSubdirectoryName(): string
178+
{
179+
return Str::before($this->identifier, '/');
180+
}
181+
182+
protected function getSubdirectoryConfiguration(): string
183+
{
184+
return config('hyde.navigation.subdirectories', 'hidden');
167185
}
168186

169187
protected function isInstanceOf(string $class): bool
170188
{
171189
return is_a($this->pageClass, $class, true);
172190
}
173191

174-
protected function findGroupFromMatter(): mixed
192+
protected function invert(?bool $value): ?bool
175193
{
176-
return $this->matter('navigation.group')
177-
?? $this->matter('navigation.category')
178-
?? 'other';
194+
return $value === null ? null : ! $value;
179195
}
180196

181-
protected static function getSubdirectoryConfiguration(): string
197+
protected function offset(?int $value, int $offset): ?int
182198
{
183-
return config('hyde.navigation.subdirectories', 'hidden');
199+
return $value === null ? null : $value + $offset;
184200
}
185201
}

packages/framework/src/Markdown/Contracts/FrontMatter/SubSchemas/NavigationSchema.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface NavigationSchema
1313
public const NAVIGATION_SCHEMA = [
1414
'label' => 'string',
1515
'group' => 'string', // Category is also supported
16-
'hidden' => 'bool',
17-
'priority' => 'int',
16+
'hidden' => 'bool', // Visible is also supported (but obviously invert the value)
17+
'priority' => 'int', // Order is also supported
1818
];
1919
}

packages/framework/tests/Feature/HydePageTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,13 @@ public function test_show_in_navigation_returns_false_for_abstract_markdown_page
553553
$this->assertFalse($page->showInNavigation());
554554
}
555555

556+
public function test_show_in_navigation_returns_true_for_abstract_markdown_page_if_matter_navigation_visible_is_true()
557+
{
558+
$page = MarkdownPage::make('foo', ['navigation.visible' => true]);
559+
560+
$this->assertTrue($page->showInNavigation());
561+
}
562+
556563
public function test_show_in_navigation_returns_true_for_abstract_markdown_page_if_matter_navigation_hidden_is_false()
557564
{
558565
$page = MarkdownPage::make('foo', ['navigation.hidden' => false]);
@@ -595,6 +602,12 @@ public function test_navigation_menu_priority_returns_front_matter_value_of_navi
595602
$this->assertEquals(1, $page->navigationMenuPriority());
596603
}
597604

605+
public function test_navigation_menu_priority_can_be_set_using_order_property()
606+
{
607+
$page = MarkdownPage::make('foo', ['navigation.order' => 1]);
608+
$this->assertEquals(1, $page->navigationMenuPriority());
609+
}
610+
598611
public function test_navigation_menu_priority_returns_specified_config_value_if_slug_exists_in_config_hyde_navigation_order()
599612
{
600613
$page = MarkdownPage::make('foo');

0 commit comments

Comments
 (0)