diff --git a/app/Services/SidebarMenuService.php b/app/Services/SidebarMenuService.php index 33b693e7..50ee70ba 100644 --- a/app/Services/SidebarMenuService.php +++ b/app/Services/SidebarMenuService.php @@ -172,10 +172,11 @@ public function isMenuActive(Menu $menu): bool return true; } - // prefix 매칭: 다른 메뉴가 현재 URL에 정확히 매칭되면 prefix 매칭 비활성화 - // (예: /esign/create 접속 시, /esign 메뉴가 prefix로 잘못 활성화되는 것 방지) + // prefix 매칭: 더 구체적인 메뉴가 있으면 덜 구체적인 prefix 매칭 비활성화 + // (예: /esign/templates/5/fields 접속 시, /esign/templates 메뉴만 활성화, /esign 메뉴는 비활성) if (str_starts_with($currentPath, $menu->url.'/')) { - return !self::hasExactMenuMatch($currentPath); + return !self::hasExactMenuMatch($currentPath) + && !self::hasMoreSpecificPrefixMenu($currentPath, $menu->url); } return false; @@ -261,6 +262,35 @@ private static function hasExactMenuMatch(string $currentPath): bool return self::$exactMatchCache; } + /** + * 현재 경로에 대해 더 구체적인 prefix를 가진 메뉴가 있는지 확인 + * (예: 현재 메뉴 URL이 /esign이고, /esign/templates 메뉴도 있으면 true) + */ + private static array $prefixMenuCache = []; + + private static function hasMoreSpecificPrefixMenu(string $currentPath, string $menuUrl): bool + { + $cacheKey = $currentPath . '|' . $menuUrl; + if (isset(self::$prefixMenuCache[$cacheKey])) { + return self::$prefixMenuCache[$cacheKey]; + } + + $tenantId = auth()->user()?->tenant_id ?? 1; + + // 현재 경로의 prefix이면서 이 메뉴 URL보다 긴 URL을 가진 활성 메뉴가 있는지 확인 + $result = Menu::withoutGlobalScopes() + ->where('tenant_id', $tenantId) + ->where('is_active', true) + ->whereNotNull('url') + ->where('url', '!=', $menuUrl) + ->whereRaw('LENGTH(url) > ?', [strlen($menuUrl)]) + ->whereRaw("? LIKE CONCAT(url, '/%')", [$currentPath]) + ->exists(); + + self::$prefixMenuCache[$cacheKey] = $result; + return $result; + } + /** * 메뉴 또는 자식 메뉴가 활성 상태인지 확인 */