Jake Vanderwerf
2026-05-03 9bbeea742424837fb58207d88e10dbca0b2cae04
inc/managers/SEO/render/Traits/_Properties/reviewTrait.php
@@ -2,7 +2,11 @@
namespace JVBase\managers\SEO\render\Traits\_Properties;
use JVBase\managers\SEO\render\Thing\CreativeWork\Review;
use JVBase\managers\SEO\render\Thing\Intangible\Rating\Rating;
use JVBase\managers\SEO\render\Thing\Person\Person;
use JVBase\managers\SEO\render\Traits\_Helpers\arrayHelper;
use JVBase\meta\Meta;
use JVBase\registrar\Fields;
if (!defined('ABSPATH')) {
   exit;
@@ -64,4 +68,156 @@
         ]
      ];
   }
   public function setReviewField(Fields $fields):void
   {
      $fields->addField(
         'enable_gmb_review_sync',
         [
            'type'   => 'true_false',
            'label'  => __('Enable Google My Business Sync', 'jvb'),
            'hint'   => 'Automagically fetch your latest positive reviews from your Google Business Listing.
            Note: you must enable your GMB integration in settings.',
         ]
      );
      $fields->addField('gmb_min_rating',
         [
            'type'   => 'number',
            'default'   => 4,
            'min' => 1,
            'max' => 5,
            'label'  => 'Minimum Rating to fetch',
            'hint'   => 'Defaults to 4 stars and above',
            'condition' => [
               'field'  => 'enable_gmb_review_sync',
               'operator'  => '==',
               'value'  => true,
            ]
         ]
      );
      $fields->addField(
         'reviews',
         [
            'type'   => 'repeater',
            'label'  => __('Reviews', 'jvb'),
            'fields' => [
               'author' => [
                  'type'   => 'text',
                  'label'  => __('Review Author', 'jvb'),
                  'required'  => true,
               ],
               'reviewRating' => [
                  'type'   => 'number',
                  'min' => 1,
                  'max' => 5,
                  'label'  => __('Review Rating', 'jvb'),
                  'required'  => true,
               ],
               'reviewBody'   => [
                  'type'   => 'textarea',
                  'label'  => __('Review Text Content', 'jvb'),
               ],
               'url'    => [
                  'type'   => 'url',
                  'label'  => __('Link to actual review'),
                  'hint'   => 'Optional. Link directly to the review source for added authenticity.'
               ]
            ],
            'condition' => [
               'field'  => 'enable_gmb_review_sync',
               'operator'  => '!=',
               'value'  => true,
            ]
         ]
      );
   }
   public function formatReviewField(Meta $meta):void
   {
      $gmb = $meta->get('enable_gmb_review_sync');
      if (!empty($gmb) && $gmb === true) {
         $this->fetchGMBReviews($meta);
         return;
      }
      $reviews = $meta->get('reviews');
      if (!empty($reviews)) {
         $theReviews = [];
         foreach ($reviews as $row) {
            $review = new Review();
            $author = $row['author'];
            $reviewer = new Person();
            $reviewer->setName($author);
            $review->setAuthor($reviewer);
            $rating = new Rating();
            $rating->setRatingValue($row['reviewRating']);
            $review->setReviewRating($rating);
            if (!empty($row['reviewBody'])) {
               $review->setReviewBody($row['reviewBody']);
            }
            if (!empty($row['url'])){
               $review->setUrl($row['url']);
            }
            $theReviews[] = $review;
         }
         if (!empty($theReviews)) {
            $this->setReview($theReviews);
         }
      }
   }
   protected function fetchGMBReviews(Meta $meta):void
   {
      $userID = (int) get_post_meta($meta->id(), BASE.'profile_link', true);
      if ($userID && $userID > 0) {
         $integration = JVB()->connect('gmb', $userID);
         if ($integration && $integration->isSetUp()){
            $fetched = $integration->getReviews(20);
            if (!empty($fetched)) {
               $reviews = [];
               $minRating = $meta->get('gmb_min_rating');
               foreach ($fetched as $review) {
                  $rating = $review['starRating'] ?? 0;
                  if ($rating >= $minRating) {
                     $reviews[] = $review;
                     if (count($reviews) >= 10) {
                        break;
                     }
                  }
               }
            }
            if (!empty($reviews)) {
               $theReviews = [];
               foreach ($reviews as $r) {
                  $review = new Review();
                  $author = $r['reviewer']['displayName'] ?? 'Anonymous';
                  $author = strtok($author, ' ');
                  $reviewer = new Person();
                  $reviewer->setName($author);
                  $review->setAuthor($reviewer);
                  $rating = new Rating();
                  $rating->setRatingValue(match($r['starRating']) {
                     'FIVE'   => 5,
                     'FOUR'   => 4,
                     'THREE'  => 3,
                     'TWO' => 2,
                     'ONE' => 1,
                     default => 0
                  });
                  $review->setReviewRating($rating);
                  if (!empty($r['comment'])) {
                     $review->setReviewBody($r['comment']);
                  }
                  if (!empty($r['updateTime']??'')){
                     $review->setDateCreated($r['updateTime']);
                  }
                  $theReviews[] = $review;
               }
               if (!empty($theReviews)) {
                  $this->setReview($theReviews);
               }
            }
         }
      }
   }
}