FB_FALLBACK_RECOMMEND_PCT, 'review_count' => FB_FALLBACK_REVIEW_COUNT, 'followers' => FB_FALLBACK_FOLLOWERS, 'source' => 'fallback', 'fetched_at' => null, ]; if (FB_PAGE_ACCESS_TOKEN === '') { return $fallback; } $cacheFile = __DIR__ . '/../cache/facebook-stats.json'; if (is_file($cacheFile)) { $cached = json_decode((string) file_get_contents($cacheFile), true); if (is_array($cached) && (time() - ($cached['fetched_at'] ?? 0)) < FB_STATS_CACHE_TTL) { $cached['source'] = 'cache'; return $cached; } } $fresh = fritz_fetch_facebook_stats($fallback); $fresh['fetched_at'] = time(); $cacheDir = dirname($cacheFile); if (!is_dir($cacheDir)) { @mkdir($cacheDir, 0775, true); } @file_put_contents($cacheFile, json_encode($fresh)); return $fresh; } function fritz_fetch_facebook_stats(array $fallback): array { if (!function_exists('curl_init')) { return $fallback; } $url = sprintf( 'https://graph.facebook.com/v21.0/%s?fields=followers_count,overall_star_rating,rating_count&access_token=%s', FB_PAGE_ID, urlencode(FB_PAGE_ACCESS_TOKEN) ); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, ]); $body = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($body === false || $httpCode !== 200) { return $fallback; } $data = json_decode($body, true); if (!is_array($data) || isset($data['error'])) { return $fallback; } $recommendPct = isset($data['overall_star_rating']) ? (int) round(($data['overall_star_rating'] / 5) * 100) : $fallback['recommend_pct']; return [ 'recommend_pct' => $recommendPct, 'review_count' => $data['rating_count'] ?? $fallback['review_count'], 'followers' => $data['followers_count'] ?? $fallback['followers'], 'source' => 'live', ]; }