self::extractDefaultRoutes('getLinks'), 'dashboard' => self::extractDefaultRoutes('getDashboardLinks'), 'account' => self::extractDefaultRoutes('getAccountDropdownLinks'), ]; return $routes; } /** * Extract default routes from a Navigation method (safe - no events) */ private static function extractDefaultRoutes($method) { try { // Instead of calling Navigation methods that trigger events, // we'll recreate the core logic without events switch ($method) { case 'getLinks': return self::getCoreLinksWithoutEvents(); case 'getDashboardLinks': return self::getCoreDashboardLinksWithoutEvents(); case 'getAccountDropdownLinks': return self::getCoreAccountLinksWithoutEvents(); default: return []; } } catch (\Exception $e) { \Log::error('DefaultRouteManager: Error extracting routes from ' . $method, [ 'error' => $e->getMessage() ]); return []; } } /** * Get core primary navigation links without triggering events */ private static function getCoreLinksWithoutEvents() { $categories = \App\Models\Category::whereNull('parent_id')->where(function ($query) { $query->whereHas('children')->orWhereHas('products', function ($query) { $query->where('hidden', false); }); })->get(); $routes = [ [ 'name' => __('navigation.home'), 'route' => 'home', 'icon' => 'ri-home-2', 'priority' => 10, ], [ 'name' => __('navigation.shop'), 'route' => 'shop', 'icon' => 'ri-shopping-bag', 'priority' => 20, 'children' => $categories->map(function ($category, $index) { return [ 'name' => $category->name, 'route' => 'category.show', 'params' => ['category' => $category->slug], 'priority' => $index * 10, ]; })->toArray(), 'condition' => count($categories) > 0, ], ]; $extractedRoutes = []; foreach ($routes as $index => $route) { if (isset($route['route'])) { $extractedRoutes[] = [ 'key' => $route['route'] . '_' . $index, 'name' => $route['name'] ?? ucfirst($route['route']), 'route' => $route['route'], 'icon' => $route['icon'] ?? null, 'priority' => $route['priority'] ?? $index * 10, 'params' => $route['params'] ?? null, 'condition' => isset($route['condition']) ? (is_bool($route['condition']) ? ($route['condition'] ? 'always_visible' : 'always_hidden') : 'custom') : 'always_visible', 'children' => isset($route['children']) ? self::extractChildRoutes($route['children'], $route['route']) : [], ]; } } return $extractedRoutes; } /** * Get core dashboard links without triggering events */ private static function getCoreDashboardLinksWithoutEvents() { $routes = [ [ 'name' => __('navigation.dashboard'), 'route' => 'dashboard', 'icon' => 'ri-function', 'priority' => 10, ], [ 'name' => __('navigation.services'), 'route' => 'services', 'icon' => 'ri-archive-stack', 'priority' => 20, ], [ 'name' => __('navigation.invoices'), 'route' => 'invoices', 'icon' => 'ri-receipt', 'priority' => 30, ], ]; $extractedRoutes = []; foreach ($routes as $index => $route) { if (isset($route['route'])) { $extractedRoutes[] = [ 'key' => $route['route'] . '_' . $index, 'name' => $route['name'] ?? ucfirst($route['route']), 'route' => $route['route'], 'icon' => $route['icon'] ?? null, 'priority' => $route['priority'] ?? $index * 10, 'params' => $route['params'] ?? null, 'condition' => 'always_visible', 'children' => [], ]; } } return $extractedRoutes; } /** * Get core account links without triggering events */ private static function getCoreAccountLinksWithoutEvents() { $routes = [ [ 'name' => __('navigation.profile'), 'route' => 'profile', 'icon' => 'ri-user', 'priority' => 10, ], [ 'name' => __('navigation.logout'), 'route' => 'auth.logout', 'icon' => 'ri-logout', 'priority' => 90, ], ]; $extractedRoutes = []; foreach ($routes as $index => $route) { if (isset($route['route'])) { $extractedRoutes[] = [ 'key' => $route['route'] . '_' . $index, 'name' => $route['name'] ?? ucfirst($route['route']), 'route' => $route['route'], 'icon' => $route['icon'] ?? null, 'priority' => $route['priority'] ?? $index * 10, 'params' => $route['params'] ?? null, 'condition' => 'always_visible', 'children' => [], ]; } } return $extractedRoutes; } /** * Extract child routes from parent route */ private static function extractChildRoutes($children, $parentRoute) { $extractedChildren = []; foreach ($children as $index => $child) { if (isset($child['route'])) { $extractedChildren[] = [ 'key' => $parentRoute . '_child_' . $child['route'] . '_' . $index, 'name' => $child['name'] ?? ucfirst($child['route']), 'route' => $child['route'], 'icon' => $child['icon'] ?? null, 'priority' => $child['priority'] ?? $index * 10, 'params' => $child['params'] ?? null, ]; } } return $extractedChildren; } /** * Sync default routes to database for editing */ public static function syncDefaultRoutes($type = 'primary') { $defaultRoutes = self::getDefaultRoutes()[$type] ?? []; $synced = 0; foreach ($defaultRoutes as $route) { $existing = NavbarLink::where('default_route_key', $route['key']) ->where('type', $type) ->first(); if (!$existing) { NavbarLink::create([ 'name' => $route['name'], 'type' => $type, 'link_type' => 'route', 'route_name' => $route['route'], 'route_params' => $route['params'], 'icon' => $route['icon'], 'condition' => $route['condition'], 'sort_order' => $route['priority'], 'is_active' => true, 'is_default_override' => true, 'default_route_key' => $route['key'], 'default_priority' => $route['priority'], ]); $synced++; } // Sync children foreach ($route['children'] as $child) { $existingChild = NavbarLink::where('default_route_key', $child['key']) ->where('type', $type) ->first(); if (!$existingChild && $existing) { NavbarLink::create([ 'name' => $child['name'], 'type' => $type, 'link_type' => 'route', 'route_name' => $child['route'], 'route_params' => $child['params'], 'icon' => $child['icon'], 'sort_order' => $child['priority'], 'is_active' => true, 'parent_id' => $existing->id, 'is_default_override' => true, 'default_route_key' => $child['key'], 'default_priority' => $child['priority'], ]); $synced++; } } } return $synced; } /** * Get merged navigation (default + custom) */ public static function getMergedNavigation($type = 'primary') { // Get default routes that are NOT overridden $defaultRoutes = self::getDefaultRoutes()[$type] ?? []; $overriddenKeys = NavbarLink::defaultOverrides() ->where('type', $type) ->pluck('default_route_key') ->toArray(); $mergedRoutes = []; // Add non-overridden default routes foreach ($defaultRoutes as $route) { if (!in_array($route['key'], $overriddenKeys)) { $mergedRoutes[] = [ 'name' => $route['name'], 'route' => $route['route'], 'icon' => $route['icon'], 'priority' => $route['priority'], 'params' => $route['params'], 'spa' => true, 'source' => 'default', ]; } } // Add custom and overridden routes from database $customRoutes = NavbarLink::active() ->topLevel() ->where('type', $type) ->orderBy('sort_order') ->get(); foreach ($customRoutes as $link) { $formatted = self::formatNavbarLink($link); if ($formatted) { $formatted['source'] = $link->is_default_override ? 'override' : 'custom'; $mergedRoutes[] = $formatted; } } // Sort by priority usort($mergedRoutes, function ($a, $b) { return ($a['priority'] ?? 0) <=> ($b['priority'] ?? 0); }); return $mergedRoutes; } /** * Format NavbarLink model to navigation array format */ private static function formatNavbarLink($link) { $formatted = [ 'name' => $link->name, 'priority' => $link->sort_order, ]; // Add icon if valid if ($link->icon) { $baseIcon = preg_replace('/-(?:line|fill)$/', '', $link->icon); $formatted['icon'] = $baseIcon; } // Handle different link types switch ($link->link_type) { case 'route': if ($link->route_name) { $formatted['route'] = $link->route_name; $formatted['spa'] = true; if ($link->route_params) { $params = is_string($link->route_params) ? json_decode($link->route_params, true) : $link->route_params; if ($params && is_array($params)) { $formatted['params'] = $params; } } } else { return null; } break; case 'path': case 'url': $formatted['route'] = 'navbar.redirect'; $formatted['params'] = ['linkId' => $link->id]; $formatted['spa'] = false; break; } // Handle children if ($link->children && $link->children->count() > 0) { $children = []; foreach ($link->children->where('is_active', true) as $child) { $childFormatted = self::formatNavbarLink($child); if ($childFormatted) { $children[] = $childFormatted; } } if (!empty($children)) { $formatted['children'] = $children; } } return $formatted; } }