- Replace inc/facebook-stats.php with inc/google-reviews.php: fetches
average star rating + review count from the Places API (New) instead
of Facebook's Graph API, same cache-to-JSON/fallback-on-failure shape
as before.
- index.php: stat card now shows the native star rating ("4.8★ average
rating") instead of a recommend %, sourced from Google. Drops the
Facebook-followers line entirely — Google's API has no equivalent and
showing a stale/static number wasn't worth keeping. "Follow on
Facebook" links elsewhere on the site are untouched.
- config.example.php: swap FB_PAGE_ID/FB_PAGE_ACCESS_TOKEN/
FB_STATS_CACHE_TTL/FB_FALLBACK_* for GOOGLE_PLACE_ID/
GOOGLE_PLACES_API_KEY/GOOGLE_STATS_CACHE_TTL/GOOGLE_FALLBACK_RATING/
GOOGLE_FALLBACK_REVIEW_COUNT (set to the pub's actual 4.8★/71 reviews),
with setup instructions in comments. config.php (gitignored) updated
to match.
- Remove the now-dead .stat-row CSS that only existed for the dropped
followers line; rebuild styles.css.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
86 lines
2.6 KiB
PHP
86 lines
2.6 KiB
PHP
<?php
|
|
/**
|
|
* Pulls the average star rating and review count from The Old Fitz's
|
|
* Google Business Profile via the Places API (New), cached to a local
|
|
* JSON file so we don't hit Google on every page load. Falls back to
|
|
* the numbers in config.php whenever there's no API key/Place ID yet,
|
|
* or the API call fails for any reason — the homepage never breaks
|
|
* because of this.
|
|
*/
|
|
|
|
function fritz_google_reviews(): array {
|
|
$fallback = [
|
|
'rating' => GOOGLE_FALLBACK_RATING,
|
|
'review_count' => GOOGLE_FALLBACK_REVIEW_COUNT,
|
|
'source' => 'fallback',
|
|
'fetched_at' => null,
|
|
];
|
|
|
|
if (GOOGLE_PLACES_API_KEY === '' || GOOGLE_PLACE_ID === '') {
|
|
return $fallback;
|
|
}
|
|
|
|
$cacheFile = __DIR__ . '/../cache/google-reviews.json';
|
|
|
|
if (is_file($cacheFile)) {
|
|
$cached = json_decode((string) file_get_contents($cacheFile), true);
|
|
if (is_array($cached) && (time() - ($cached['fetched_at'] ?? 0)) < GOOGLE_STATS_CACHE_TTL) {
|
|
$cached['source'] = 'cache';
|
|
return $cached;
|
|
}
|
|
}
|
|
|
|
$fresh = fritz_fetch_google_reviews($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_google_reviews(array $fallback): array {
|
|
if (!function_exists('curl_init')) {
|
|
return $fallback;
|
|
}
|
|
|
|
$url = sprintf(
|
|
'https://places.googleapis.com/v1/places/%s',
|
|
rawurlencode(GOOGLE_PLACE_ID)
|
|
);
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 5,
|
|
CURLOPT_HTTPHEADER => [
|
|
'X-Goog-Api-Key: ' . GOOGLE_PLACES_API_KEY,
|
|
// Field mask is required by the New Places API (400 without
|
|
// it) and also determines the billing SKU — rating and
|
|
// userRatingCount are "Place Details (New) - Atmosphere".
|
|
'X-Goog-FieldMask: rating,userRatingCount',
|
|
],
|
|
]);
|
|
$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;
|
|
}
|
|
|
|
return [
|
|
'rating' => $data['rating'] ?? $fallback['rating'],
|
|
'review_count' => $data['userRatingCount'] ?? $fallback['review_count'],
|
|
'source' => 'live',
|
|
];
|
|
}
|