From 46d681c6b825d21b3f698d793c4e630c687d90ad Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Thu, 21 May 2026 21:41:53 +0000
Subject: [PATCH] =Major CustomBlocks.php overhaul, expanding block support and customization from the editor. theme.json should now be updated on new themes to set brand colours, etc. Also note: major change to .col vs .row alignment: simplifying it to .top .bottom vs the confusion of the differences for .col/.row .start and .a-start
---
src/gmbreviews/render.php | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 207 insertions(+), 0 deletions(-)
diff --git a/src/gmbreviews/render.php b/src/gmbreviews/render.php
new file mode 100644
index 0000000..487f394
--- /dev/null
+++ b/src/gmbreviews/render.php
@@ -0,0 +1,207 @@
+<?php
+/**
+ * GMB Reviews Block - Render Template
+ *
+ * Displays recent Google My Business reviews with a link to leave a review
+ */
+function jvbRenderGMBReviewsBlock(array $attributes): string
+{
+ $count = $attributes['count'] ?? 5;
+ $showRating = $attributes['showRating'] ?? true;
+ $showDate = $attributes['showDate'] ?? true;
+ $showReviewLink = $attributes['showReviewLink'] ?? true;
+ $showViewAllLink = $attributes['showViewAllLink'] ?? true;
+ $showStats = $attributes['showStats'] ?? true;
+ $minStars = $attributes['minStars'] ?? 4; // Only show 4+ star reviews
+ $inheritUser = $attributes['inheritUser']??null;
+ if ($inheritUser) {
+ global $post;
+ $inheritUser = $post->post_author;
+ }else {
+ $inheritUser = null;
+ }
+ try {
+ $gmb = JVB()->connect('gmb', $inheritUser);
+ if (!$gmb->isSetUp()) {
+ error_log('GMB Not set up for: '.(int)$inheritUser);
+ return '';
+ }
+ $gotReviews = $gmb->getReviews();
+ // Get all data
+ $allReviews = $gotReviews['reviews']??[];
+ $reviewUrl = $gmb->getReviewUrl();
+ $viewAllUrl = $gmb->getReviewsViewUrl();
+
+ $average = $gotReviews['averageRating']??null;
+ $total = $gotReviews['totalReviewCount']??null;
+
+ // Filter reviews by minimum stars
+ $reviews = [];
+ if (!empty($allReviews)) {
+ foreach ($allReviews as $review) {
+ $rating = $review['starRating'] ?? 0;
+ if ($rating >= $minStars) {
+ $reviews[] = $review;
+ if (count($reviews) >= $count) {
+ break; // Got enough reviews
+ }
+ }
+ }
+ }
+
+ if (empty($reviews) && empty($reviewUrl) && empty($stats)) {
+ error_log('No reviews to display...');
+ return '';
+ }
+
+ ob_start();
+ ?>
+ <div class="gmb-reviews">
+ <div class="row center">
+ <?php
+ if ($showStats && !empty($average) && !empty($total)) {
+ ?>
+ <p>
+ <span class="stars" title="<?= $average ?> out of 5 stars">
+ <?php
+ $fullStars = floor($average);
+ $hasHalfStar = ($average - $fullStars) >= 0.5;
+
+ for ($i = 1; $i <= 5; $i++) {
+ if ($i <= $fullStars) {
+ echo jvbIcon('star', ['style' => 'fill']);
+ } elseif ($i == $fullStars + 1 && $hasHalfStar) {
+ echo jvbIcon('star-half', ['style'=> 'fill']);
+ } else {
+ echo jvbIcon('star', ['style' => 'light']);
+ }
+ }
+ ?>
+ </span>
+ <i>Average</i>
+ </p>
+ <?php
+ if ($total > 0) {
+ ?>
+ <p><i>{ <?= number_format($total ) . ' ' . _n('Review', 'Reviews', $total, 'jvb')?> Total }</i></p>
+ <?php
+ }
+ ?>
+ <?php
+ }
+ ?>
+
+
+ </div>
+ <?php
+ if ($showReviewLink && !empty($reviewUrl)) {
+ ?>
+ <a href="<?=esc_url($reviewUrl)?>"
+ class="button"
+ target="_blank"
+ rel="noopener noreferrer">
+ <?= jvbIcon('star', ['style' => 'fill']) ?>
+ Leave Your Review
+ </a>
+ <?php
+ }
+ ?>
+
+ <ul>
+ <?php
+ foreach ($reviews as $review) {
+ $reviewer = $review['reviewer']['displayName'] ?? 'Anonymous';
+ $reviewer = strtok($reviewer, ' ');
+ $profilePhoto = $review['reviewer']['profilePhotoUrl'] ?? '';
+ $rating = $review['starRating'] ?? 0;
+ $rating = match($rating) {
+ 'FIVE' => 5,
+ 'FOUR' => 4,
+ 'THREE' => 3,
+ 'TWO' => 2,
+ 'ONE' => 1,
+ default => $rating
+ };
+ $comment = $review['comment'] ?? '';
+ $date = $review['updateTime'] ?? '';
+ ?>
+ <li>
+ <blockquote class="review">
+ <?php
+ // Review text
+ if (!empty($comment)) { ?>
+ <div class="content review">
+ <?= apply_filters('wpautop', $comment) ?>
+ </div>
+ <?php } ?>
+ <cite class="row left nowrap">
+ <?php if (!empty($profilePhoto)) { ?>
+ <img src="<?=esc_url($profilePhoto)?>"
+ alt="<?=esc_attr($reviewer)?>"
+ 'loading="lazy">
+ <?php } else { ?>
+ <div class="avatar">
+ <?= jvbIcon('user-circle')?>
+ </div>
+ <?php } ?>
+
+ <div class="row left wrap">
+ <?php if ($showRating && $rating > 0) { ?>
+ <div class="stars" title="<?= $rating ?> out of 5 stars">
+ <?php
+ for ($i = 1; $i <= 5; $i++) {
+ echo ($i <= $rating) ? jvbIcon('star', ['style' => 'fill']) : jvbIcon('star', ['style' => 'light']);
+ } ?>
+ </div>
+ <?php } ?>
+ <p><?= esc_html($reviewer)?></p>
+ <?php
+ // Date
+ if ($showDate && !empty($date)) {
+ $formatted_date = human_time_diff(strtotime($date), current_time('timestamp')) . ' ago';
+ ?>
+ <time datetime="<?=esc_attr($date)?>">
+ <?= esc_html($formatted_date) ?>
+ </time>
+ <?php } ?>
+
+ </div>
+ </cite>
+ </blockquote>
+ </li>
+ <?php
+ }
+ ?>
+ </ul>
+ <?php
+ // Footer with "See All Reviews" button
+ if ($showViewAllLink && !empty($viewAllUrl)) {
+ ?>
+ <div class="footer">
+ <a href=" <?= esc_url($viewAllUrl) ?>"
+ class="button"
+ target="_blank"
+ rel="noopener noreferrer">
+
+ <?php
+ if ($showStats ) {
+ echo 'See All ' . number_format($total) . ' Reviews';
+ } else {
+ echo ' See All Reviews';
+ }
+ ?>
+ <?= jvbIcon('arrow-square-out') ?>
+ </a>
+ </div>
+ <?php
+ }
+ ?>
+ </div>
+ <?php
+ return ob_get_clean();
+
+ } catch (\Exception $e) {
+ error_log('[GMB Reviews Block] Error: ' . $e->getMessage());
+ return '';
+ }
+}
--
Gitblit v1.10.0