ultimatepos/app/Services/AdminMenuGroupingService.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);
}
}