146 lines
4.2 KiB
PHP
146 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Menu;
|
|
use Nwidart\Menus\MenuBuilder;
|
|
use Nwidart\Menus\MenuItem;
|
|
use ReflectionClass;
|
|
|
|
class AdminMenuGroupingService
|
|
{
|
|
public function apply(string $menuName = 'admin-sidebar-menu'): void
|
|
{
|
|
$groups = config('admin_menu_groups', []);
|
|
|
|
if (empty($groups)) {
|
|
return;
|
|
}
|
|
|
|
Menu::modify($menuName, function (MenuBuilder $menu) use ($groups) {
|
|
$items = collect($menu->getOrderedItems())
|
|
->filter(function (MenuItem $item) {
|
|
return ! $item->isHeader() && ! $item->isDivider();
|
|
})
|
|
->values();
|
|
|
|
if ($items->isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
$groupBuckets = [];
|
|
foreach (array_keys($groups) as $groupKey) {
|
|
$groupBuckets[$groupKey] = [];
|
|
}
|
|
|
|
foreach ($items as $item) {
|
|
$groupKey = $this->resolveGroupKey($item, $groups);
|
|
if (! isset($groupBuckets[$groupKey])) {
|
|
$groupBuckets[$groupKey] = [];
|
|
}
|
|
$groupBuckets[$groupKey][] = $item;
|
|
}
|
|
|
|
$newItems = [];
|
|
$assigned = [];
|
|
|
|
foreach ($groups as $groupKey => $groupConfig) {
|
|
$groupItems = $groupBuckets[$groupKey] ?? [];
|
|
if (empty($groupItems)) {
|
|
continue;
|
|
}
|
|
|
|
usort($groupItems, function (MenuItem $a, MenuItem $b) {
|
|
return ((int) ($a->order ?? 0)) <=> ((int) ($b->order ?? 0));
|
|
});
|
|
|
|
$newItems[] = MenuItem::make([
|
|
'name' => 'header',
|
|
'title' => $this->resolveLabel($groupConfig),
|
|
'attributes' => [
|
|
'data-group' => $groupKey,
|
|
'class' => 'nav-small-cap--collapsible',
|
|
],
|
|
'order' => (int) ($groupItems[0]->order ?? 0) - 1,
|
|
]);
|
|
|
|
foreach ($groupItems as $groupItem) {
|
|
$newItems[] = $groupItem;
|
|
$assigned[spl_object_id($groupItem)] = true;
|
|
}
|
|
}
|
|
|
|
foreach ($items as $item) {
|
|
if (! isset($assigned[spl_object_id($item)])) {
|
|
$newItems[] = $item;
|
|
}
|
|
}
|
|
|
|
$this->setMenuItems($menu, $newItems);
|
|
});
|
|
}
|
|
|
|
protected function resolveLabel(array $groupConfig): string
|
|
{
|
|
if (! empty($groupConfig['label_key'])) {
|
|
return (string) __($groupConfig['label_key']);
|
|
}
|
|
|
|
return (string) ($groupConfig['label'] ?? '');
|
|
}
|
|
|
|
protected function resolveGroupKey(MenuItem $item, array $groups): string
|
|
{
|
|
$attrs = $item->attributes ?? [];
|
|
|
|
if (! empty($attrs['data-menu-group'])) {
|
|
$key = (string) $attrs['data-menu-group'];
|
|
if (isset($groups[$key])) {
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
$module = $attrs['data-module'] ?? null;
|
|
if ($module) {
|
|
foreach ($groups as $key => $config) {
|
|
if (! empty($config['modules']) && in_array($module, $config['modules'], true)) {
|
|
return $key;
|
|
}
|
|
}
|
|
}
|
|
|
|
$order = (int) ($item->order ?? 0);
|
|
|
|
foreach ($groups as $key => $config) {
|
|
if (empty($config['orders'])) {
|
|
continue;
|
|
}
|
|
|
|
[$min, $max] = $config['orders'];
|
|
if ($order >= $min && $order <= $max) {
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
foreach (array_reverse(array_keys($groups)) as $fallbackKey) {
|
|
if (! empty($groups[$fallbackKey]['orders'])) {
|
|
continue;
|
|
}
|
|
|
|
if (! empty($groups[$fallbackKey]['modules'])) {
|
|
return $fallbackKey;
|
|
}
|
|
}
|
|
|
|
return array_key_first($groups) ?: 'dashboard';
|
|
}
|
|
|
|
protected function setMenuItems(MenuBuilder $menu, array $items): void
|
|
{
|
|
$reflection = new ReflectionClass($menu);
|
|
$property = $reflection->getProperty('items');
|
|
$property->setAccessible(true);
|
|
$property->setValue($menu, $items);
|
|
}
|
|
}
|