// === Google Reviews (ACF local group on Options) ===
add_action('acf/init', function () {
if( function_exists('acf_add_local_field_group') ){
acf_add_local_field_group([
'key' => 'group_spotts_google_reviews',
'title' => 'Footer: Google Reviews',
'fields' => [
[
'key' => 'field_gr_enable',
'label' => 'Enable Google Reviews',
'name' => 'gr_enable',
'type' => 'true_false',
'ui' => 1,
'default_value' => 0,
],
[
'key' => 'field_gr_title',
'label' => 'Section Title',
'name' => 'gr_title',
'type' => 'text',
'placeholder' => 'What clients say on Google',
],
[
'key' => 'field_gr_place_id',
'label' => 'Google Place ID',
'name' => 'gr_place_id',
'type' => 'text',
'instructions' => 'e.g. ChIJ... (Place ID for spottsgardens.com business)',
],
[
'key' => 'field_gr_api_key',
'label' => 'Google API Key (Places)',
'name' => 'gr_api_key',
'type' => 'text',
'instructions' => 'Must have Places API enabled. If left blank, the site-wide ACF Google key will NOT be used automatically—put a key here.',
],
[
'key' => 'field_gr_max',
'label' => 'Max Reviews to Show',
'name' => 'gr_max',
'type' => 'number',
'default_value' => 3,
'min' => 1,
'max' => 5
],
[
'key' => 'field_gr_min_rating',
'label' => 'Minimum Star Rating',
'name' => 'gr_min_rating',
'type' => 'number',
'default_value' => 4,
'min' => 1,
'max' => 5,
'step' => 0.1
],
],
'location' => [[[
'param' => 'options_page',
'operator' => '==',
'value' => 'acf-options',
]]],
]);
}
});
// === Fetch Google Reviews with caching ===
function spotts_get_google_reviews() {
if (!function_exists('get_field')) return [];
$enabled = get_field('gr_enable', 'options');
if (!$enabled) return [];
$place_id = trim((string) get_field('gr_place_id', 'options'));
$api_key = trim((string) get_field('gr_api_key', 'options'));
$max_show = (int) (get_field('gr_max', 'options') ?: 3);
$min_rating = (float) (get_field('gr_min_rating', 'options') ?: 4);
if (!$place_id || !$api_key) return [];
$transient_key = 'spotts_gr_' . md5($place_id . '|' . $max_show . '|' . $min_rating);
$cached = get_transient($transient_key);
if ($cached !== false) return $cached;
$endpoint = add_query_arg([
'place_id' => $place_id,
'fields' => 'name,url,rating,user_ratings_total,reviews',
'reviews_sort' => 'newest',
'key' => $api_key,
], 'https://maps.googleapis.com/maps/api/place/details/json');
$resp = wp_remote_get($endpoint, ['timeout' => 12]);
if (is_wp_error($resp)) return [];
$code = wp_remote_retrieve_response_code($resp);
if ($code !== 200) return [];
$data = json_decode(wp_remote_retrieve_body($resp), true);
if (!is_array($data) || empty($data['result'])) return [];
$result = $data['result'];
$reviews = isset($result['reviews']) && is_array($result['reviews']) ? $result['reviews'] : [];
// Filter & trim
$reviews = array_values(array_filter($reviews, function($r) use ($min_rating){
return isset($r['rating']) && (float)$r['rating'] >= $min_rating;
}));
$reviews = array_slice($reviews, 0, max(1, min(5, $max_show)));
// Normalize fields we need
$normalized = [];
foreach ($reviews as $r) {
$normalized[] = [
'author_name' => $r['author_name'] ?? 'Google User',
'profile_photo_url' => $r['profile_photo_url'] ?? '',
'rating' => (float) ($r['rating'] ?? 0),
'text' => $r['text'] ?? '',
'relative_time' => $r['relative_time_description'] ?? '',
'author_url' => $r['author_url'] ?? '',
'place_name' => $result['name'] ?? '',
'place_url' => $result['url'] ?? '',
'overall_rating' => (float) ($result['rating'] ?? 0),
'total_ratings' => (int) ($result['user_ratings_total'] ?? 0),
];
}
// Cache 12 hours
set_transient($transient_key, $normalized, 12 * HOUR_IN_SECONDS);
return $normalized;
}
Spotts Gardens | Organic Garden Design, Installation, & Care
Please ensure Javascript is enabled for purposes of website accessibility