From afdb70b6ee48276c84f881f80b621d5815e04178 Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 1 Oct 2024 12:28:08 -0500 Subject: [PATCH 1/8] =?UTF-8?q?=E2=9C=A8=20Add=20a=20`navi:list`=20command?= =?UTF-8?q?=20to=20show=20registered=20navigation=20menus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Console/NaviListCommand.php | 48 +++++++++++++++++++++++++++ src/Providers/NaviServiceProvider.php | 5 +-- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/Console/NaviListCommand.php diff --git a/src/Console/NaviListCommand.php b/src/Console/NaviListCommand.php new file mode 100644 index 0000000..424dc8a --- /dev/null +++ b/src/Console/NaviListCommand.php @@ -0,0 +1,48 @@ +map(fn ($label, $value) => $menus->firstWhere('term_id', $locations->get($value))) + ->map(fn ($menu, $location) => collect([ + $location, + $menu?->name ?? 'Unassigned', + $menu?->count ?? 0, + ])->map(fn ($value) => $menu?->name ? $value : "{$value}")); + + $this->table([ + 'Location', + 'Assigned Menu', + 'Menu Items', + ], $rows, tableStyle: 'box'); + } +} diff --git a/src/Providers/NaviServiceProvider.php b/src/Providers/NaviServiceProvider.php index 08b2ce1..eb7c23e 100644 --- a/src/Providers/NaviServiceProvider.php +++ b/src/Providers/NaviServiceProvider.php @@ -3,7 +3,7 @@ namespace Log1x\Navi\Providers; use Illuminate\Support\ServiceProvider; -use Log1x\Navi\Console\NaviMakeCommand; +use Log1x\Navi\Console; use Log1x\Navi\Navi; class NaviServiceProvider extends ServiceProvider @@ -27,7 +27,8 @@ public function boot() { if ($this->app->runningInConsole()) { $this->commands([ - NaviMakeCommand::class, + Console\NaviListCommand::class, + Console\NaviMakeCommand::class, ]); } } From 99cad9653be045c38b885201382adb56353e917a Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 1 Oct 2024 12:28:22 -0500 Subject: [PATCH 2/8] =?UTF-8?q?=E2=9E=95=20Add=20`roots/acorn`=20to=20the?= =?UTF-8?q?=20project=20in=20development?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 310cd8b..3da0252 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,8 @@ "php": "^8.0" }, "require-dev": { - "laravel/pint": "^1.14" + "laravel/pint": "^1.14", + "roots/acorn": "^4.3" }, "extra": { "acorn": { From 5b95f768dadc8a35d4e79b8576829204c0ca7fdf Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 1 Oct 2024 12:29:24 -0500 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20Improve?= =?UTF-8?q?=20the=20`navi:make`=20command=20output=20=F0=9F=9A=9A=20Change?= =?UTF-8?q?=20the=20`make:navi`=20command=20signature=20to=20`navi:make`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Console/NaviMakeCommand.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Console/NaviMakeCommand.php b/src/Console/NaviMakeCommand.php index 85867e4..c56f91e 100644 --- a/src/Console/NaviMakeCommand.php +++ b/src/Console/NaviMakeCommand.php @@ -41,9 +41,28 @@ public function handle() return false; } - $name = strtolower(trim($this->argument('name'))); + $component = Str::of($this->argument('name')) + ->lower() + ->trim(); - $this->components->info("Navi component is ready for use."); + $default = $this->option('default') ?? 'primary_navigation'; + + $locations = collect(get_registered_nav_menus()) + ->take(5) + ->map(fn ($name, $slug) => $slug === $default + ? "{$name}: " + : "{$name}: " + ); + + $this->components->info("Navi component is ready for use."); + + if ($locations->isEmpty()) { + $this->components->warn('Your theme does not appear to have any registered navigation menu locations.'); + + return; + } + + $this->components->bulletList($locations->all()); } /** From 76c39df588afa162291882d8cd255e31edb9eaa4 Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 1 Oct 2024 12:32:40 -0500 Subject: [PATCH 4/8] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20allowing?= =?UTF-8?q?=20default=20CSS=20classes=20on=20menu=20items=20=F0=9F=8E=A8?= =?UTF-8?q?=20Improve=20disallowed=20menu=20class=20filtering=20?= =?UTF-8?q?=F0=9F=A9=B9=20Properly=20remove=20default=20WordPress=20CSS=20?= =?UTF-8?q?classes=20from=20menu=20items=20(Fixes=20#84,=20Fixes=20#83,=20?= =?UTF-8?q?Fixes=20#78)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Exceptions/MenuLifecycleException.php | 10 +++ src/MenuBuilder.php | 40 +++++----- src/Navi.php | 94 +++++++++++++++++++++-- 3 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 src/Exceptions/MenuLifecycleException.php diff --git a/src/Exceptions/MenuLifecycleException.php b/src/Exceptions/MenuLifecycleException.php new file mode 100644 index 0000000..6a37b02 --- /dev/null +++ b/src/Exceptions/MenuLifecycleException.php @@ -0,0 +1,10 @@ + 'title', 'object' => 'object', 'objectId' => 'object_id', + 'order' => 'menu_order', 'parent' => 'menu_item_parent', 'slug' => 'post_name', 'target' => 'target', @@ -30,25 +31,12 @@ class MenuBuilder 'type' => 'type', 'url' => 'url', 'xfn' => 'xfn', - 'order' => 'menu_order', ]; /** - * The disallowed menu classes. + * The classes to remove from menu items. */ - protected array $disallowedClasses = [ - 'current-menu', - 'current_page', - 'sub-menu', - 'menu-item', - 'menu-item-type-post_type', - 'menu-item-object-page', - 'menu-item-type-custom', - 'menu-item-object-custom', - 'menu_item', - 'page-item', - 'page_item', - ]; + protected array $withoutClasses = []; /** * Make a new Menu Builder instance. @@ -93,7 +81,15 @@ protected function filter(array $menu = []): array _wp_menu_item_classes_by_context($menu); return array_map(function ($item) { - $classes = array_filter($item->classes, fn ($class) => ! in_array($class, $this->disallowedClasses)); + $classes = array_filter($item->classes, function ($class) { + foreach ($this->withoutClasses as $value) { + if (str_starts_with($class, $value)) { + return false; + } + } + + return true; + }); $item->classes = is_array($classes) ? implode(' ', $classes) : $classes; @@ -142,10 +138,18 @@ protected function handle(array $items, string|int $parent = 0): array $item->children = $this->handle($items, $item->id); $menu[$item->id] = $item; - - unset($item); } return $menu; } + + /** + * Remove classes from menu items. + */ + public function withoutClasses(array $classes = []): self + { + $this->withoutClasses = $classes; + + return $this; + } } diff --git a/src/Navi.php b/src/Navi.php index 5a0e8fd..a067a41 100644 --- a/src/Navi.php +++ b/src/Navi.php @@ -2,6 +2,8 @@ namespace Log1x\Navi; +use Log1x\Navi\Exceptions\MenuLifecycleException; + class Navi { /** @@ -19,6 +21,17 @@ class Navi */ protected string $default = 'primary_navigation'; + /** + * The disallowed menu classes. + */ + protected array $disallowedClasses = [ + 'current-page', + 'current-menu', + 'menu-item', + 'page-item', + 'sub-menu', + ]; + /** * Create a new Navi instance. */ @@ -60,14 +73,15 @@ public function build(mixed $menu = null): self $items = wp_get_nav_menu_items($this->menu); - $this->items = MenuBuilder::make()->build($items ?: []); + $this->items = MenuBuilder::make() + ->withoutClasses($this->disallowedClasses()) + ->build($items ?: []); return $this; } /** - * Retrieve the specified key from the WordPress menu object. - * If no key is specified, the entire menu object will be returned. + * Retrieve data from the WordPress menu object. */ public function get(?string $key = null, mixed $default = null): mixed { @@ -83,7 +97,7 @@ public function get(?string $key = null, mixed $default = null): mixed } /** - * Determine if Navi is empty. + * Determine if the menu is empty. */ public function isEmpty(): bool { @@ -91,7 +105,7 @@ public function isEmpty(): bool } /** - * Determine if Navi is not empty. + * Determine if the menu is not empty. */ public function isNotEmpty(): bool { @@ -99,7 +113,7 @@ public function isNotEmpty(): bool } /** - * Retrieve the Navi items. + * Retrieve the menu items. */ public function all(): array { @@ -107,7 +121,7 @@ public function all(): array } /** - * Retrieve the Navi items as an array. + * Retrieve the menu items as an array. */ public function toArray(): array { @@ -115,13 +129,77 @@ public function toArray(): array } /** - * Retrieve the Navi items as JSON. + * Retrieve the menu items as JSON. */ public function toJson(int $options = 0): string { return json_encode($this->toArray(), $options); } + /** + * The classes to allow on menu items. + * + * @throws \Log1x\Navi\Exceptions\MenuLifecycleException + */ + public function withClasses(string|array $classes): self + { + if ($this->menu) { + throw new MenuLifecycleException('Classes must be set before building the menu.'); + } + + $classes = is_string($classes) + ? explode(' ', $classes) + : $classes; + + $this->disallowedClasses = array_diff($this->disallowedClasses, $classes); + + return $this; + } + + /** + * The classes to remove from menu items. + * + * @throws \Log1x\Navi\Exceptions\MenuLifecycleException + */ + public function withoutClasses(string|array $classes): self + { + if ($this->menu) { + throw new MenuLifecycleException('Attributes must be set before building the menu.'); + } + + $classes = is_string($classes) + ? explode(' ', $classes) + : $classes; + + $this->disallowedClasses = array_unique([ + ...$this->disallowedClasses, + ...$classes, + ]); + + return $this; + } + + /** + * Allow the disallowed classes on menu items. + */ + public function withDefaultClasses(): self + { + $this->disallowedClasses = []; + + return $this; + } + + /** + * Retrieve the disallowed classes. + */ + protected function disallowedClasses(): array + { + return array_merge(...array_map(fn ($class) => [ + $class, + str_replace('-', '_', $class), + ], $this->disallowedClasses)); + } + /** * Dynamically retrieve a Navi item. */ From 915c3e2c528dc87a8d535acf7d75f61837aec5a7 Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 1 Oct 2024 12:32:58 -0500 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=8E=A8=20Use=20`all()`=20instead=20of?= =?UTF-8?q?=20`toArray()`=20in=20examples?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/vanilla/template-parts/site-nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/vanilla/template-parts/site-nav.php b/examples/vanilla/template-parts/site-nav.php index 5d14698..bd1e87b 100644 --- a/examples/vanilla/template-parts/site-nav.php +++ b/examples/vanilla/template-parts/site-nav.php @@ -11,7 +11,7 @@ isNotEmpty() ) : ?>