'error', 'message' => 'Method not allowed', ], JSON_UNESCAPED_UNICODE); exit; } $config = require __DIR__ . '/../config/menu.php'; $languages = is_array($config['languages'] ?? null) ? $config['languages'] : []; $lang = strtolower(trim((string) ($_GET['lang'] ?? 'pl'))); if ($lang === '' || !isset($languages[$lang])) { http_response_code(422); echo json_encode([ 'status' => 'error', 'message' => 'Unsupported language', 'allowed' => array_keys($languages), ], JSON_UNESCAPED_UNICODE); exit; } $langConfig = $languages[$lang]; $source = (string) ($langConfig['source'] ?? 'upstream'); $timeout = max(3, (int) ($config['timeout_seconds'] ?? 12)); $cacheFile = menuCachePath($lang); $cached = readMenuCache($cacheFile); // Cache odświeżamy tylko ręcznie (panel admina / skrypt CLI) — nie fetchujemy upstreamu przy każdym TTL. if ($cached) { echo json_encode($cached, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } if ($source === 'ai') { $from = strtolower((string) ($langConfig['from'] ?? 'pl')); $fallback = readMenuCache(menuCachePath($from)); if ($fallback) { $fallback['lang'] = $lang; $fallback['source'] = 'ai_fallback_pl'; echo json_encode($fallback, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } http_response_code(503); echo json_encode([ 'status' => 'error', 'message' => 'AI menu not available yet — uruchom: php scripts/refresh_menu_cache.php --force-ai', 'lang' => $lang, ], JSON_UNESCAPED_UNICODE); exit; } $base = rtrim((string) ($config['upstream_base'] ?? ''), '/'); $url = $base . '/' . rawurlencode($lang); $raw = fetchUpstreamMenu($url, $timeout); if ($raw === null) { http_response_code(502); echo json_encode([ 'status' => 'error', 'message' => 'Failed to fetch menu (brak cache — uruchom odświeżenie w panelu)', 'lang' => $lang, ], JSON_UNESCAPED_UNICODE); exit; } $mapped = mapUpstreamMenu($raw, $lang, 'upstream'); try { writeMenuCache($cacheFile, $mapped); } catch (Throwable $e) { // Serwuj świeże dane nawet gdy cache nie da się zapisać } echo json_encode($mapped, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);