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); } }