Skip to content

Commit 5031eca

Browse files
authored
Merge pull request #1 from sukristyan/dev
release: v1.0.0
2 parents a1c98a3 + 2e56072 commit 5031eca

File tree

7 files changed

+294
-0
lines changed

7 files changed

+294
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor/
2+
.DS_Store

composer.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "sukristyan/laravel-menu-wrapper",
3+
"description": "A lightweight Laravel package to simplify building dynamic and structured menus in your applications.",
4+
"type": "library",
5+
"keywords": [
6+
"laravel",
7+
"menu",
8+
"dynamic menu",
9+
"laravel-menu",
10+
"group menu",
11+
"wrapper",
12+
"laravel wrapper",
13+
"laravel menu wrapper",
14+
"laravel menu"
15+
],
16+
"license": "MIT",
17+
"autoload": {
18+
"psr-4": {
19+
"Sukristyan\\LaravelMenuWrapper\\": "src/"
20+
}
21+
},
22+
"authors": [
23+
{
24+
"name": "sukristyan",
25+
"email": "hi@galih.me"
26+
}
27+
],
28+
"require": {
29+
"php": "^8.1"
30+
},
31+
"minimum-stability": "dev",
32+
"prefer-stable": true,
33+
"config": {
34+
"sort-packages": true
35+
},
36+
"extra": {
37+
"laravel": {
38+
"providers": [
39+
"Sukristyan\\LaravelMenuWrapper\\CustomRouteProvider"
40+
]
41+
}
42+
}
43+
}

config/laravel-menu-wrapper.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
use Illuminate\Routing\Route;
4+
5+
return [
6+
/**
7+
* ----------------------------------------------------------------------
8+
* Determine the grouping method that will be used to group your menus
9+
* this configuration will applied only if you give the group label
10+
* on menu(). Refer to the README.md for more information
11+
* ----------------------------------------------------------------------
12+
* Possible value: key, item
13+
*/
14+
'group_as' => 'key',
15+
16+
'populate_items' => function (Route $route) {
17+
return [
18+
'route_name' => $route->getName(),
19+
'uri' => $route->uri(),
20+
'method' => $route->getActionMethod(),
21+
];
22+
}
23+
];

src/Commands/MenuList.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace Sukristyan\LaravelMenuWrapper\Commands;
4+
5+
use Illuminate\Console\Command;
6+
7+
class MenuList extends Command
8+
{
9+
protected $signature = 'menu:list';
10+
protected $description = 'Show all menus you have defined';
11+
12+
public function handle()
13+
{
14+
$menus = app('sukristyan.menu')->all();
15+
$groupAs = config('laravel-menu-wrapper.group_as');
16+
$withoutGroup = [];
17+
18+
$this->line("\n<fg=yellow>--- Showing all menu ----</>");
19+
20+
foreach ($menus as $key => $menu) {
21+
if ($groupAs === 'key') {
22+
is_string($key)
23+
? $this->showGroupsAsKey($key, $menu)
24+
: $withoutGroup[] = $menu;
25+
} elseif ($groupAs === 'item') {
26+
isset($menu['group_name'])
27+
? $this->showGroupsAsItem($menu)
28+
: $withoutGroup[] = $menu;
29+
}
30+
}
31+
32+
$count = count($withoutGroup);
33+
$this->info("\nWithout Group: ({$count} items)");
34+
35+
foreach ($withoutGroup as $menu) {
36+
$this->showChilds($menu);
37+
}
38+
39+
return self::SUCCESS;
40+
}
41+
42+
private function showGroupsAsKey(string $groupName, array $menu)
43+
{
44+
$this->info("\nGroup: {$groupName} (" . count($menu) . " items)");
45+
46+
foreach ($menu as $child) {
47+
$this->showChilds($child);
48+
}
49+
}
50+
51+
private function showGroupsAsItem(array $menu)
52+
{
53+
$this->info("\nGroup: {$menu['group_name']} (" . count($menu['childs']) . " items)");
54+
55+
foreach ($menu['childs'] as $child) {
56+
$this->showChilds($child);
57+
}
58+
}
59+
60+
private function showChilds(array $menu)
61+
{
62+
foreach (array_keys($menu) as $i => $key) {
63+
$prefix = $i === 0 ? '-' : ' ';
64+
$this->line("<fg=gray>{$prefix} {$key}:</> {$menu[$key]}");
65+
}
66+
}
67+
}

src/CustomRouteProvider.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace Sukristyan\LaravelMenuWrapper;
4+
5+
use Illuminate\Routing\Route;
6+
use Illuminate\Support\ServiceProvider;
7+
use Sukristyan\LaravelMenuWrapper\Facade\RegisterMenu;
8+
9+
final class CustomRouteProvider extends ServiceProvider
10+
{
11+
/**
12+
* Register any application services.
13+
*/
14+
public function register(): void
15+
{
16+
$this->registerConfig();
17+
18+
$this->app->singleton('sukristyan.menu', function () {
19+
return new RegisterMenu();
20+
});
21+
}
22+
23+
/**
24+
* Bootstrap any application services.
25+
*/
26+
public function boot(): void
27+
{
28+
Route::macro('groupMenu', function (string $label) {
29+
RegisterMenu::groupping($label);
30+
return $this;
31+
});
32+
33+
Route::macro('menu', function (string $label) {
34+
/** @var \Illuminate\Routing\Route $this */
35+
RegisterMenu::add($this, $label);
36+
return $this;
37+
});
38+
39+
Route::macro('group', function ($attributes, $routes) {
40+
$result = \Illuminate\Support\Facades\Route::buildGroup($attributes, $routes);
41+
RegisterMenu::endGroup();
42+
return $result;
43+
});
44+
}
45+
46+
public function registerConfig()
47+
{
48+
$this->mergeConfigFrom(
49+
__DIR__ . '/../config/laravel-menu-wrapper.php',
50+
'laravel-menu-wrapper'
51+
);
52+
}
53+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Sukristyan\LaravelMenuWrapper\Exceptions;
4+
5+
use InvalidArgumentException;
6+
7+
class InvalidGroupException extends InvalidArgumentException
8+
{
9+
public static function create(string $given, array $expect)
10+
{
11+
$implode = implode(', ', $expect);
12+
return new static("The given role or permission should use guard `{$implode}` instead of `{$given}`.");
13+
}
14+
}

src/Facade/RegisterMenu.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
namespace Sukristyan\LaravelMenuWrapper\Facade;
4+
5+
use Illuminate\Routing\Route;
6+
use Illuminate\Support\Facades\Facade;
7+
use Sukristyan\LaravelMenuWrapper\Exceptions\InvalidGroupException;
8+
9+
class RegisterMenu extends Facade
10+
{
11+
protected static array $menus = [];
12+
protected static array $groups = ['index' => 0, 'group_name' => ''];
13+
14+
protected static function getFacadeAccessor()
15+
{
16+
return 'sukristyan.menu';
17+
}
18+
19+
public static function all(): array
20+
{
21+
return static::$menus;
22+
}
23+
24+
protected static function add(Route $route, string $label, string $groupLabel = '')
25+
{
26+
if (!empty($groupLabel)) {
27+
self::createAsGroup($route, $label, $groupLabel);
28+
} else {
29+
static::$menus[] = array_merge(
30+
['label' => $label],
31+
config('laravel-menu-wrapper.populate_items')($route)
32+
);
33+
}
34+
}
35+
36+
private static function createAsGroup(Route $route, string $label, string $groupLabel): array
37+
{
38+
if (
39+
!in_array(
40+
$given = config('laravel-menu-wrapper.group_as', 'key'),
41+
$expect = ['item', 'key'],
42+
true
43+
)
44+
) {
45+
throw InvalidGroupException::create($given, $expect);
46+
}
47+
48+
foreach (static::$menus as $id => $menu) {
49+
if (is_array($menu) && ($menu['group_name'] ?? null) === $groupLabel) {
50+
static::$groups = ['id' => $id, 'group_name' => $groupLabel];
51+
return match ($given) {
52+
'key' => self::groupAsKey($route, $label, $groupLabel),
53+
'item' => self::groupAsItem($route, $label, $groupLabel),
54+
};
55+
}
56+
}
57+
58+
$newId = count(static::$menus);
59+
static::$groups = ['id' => $newId, 'group_name' => $groupLabel];
60+
61+
return match ($given) {
62+
'key' => self::groupAsKey($route, $label, $groupLabel),
63+
'item' => self::groupAsItem($route, $label, $groupLabel),
64+
};
65+
}
66+
67+
private static function groupAsKey(Route $route, string $label, string $groupLabel): array
68+
{
69+
return static::$menus[$groupLabel][] = array_merge(
70+
['label' => $label],
71+
config('laravel-menu-wrapper.populate_items')($route)
72+
);
73+
}
74+
75+
private static function groupAsItem(Route $route, string $label, string $groupLabel): array
76+
{
77+
$id = static::$groups['id'];
78+
79+
if (!isset(static::$menus[$id]['childs'])) {
80+
static::$menus[$id] = [
81+
'group_name' => $groupLabel,
82+
'childs' => []
83+
];
84+
}
85+
86+
static::$menus[$id]['childs'][] = array_merge(
87+
['label' => $label],
88+
config('laravel-menu-wrapper.populate_items')($route)
89+
);
90+
return static::$menus[$id];
91+
}
92+
}

0 commit comments

Comments
 (0)