From ccf5e61a075c35d24befc175994b5cb8957ca322 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 26 Aug 2026 21:45:53 +0000
Subject: [PATCH] =Extra JVB() calls replaced, minor tweaks
---
inc/integrations/services/GoogleMyBusiness.php | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 355 insertions(+), 6 deletions(-)
diff --git a/inc/integrations/services/GoogleMyBusiness.php b/inc/integrations/services/GoogleMyBusiness.php
index 25e98bb..8d374ea 100644
--- a/inc/integrations/services/GoogleMyBusiness.php
+++ b/inc/integrations/services/GoogleMyBusiness.php
@@ -9,7 +9,9 @@
use JVBase\integrations\OAuthURLs;
use JVBase\integrations\Requests;
use JVBase\integrations\SyncTo;
+use JVBase\integrations\SyncToPost;
use JVBase\integrations\UserConnection;
+use WP_Error;
if (!defined('ABSPATH')) {
@@ -18,10 +20,10 @@
class GoogleMyBusiness extends Integrations
{
- use Admin, Instance, OAuth, Requests, UserConnection, SyncTo;
+ use Admin, Instance, OAuth, Requests, UserConnection, SyncToPost;
protected string $readMask = 'name,title,storefrontAddress,metadata,openInfo,storeCode,categories,phoneNumbers,labels,specialHours';
-
+ protected string $businessV4;
protected function __construct()
{
$this->service_name = 'gmb';
@@ -35,6 +37,9 @@
];
$this->supportsWebp = false;
+ $this->baseUrl = 'https://mybusinessbusinessinformation.googleapis.com';
+ $this->businessV4 = 'https://mybusiness.googleapis.com/v4';
+
$this->defineFields();
$this->defineInstructions();
$this->defineOAuth();
@@ -140,7 +145,12 @@
protected function getRequestHeaders(): array
{
- // TODO: Implement getRequestHeaders() method.
+
+ return [
+ 'Authorization' => 'Bearer ' . $this->getAccessToken(),
+ 'Content-Type' => 'application/json',
+ 'Accept' => 'application/json'
+ ];
}
protected function handleResponse(\WP_Error|array $response, string $method, string $endpoint): array
@@ -151,14 +161,16 @@
return match($endpoint) {
'https://mybusinessaccountmanagement.googleapis.com/v1/accounts' => $this->handleGetAccountsResponse($response, $method),
+ sprintf('%s/%s/%s/reviews', $this->businessV4, $this->getAccountID()??'', $this->getLocationID()??'') => $this->handleGetReviewResponse($response, $method),
sprintf('https://mybusinessbusinessinformation.googleapis.com/v1/%s/locations', $this->getAccountID()??'') => $this->handleGetLocationsResponse($response, $method),
+ sprintf('%s/v1/%s', $this->baseUrl,$this->getLocationID()??'') => $this->handleGetLocationResponse($response, $method),
default => $this->response(false, 'Unhandled response for '.$endpoint.' endpoint, with method: '.$method)
};
}
protected function refreshAccessToken(OAuthCredentials $credentials): array
{
- // TODO: Implement refreshAccessToken() method.
+
}
/*********************************************************
@@ -177,6 +189,31 @@
return $stored;
}
+ protected function getLocation(bool $force = false):?array
+ {
+ $location_name = $this->getLocationID();
+ if (empty($location_name)) {
+ return null;
+ }
+ $params = [
+ 'readMask' => $this->readMask
+ ];
+
+ return $this->getRequest(
+ sprintf(
+ '%s/v1/%s',
+ $this->baseUrl,
+ $location_name,
+ ),
+ $params,
+ $force
+ );
+
+ }
+ protected function handleGetLocationResponse(WP_Error|array $response, string $method):?array
+ {
+ return $response??null;
+ }
protected function getLocationID():string|false
{
return $this->loadCredentials()['location_id']??false;
@@ -254,11 +291,323 @@
protected function setContentTypes(): void
{
- // TODO: Implement setContentTypes() method.
+ $this->contentTypes = [
+ 'menu_item' => $this->buildMenuItemContentType(),
+ 'post' => $this->buildPostContentType(),
+ 'event' => $this->buildEventContentType(),
+ 'offer' => $this->buildOfferContentType(),
+ ];
}
-
+ protected function buildMenuItemContentType():array
+ {
+ return [
+ 'nutritionFacts' => [
+ 'type' => 'repeater',
+ 'label' => 'Nutrition',
+ 'fields' => [
+ 'name' => [
+ 'type' => 'select',
+ 'label' => 'Name',
+ 'options' => [
+ 'calories' => 'Calories',
+ 'totalFat' => 'Total Fat',
+ 'cholesterol' => 'Cholesterol',
+ 'sodium' => 'Sodium',
+ 'totalCarbohydrate' => 'Total Carbohydrates',
+ 'protein' => 'Protein'
+ ]
+ ],
+ 'amount' => [
+ 'type' => 'number',
+ 'label' => 'Amount',
+ ],
+ 'unit' => [
+ 'type' => 'select',
+ 'label' => 'Unit',
+ 'options' => [
+ 'MILLIGRAM' => 'Milligram',
+ 'GRAM' => 'Gram',
+ 'CALORIE' => 'Calorie'
+ ]
+ ]
+ ],
+ 'description' => 'Recommended. Example: Total Fat: 3g',
+ 'section' => 'gmb',
+ ],
+ 'servesNumPeople' => [
+ 'type' => 'number',
+ 'label' => 'Number of People this Serves',
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ],
+ 'portionSize' => [
+ 'type' => 'text',
+ 'label' => 'Portion size',
+ 'description' => 'Example: 8-piece of nuggets',
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ],
+ 'preparationMethods' => [
+ 'type' => 'textarea',
+ 'label' => 'Preparation Methods',
+ 'description' => 'Specific methods that the food can be prepared in',
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ],
+ 'cuisines' => [
+ 'type' => 'text',
+ 'label' => 'Cuisines',
+ 'description' => 'Recommended. The specific cuisine of the food item',
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ],
+ 'spiciness' => [
+ 'type' => 'select',
+ 'label' => 'Spiciness',
+ 'options' => [
+ 'none' => 'None',
+ 'mild' => 'Mild',
+ 'medium' => 'Medium',
+ 'hot' => 'Hot',
+ ],
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ],
+ 'allergen' => [
+ 'type' => 'checkbox',
+ 'label' => 'Allergens',
+ 'options' => [
+ 'dairy' => 'Dairy',
+ 'egg' => 'Egg',
+ 'fish' => 'Fish',
+ 'peanut' => 'Peanut',
+ 'shellfish' => 'Shellfish',
+ 'soy' => 'Soy',
+ 'tree nut' => 'Tree Nut',
+ 'wheat' => 'Wheat'
+ ],
+ 'description' => 'Recommended',
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ],
+ 'dietaryRestriction' => [
+ 'type' => 'checkbox',
+ 'label' => 'Dietary Restrictions',
+ 'description' => 'Recommended.',
+ 'options' => [
+ 'halal' => 'Halal',
+ 'kosher' => 'Kosher',
+ 'organic' => 'Organic',
+ 'vegan' => 'Vegan',
+ 'vegetarian' => 'Vegetarian',
+ 'gluten-free' => 'Gluten Free'
+ ],
+ 'bulkEdit' => true,
+ 'section' => 'gmb',
+ ]
+ ];
+ }
+ protected function buildPostContentType():array
+ {
+ return [
+ 'summary' => [
+ 'type' => 'textarea',
+ 'label' => 'Post Summary',
+ 'required' => true
+ ],
+ 'language_code' => [
+ 'type' => 'text',
+ 'label' => 'Language',
+ 'default' => 'en-CA'
+ ],
+ 'media' => [
+ 'type' => 'image',
+ 'label' => 'Photo',
+ ],
+ 'call_to_action' => [
+ 'type' => 'group',
+ 'fields' => [
+ 'type' => [
+ 'type' => 'select',
+ 'options' =>
+ [
+ 'BOOK' => 'Book Now',
+ 'ORDER' => 'Order Now',
+ 'SHOP' => 'Shop Now',
+ 'LEARN_MORE' => 'Learn More',
+ 'SIGN_UP' => 'Sign up',
+ 'CALL' => 'Call'
+ ]
+ ],
+ 'url' => [
+ 'type' => 'url',
+ 'label' => 'Action URL'
+ ]
+ ]
+ ]
+ ];
+ }
+ protected function buildEventContentType():array
+ {
+ return [
+ 'summary' => [
+ 'type' => 'textarea',
+ 'label' => 'Event Description',
+ 'required' => true
+ ],
+ 'event' => [
+ 'title' => [
+ 'type' => 'text',
+ 'label' => 'Event Title',
+ 'required' => true
+ ],
+ 'start_date' => [
+ 'type' => 'date',
+ 'label' => 'Start Date',
+ 'required' => true
+ ],
+ 'end_date' => [
+ 'type' => 'date',
+ 'label' => 'End Date'
+ ],
+ 'start_time' => [
+ 'type' => 'time',
+ 'label' => 'Start Time'
+ ],
+ 'end_time' => [
+ 'type' => 'time',
+ 'label' => 'End Time'
+ ]
+ ],
+ 'media' => [
+ 'type' => 'image',
+ 'label' => 'Event Photo'
+ ]
+ ];
+ }
+ protected function buildOfferContentType():array
+ {
+ return [
+ 'summary' => [
+ 'type' => 'textarea',
+ 'label' => 'Offer Description',
+ 'required' => true
+ ],
+ 'offer' => [
+ 'coupon_code' => [
+ 'type' => 'text',
+ 'label' => 'Coupon Code'
+ ],
+ 'redeem_online_url' => [
+ 'type' => 'url',
+ 'label' => 'Redemption URL'
+ ],
+ 'terms_conditions' => [
+ 'type' => 'textarea',
+ 'label' => 'Terms & Conditions']
+ ],
+ 'media' => ['type' => 'image', 'label' => 'Offer Photo']
+ ];
+ }
protected function formatForService(int $itemID, string $type = 'post'): array
{
// TODO: Implement formatForService() method.
}
+
+
+ public function getReviews(int $number = 5):array
+ {
+ if (!$this->getLocationID() || !$this->getAccountID()){
+ return [];
+ }
+ return $this->cache->remember(
+ ['reviews', $this->getLocationID(), $number],
+ function() use ($number) {
+ try {
+ return $this->getRequest(
+ sprintf(
+ "%s/{$this->getAccountID()}/{$this->getLocationID()}/reviews",
+ $this->businessV4
+ ),
+ [
+ 'orderBy' => 'updateTime desc'
+ ],
+ );
+ } catch (Exception $e) {
+ $this->logError(
+ 'getReviews',
+ 'Failed to fetch Reviews',
+ [
+ 'error' => $e->getMessage()
+ ]);
+ return [];
+ }
+ }
+ );
+ }
+ protected function handleGetReviewResponse(WP_Error|array $response, string $method):array
+ {
+ return $response;
+ }
+
+ /**********************************************************************
+ * REVIEW UTILITY
+ **********************************************************************/
+ /**
+ * Get the URL to view all Google reviews for the current location
+ * @return string|null The reviews viewing URL or null if not available
+ */
+ public function getReviewsViewUrl():?string
+ {
+ $location = $this->getLocation();
+ if (!$location) {
+ return null;
+ }
+
+ if (!empty($location['metadata']['mapsUrl']??'')) {
+ return $location['metadata']['mapsUrl'];
+ }
+
+ if (!empty($location['metadata']['placeId']??'')) {
+ return sprintf(
+ 'https://search.google.com/local/reviews?placeid=%s',
+ urlencode($location['metadata']['placeId'])
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the URL to leave a review for the current location
+ * @return string|null The review URL or null if not available
+ */
+ public function getReviewUrl():?string
+ {
+ $location = $this->getLocation();
+ if (!$location) {
+ return null;
+ }
+
+ if (!empty($location['metadata']['placeId']??'')) {
+ return sprintf(
+ 'https://search.google.com/local/writereview?placeid=%s',
+ urlencode($location['metadata']['placeId'])
+ );
+ }
+
+ if (!empty($location['metadata']['mapsUrl']??'')) {
+ return sprintf(
+ '%s/reviews',
+ $location['metadata']['mapsUrl']
+ );
+ }
+
+ return null;
+ }
+
+
+ /**************************************************************************
+ * FOOD MENU HELPERS
+ **************************************************************************/
}
--
Gitblit v1.10.0