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/UmamiOld.php | 4
inc/managers/CustomTable.php | 2
inc/blocks/SummaryBlock.php | 19
inc/managers/SEO/render/SchemaOutput.php | 4
inc/managers/Dashboard/DashboardPage.php | 6
jvb.php | 39 -
inc/rest/routes/TermRoutes.php | 9
inc/integrations/_Base.php | 3
inc/managers/OperationQueue.php | 12
inc/managers/DashboardManager.php | 13
inc/rest/routes/ContentRoutes.php | 16
inc/blocks/CustomBlocks.php | 16
inc/rest/routes/FeedRoutes.php | 4
inc/registrar/config/seo/Schema.php | 12
inc/rest/routes/ResponseRoutes.php | 2
inc/blocks/DrawerMenuBlock.php | 4
inc/blocks/TimelineBlock.php | 5
inc/managers/queue/executors/ContentExecutor.php | 3
inc/managers/TaxonomyRelationships.php | 4
inc/rest/routes/ShopRoutes.php | 11
src/forms/render.php | 54 -
inc/managers/Referrals.php | 7
inc/managers/IconsManager.php | 74 +
inc/rest/routes/NewsRoutes.php | 8
inc/managers/queue/executors/IntegrationExecutor.php | 14
inc/integrations/ServiceMap.php | 9
inc/managers/Responses.php | 13
inc/managers/DirectoryManager.php | 7
inc/blocks/FeedBlock.php | 6
inc/registrar/Registrar.php | 7
inc/managers/UserTermsManager.php | 2
inc/forms/PostSelector.php | 6
inc/helpers/renderFields.php | 4
inc/meta/Storage.php | 27
inc/integrations/services/GoogleMyBusiness.php | 361 +++++++++++++
inc/registrar/Posts.php | 2
inc/rest/routes/ContentTermsRoutes.php | 9
templates/dashboard/sections/favourites.php | 12
inc/integrations/services/InstagramOld.php | 7
inc/rest/routes/UploadRoutes.php | 2
inc/managers/queue/Queue.php | 3
inc/blocks/MenuBlock.php | 100 ++-
inc/rest/routes/QueueRoutes.php | 4
inc/managers/Login.php | 2
checks.php | 2
inc/blocks/FeedBlockOld.php | 6
inc/utility/Image.php | 14
inc/managers/Dashboard/Dashboard.php | 4
inc/rest/routes/Invitations.php | 8
inc/managers/MagicLinks.php | 13
inc/integrations/services/GoogleMyBusinessOld.php | 4
/dev/null | 359 -------------
inc/rest/Rest.php | 8
inc/utility/Video.php | 10
inc/rest/RestRouteManager.php | 10
inc/rest/routes/LoginRoutes.php | 139 +----
inc/integrations/services/GoogleMapsOld.php | 10
inc/blocks/FormBlock.php | 4
inc/managers/InvitationsManager.php | 2
inc/managers/Favourites.php | 4
inc/managers/SEO/render/Traits/_Properties/reviewTrait.php | 4
61 files changed, 700 insertions(+), 829 deletions(-)
diff --git a/checks.php b/checks.php
index 242bf4c..4339047 100644
--- a/checks.php
+++ b/checks.php
@@ -37,7 +37,7 @@
function jvbTermHasPosts(int $termID, string $taxonomy):bool
{
- $cache = Cache::for('termUtility', 30*60)->connect('taxonomy');
+ $cache = Cache::for('termUtility', 'term', 30*60);
return $cache->remember(
$termID,
function() use($taxonomy, $termID) {
diff --git a/inc/blocks/CustomBlocks.php b/inc/blocks/CustomBlocks.php
index 2612fbd..20085fe 100644
--- a/inc/blocks/CustomBlocks.php
+++ b/inc/blocks/CustomBlocks.php
@@ -1405,9 +1405,6 @@
if (!static::$currentLoop) {
- if (JVB_TESTING) {
- jvbDump('No loop stored');
- }
return $content;
}
if (static::$currentLoop->have_posts()) {
@@ -1943,9 +1940,7 @@
);
}
- if (JVB_TESTING) {
- jvbDump('Could not create template part block for '.$block['blockName']);
- }
+
return $content;
// $isHeaderTemplate = (
@@ -2792,6 +2787,9 @@
);
}
return $classes;
+ case 'anchor':
+ //TODO: What's this doing?
+ return '';
default:
if (JVB_TESTING && !is_admin() &&!in_array($key, $this->ignore)) {
// TESTING
@@ -3154,7 +3152,9 @@
break;
}
return $this->getColorStyle($value, $type);
-
+ case 'anchor':
+ //TODO: What should we do here?
+ break;
// Any other attributes that need direct styling
default:
if (JVB_TESTING && !is_admin() && !in_array($key, $this->ignore)) {
@@ -3184,7 +3184,7 @@
break;
default:
if (JVB_TESTING) {
- jvbDump($value, 'No preset found for size: '.print_r($value, true));
+ error_log('No preset found for size: '.print_r($value, true));
}
}
}
diff --git a/inc/blocks/DrawerMenuBlock.php b/inc/blocks/DrawerMenuBlock.php
index 0ec9f1d..0a30975 100644
--- a/inc/blocks/DrawerMenuBlock.php
+++ b/inc/blocks/DrawerMenuBlock.php
@@ -49,9 +49,7 @@
}
$cache = Cache::for('drawer');
- if (JVB_TESTING) {
- $cache->flush();
- }
+
if (!is_front_page()) {
$menu_items[] = [
diff --git a/inc/blocks/FeedBlock.php b/inc/blocks/FeedBlock.php
index 3cc10ba..2cf593c 100644
--- a/inc/blocks/FeedBlock.php
+++ b/inc/blocks/FeedBlock.php
@@ -32,12 +32,6 @@
public function __construct()
{
-// // Initialize cache with connections
-// $this->cache = Cache::for('feed_block','post', WEEK_IN_SECONDS);
-// if (JVB_TESTING) {
-// $this->cache->flush();
-// }
-
add_action('init', [$this, 'registerBlock']);
}
diff --git a/inc/blocks/FeedBlockOld.php b/inc/blocks/FeedBlockOld.php
index d56cc1c..fcc482d 100644
--- a/inc/blocks/FeedBlockOld.php
+++ b/inc/blocks/FeedBlockOld.php
@@ -22,9 +22,7 @@
{
// Initialize cache with connections
$this->cache = Cache::for('feed_block', WEEK_IN_SECONDS);
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
add_action('init', [$this, 'registerBlock']);
}
@@ -117,7 +115,7 @@
$this->config = $this->buildParams($attributes);
return $this->cache->remember(
- $this->cache->generateKey($this->config),
+ $this->config,
function() {
return $this->renderBlock();
}
diff --git a/inc/blocks/FormBlock.php b/inc/blocks/FormBlock.php
index 5cd1b22..1bb5115 100644
--- a/inc/blocks/FormBlock.php
+++ b/inc/blocks/FormBlock.php
@@ -36,9 +36,7 @@
{
$this->cache = Cache::for('forms', null, WEEK_IN_SECONDS);
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
// Initialize forms from filter
$this->forms = $this->registerForms();
$this->form_contact = apply_filters('jvb_form_contact', '');
diff --git a/inc/blocks/MenuBlock.php b/inc/blocks/MenuBlock.php
index 24d3759..a623d7c 100644
--- a/inc/blocks/MenuBlock.php
+++ b/inc/blocks/MenuBlock.php
@@ -215,54 +215,78 @@
<div>
<h4>%s — %s</h4>
%s
- </div>', //Note: we had 3 %s%s%s before the last </div> last time. This was to add optional ingredients or preparation time duration, not default in WooCommerce
+ </div><a href="?add-to-cart=%d&variation_id=%d"
+ data-quantity="1"
+ data-product_id="%d"
+ data-variation_id="%d"
+ class="add_to_cart_button ajax_add_to_cart add-to-cart">
+ %s
+ <span>Add to Cart</span>
+</a>', //Note: we had 3 %s%s%s before the last </div> last time. This was to add optional ingredients or preparation time duration, not default in WooCommerce
$row['title'],
jvbCurrency($row['price']),
empty($row['description']) ? '' : wpautop($row['description']),
+ $ID,
+ $row['id'],
+ $ID,
+ $row['id'],
+ jvbIcon('plus-square')
);
- $out .= Form::render(
- $row['id'],
- '',
- [
- 'type' => 'quantity',
- 'label' => $row['title'],
- 'min' => 0,
- 'max' => 30,
- 'data' => [
- 'price' => $row['price'],
- 'id' => $row['id'],
- 'sku' => $row['sku'],
- 'name' => $row['title'],
- 'add-to-cart' => ''
- ],
- 'add' => 'Add 1 '.$row['title'].' to cart',
- 'remove' => 'Remove 1 '.$row['title']. ' from cart',
- ]
- );
+// $out .= Form::render(
+// $row['id'],
+// '',
+// [
+// 'type' => 'quantity',
+// 'label' => $row['title'],
+// 'min' => 0,
+// 'max' => 30,
+// 'data' => [
+// 'price' => $row['price'],
+// 'id' => $row['id'],
+// 'sku' => $row['sku'],
+// 'name' => $row['title'],
+// 'add-to-cart' => ''
+// ],
+// 'add' => 'Add 1 '.$row['title'].' to cart',
+// 'remove' => 'Remove 1 '.$row['title']. ' from cart',
+// ]
+// );
$out .= '</div>';
}
} else {
- $out .= Form::render(
+ $out .= sprintf(
+ '<a href="?add-to-cart=%d"
+ data-quantity="1"
+ data-product_id="%d"
+ class="add_to_cart_button ajax_add_to_cart add-to-cart">
+ %s
+ <span>Add to Cart</span>
+ </a>',
$ID,
- '',
- [
- 'type' => 'quantity',
- 'label' => 'Add to Order',
- 'min' => 0,
- 'max' => 30,
- 'step' => 1,
- 'data' => [
- 'price' => $fields['_price'],
- 'id' => $ID,
- 'name' => $fields['post_title'],
- 'step' => 1,
- 'add-to-cart' => '',
- ],
- 'add' => 'Add 1 '.$fields['post_title'].' to cart',
- 'remove' => 'Remove 1 '.$fields['title']. ' from cart',
- ]
+ $ID,
+ jvbIcon('plus-square')
);
+// $out .= Form::render(
+// $ID,
+// '',
+// [
+// 'type' => 'quantity',
+// 'label' => 'Add to Order',
+// 'min' => 0,
+// 'max' => 30,
+// 'step' => 1,
+// 'data' => [
+// 'price' => $fields['_price'],
+// 'id' => $ID,
+// 'name' => $fields['post_title'],
+// 'step' => 1,
+// 'add-to-cart' => '',
+// ],
+// 'add' => 'Add 1 '.$fields['post_title'].' to cart',
+// 'remove' => 'Remove 1 '.$fields['title']. ' from cart',
+// ]
+// );
}
$out .= '</div></div>';
diff --git a/inc/blocks/SummaryBlock.php b/inc/blocks/SummaryBlock.php
index 186ebbd..9ea9fd8 100644
--- a/inc/blocks/SummaryBlock.php
+++ b/inc/blocks/SummaryBlock.php
@@ -28,9 +28,7 @@
$this->cache = Cache::for('summary_block', 'post', WEEK_IN_SECONDS);
add_action('init', [ $this, 'registerBlock' ]);
add_action('wp_enqueue_scripts', [$this, 'enqueueScripts']);
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
}
public function registerBlock()
@@ -50,21 +48,10 @@
return (is_tax()) ? 'tax' : 'content';
}
- protected function generateKey():string
- {
- $obj = get_queried_object();
- return match (true) {
- is_tax() => jvbNoBase($obj->taxonomy) . $obj->term_id,
- is_a($obj, 'WP_Post_type') => jvbNoBase($obj->name),
- is_a($obj, 'WP_User') => jvbUserRole($obj->ID),
- default => jvbNoBase($obj->post_type) . $obj->ID,
- };
- }
-
public function render(array $attributes, string $content, WP_Block $block)
{
$this->config = $this->getConfig();
- $key = $this->generateKey();
+
if (is_tax()) {
$this->cache = Cache::for('summary_tax', 'term', WEEK_IN_SECONDS);
} elseif (is_author()) {
@@ -138,7 +125,7 @@
ob_start();
$this->renderBlock();
$content = ob_get_clean();
- $this->cache->set($key, $content);
+ $this->cache->set(get_queried_object_id(), $content);
return $content;
}
diff --git a/inc/blocks/TimelineBlock.php b/inc/blocks/TimelineBlock.php
index 3bf86e2..39d074c 100644
--- a/inc/blocks/TimelineBlock.php
+++ b/inc/blocks/TimelineBlock.php
@@ -4,6 +4,7 @@
use JVBase\managers\Cache;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
+use JVBase\rest\routes\ContentRoutes;
use WP_Block;
if (!defined('ABSPATH')) {
@@ -86,7 +87,7 @@
protected function renderHeader():void
{
$meta = Meta::forPost($this->parentID);
- $sharedFields = JVB()->routes('content')->getTimelineSharedFields($this->content);
+ $sharedFields = ContentRoutes::getInstance()->getTimelineSharedFields($this->content);
$fields = $meta->getAll($sharedFields);
$extra = $meta->getAll();
?>
@@ -170,7 +171,7 @@
{
$all = $this->children;
array_unshift($all, $this->parentID);
- $uniqueFields = JVB()->routes('content')->getTimelineUniqueFields($this->content);
+ $uniqueFields = ContentRoutes::getInstance()->getTimelineUniqueFields($this->content);
foreach ($all as $i => $ID) {
$meta = Meta::forPost($ID);
diff --git a/inc/forms/PostSelector.php b/inc/forms/PostSelector.php
index f6f564f..c68191d 100644
--- a/inc/forms/PostSelector.php
+++ b/inc/forms/PostSelector.php
@@ -185,8 +185,8 @@
}
// Check cache
- $cache_key = $this->cache->generateKey($args);
- $cached_result = $this->cache->get($cache_key);
+
+ $cached_result = $this->cache->get($args);
if ($cached_result) {
return new WP_REST_Response($cached_result);
}
@@ -224,7 +224,7 @@
];
// Cache the result
- $this->cache->set($cache_key, $result, 300); // 5 minute cache
+ $this->cache->set($args, $result, 300); // 5 minute cache
return new WP_REST_Response($result);
}
diff --git a/inc/helpers/renderFields.php b/inc/helpers/renderFields.php
index ec892dd..718b66d 100644
--- a/inc/helpers/renderFields.php
+++ b/inc/helpers/renderFields.php
@@ -603,8 +603,8 @@
}
$cache = Cache::for('tax_locations', 'term');
- $key = $cache->generateKey($location);
+ $cached = $cache->get($location);
$cached = false;
if ($cached) {
return $cached;
@@ -636,7 +636,7 @@
);
$cached = '<p class="find-us">'.jvbIcon('map-pin').'Find us here: '.$google.$apple.'</p>';
- $cache->set($key, $cached);
+ $cache->set($location, $cached);
return $cached;
}
diff --git a/inc/integrations/ServiceMap.php b/inc/integrations/ServiceMap.php
index 9386ea3..7cc2069 100644
--- a/inc/integrations/ServiceMap.php
+++ b/inc/integrations/ServiceMap.php
@@ -26,6 +26,15 @@
: false;
}
+ public function getServiceUser(string $service, ?int $userID = null):Integrations|false
+ {
+ $service = $this->getService($service);
+ if ($service->userID !== $userID && method_exists($service, 'switchUser')) {
+ $service->switchUser($userID);
+ }
+ return $service;
+ }
+
public function getAvailableServices():array
{
return array_filter(array_keys($this->serviceMap), function ($service) {
diff --git a/inc/integrations/_Base.php b/inc/integrations/_Base.php
index 03996ca..cc61055 100644
--- a/inc/integrations/_Base.php
+++ b/inc/integrations/_Base.php
@@ -2,6 +2,7 @@
namespace JVBase\integrations;
use JVBase\managers\Cache;
+use JVBase\managers\Errors;
use JVBase\managers\IconsManager;
if (!defined('ABSPATH')) {
@@ -108,7 +109,7 @@
protected function logError(string $method, string $message, array $context = []):void
{
$context['service'] = $this->service_name;
- JVB()->error()->log('['.self::class.']'.$method, $message, $context);
+ Errors::getInstance()->log('['.self::class.']'.$method, $message, $context);
}
protected function getReturnURL():string
diff --git a/inc/integrations/services/GoogleMapsOld.php b/inc/integrations/services/GoogleMapsOld.php
index aebaf87..0f87b97 100644
--- a/inc/integrations/services/GoogleMapsOld.php
+++ b/inc/integrations/services/GoogleMapsOld.php
@@ -202,7 +202,7 @@
'key' => $this->private_key
];
- $key = $this->cache->generateKey(['geocode', $address]);
+ $key =['geocode', $address];
$cached = $this->cache->get($key);
if ($cached) {
return $cached;
@@ -256,7 +256,7 @@
'key' => $this->private_key
];
- $key = $this->cache->generateKey(['reverse', $lat, $lng]);
+ $key = ['reverse', $lat, $lng];
$cached = $this->cache->get($key);
if ($cached) {
return $cached;
@@ -302,7 +302,7 @@
$default_fields = ['name', 'formatted_address', 'geometry', 'rating', 'formatted_phone_number'];
$fields = empty($fields) ? $default_fields : $fields;
- $key = $this->cache->generateKey(['place', $place_id, $fields]);
+ $key = ['place', $place_id, $fields];
$cached = $this->cache->get($key);
if ($cached) {
return $cached;
@@ -355,7 +355,7 @@
$params['type'] = $type;
}
- $key = $this->cache->generateKey(['nearby', $lat, $lng, $radius, $type]);
+ $key = ['nearby', $lat, $lng, $radius, $type];
$cached = $this->cache->get($key);
if ($cached) {
return $cached;
@@ -406,7 +406,7 @@
'key' => $this->private_key
];
- $key = $this->cache->generateKey(['distance', $origin_str, $dest_str, $mode]);
+ $key = ['distance', $origin_str, $dest_str, $mode];
$cached = $this->cache->get($key);
if ($cached) {
return $cached;
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
+ **************************************************************************/
}
diff --git a/inc/integrations/services/GoogleMyBusinessOld.php b/inc/integrations/services/GoogleMyBusinessOld.php
index 7a33151..111845f 100644
--- a/inc/integrations/services/GoogleMyBusinessOld.php
+++ b/inc/integrations/services/GoogleMyBusinessOld.php
@@ -143,9 +143,7 @@
]
);
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
}
protected function initialize(): void
diff --git a/inc/integrations/services/InstagramOld.php b/inc/integrations/services/InstagramOld.php
index a09aa47..378cb7b 100644
--- a/inc/integrations/services/InstagramOld.php
+++ b/inc/integrations/services/InstagramOld.php
@@ -7,6 +7,7 @@
namespace JVBase\integrations\services;
use JVBase\integrations\Integrations;
use JVBase\meta\Meta;
+use WP_Error;
if (!defined('ABSPATH')) {
exit;
@@ -165,14 +166,14 @@
}
public function isSetUp():bool {
- $fb = JVB()->connect('facebook');
+ $fb = Facebook::getInstance();
return $fb->isSetUp();
}
protected function getOAuthCredentials(): array
{
// Get Facebook integration
- $facebook = JVB()->connect('facebook');
+ $facebook = Facebook::getInstance();
if (!$facebook || !$facebook->isSetUp()) {
return [];
@@ -190,7 +191,7 @@
public function getCredentials():array {
$credentials = parent::getCredentials();
if (empty($credentials)) {
- $facebook = JVB()->connect('facebook');
+ $facebook = Facebook::getInstance();
if (!$facebook || !$facebook->isSetUp()) {
return [];
diff --git a/inc/integrations/services/UmamiOld.php b/inc/integrations/services/UmamiOld.php
index eb1df1e..bf4df17 100644
--- a/inc/integrations/services/UmamiOld.php
+++ b/inc/integrations/services/UmamiOld.php
@@ -145,10 +145,6 @@
*/
public function renderTrackingScript(): void
{
- // Skip on local environments
- if (JVB_TESTING) {
- return;
- }
if (!$this->isSetUp() || is_admin()) {
return;
}
diff --git a/inc/managers/CustomTable.php b/inc/managers/CustomTable.php
index c8a9171..bbe261f 100644
--- a/inc/managers/CustomTable.php
+++ b/inc/managers/CustomTable.php
@@ -1178,7 +1178,7 @@
private function logError(string $operation, array $context = []): void
{
if (function_exists('JVB')) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
$this->tableName,
"CustomTable {$operation} failed: " . $this->wpdb->last_error,
$context,
diff --git a/inc/managers/Dashboard/Dashboard.php b/inc/managers/Dashboard/Dashboard.php
index 43d6c52..0b4b4fb 100644
--- a/inc/managers/Dashboard/Dashboard.php
+++ b/inc/managers/Dashboard/Dashboard.php
@@ -19,9 +19,7 @@
private function __construct() {
self::$based = BASE.$this->slug;
$this->cache = Cache::for('dashboard', 'post');
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
$this->registerDashboard();
$this->buildPages();
$this->buildSections();
diff --git a/inc/managers/Dashboard/DashboardPage.php b/inc/managers/Dashboard/DashboardPage.php
index bc0c040..af4145c 100644
--- a/inc/managers/Dashboard/DashboardPage.php
+++ b/inc/managers/Dashboard/DashboardPage.php
@@ -24,10 +24,8 @@
protected Cache $cache;
public function __construct(string $title, string $slug = '', string $icon ='', int $parent = 0) {
- $this->cache = Cache::for('dashboard');
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+ $this->cache = Cache::for('dash_pages');
+
$this->title = $title;
$this->setSlug(empty($slug) ? $title : $slug);
$this->icon = $icon;
diff --git a/inc/managers/DashboardManager.php b/inc/managers/DashboardManager.php
index 35cad18..fc91ddf 100644
--- a/inc/managers/DashboardManager.php
+++ b/inc/managers/DashboardManager.php
@@ -28,9 +28,7 @@
public function __construct()
{
$this->cache = Cache::for('dashboard', WEEK_IN_SECONDS)->user();
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
add_action('init', [$this, 'registerDashboard']);
@@ -964,10 +962,11 @@
if ($connection !== 'integrations') {
$userID = (Site::has('has_membership')) ? $this->user->ID : null;
- $integration = JVB()->connect($connection, $userID);
-
- echo '<h1>Managing '.$integration->title.'</h1>';
- $integration->renderDefaults();
+ $integration = $this->getServiceUser($connection, $userID);
+ if (method_exists($integration, 'renderDefaults')) {
+ echo '<h1>Managing '.$integration->title.'</h1>';
+ $integration->renderDefaults();
+ }
} else {
?>
<section class="item-grid integrations">
diff --git a/inc/managers/DirectoryManager.php b/inc/managers/DirectoryManager.php
index 23bd63b..4f46e0f 100644
--- a/inc/managers/DirectoryManager.php
+++ b/inc/managers/DirectoryManager.php
@@ -6,6 +6,7 @@
}
use JVBase\Instance;
+use JVBase\integrations\services\Umami;
use JVBase\registrar\Registrar;
use JVBase\base\Site;
use WP_Block;
@@ -31,9 +32,7 @@
$this->perPage = $perPage;
$this->cache = Cache::for('directory', WEEK_IN_SECONDS);
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
jvb_register_do_once('buildDirectories', [$this, 'activate']);
add_action('init', [$this, 'registerDirectories']);
@@ -680,7 +679,7 @@
public function renderLettersList(array $list, string $type):string
{
- $umami = JVB()->connect('umami');
+ $umami = Umami::getInstance();
$out = '<ul class="list-none">';
foreach ($list as $letter => $items) {
diff --git a/inc/managers/Favourites.php b/inc/managers/Favourites.php
index c48e42d..66370a0 100644
--- a/inc/managers/Favourites.php
+++ b/inc/managers/Favourites.php
@@ -812,7 +812,7 @@
'item_id' => $post_id
])->deleteResults();
} catch (Exception $e) {
- JVB()->error()->log('cleanupPostFavourites', $e->getMessage(), [
+ Errors::getInstance()->log('cleanupPostFavourites', $e->getMessage(), [
'post_id' => $post_id
]);
}
@@ -835,7 +835,7 @@
'item_id' => $term_id
])->deleteResults();
} catch (Exception $e) {
- JVB()->error()->log('cleanupTermFavourites', $e->getMessage(), [
+ Errors::getInstance()->log('cleanupTermFavourites', $e->getMessage(), [
'term_id' => $term_id,
'taxonomy'=> $taxonomy
]);
diff --git a/inc/managers/IconsManager.php b/inc/managers/IconsManager.php
index cf48409..b3b5d62 100644
--- a/inc/managers/IconsManager.php
+++ b/inc/managers/IconsManager.php
@@ -26,6 +26,15 @@
protected array $map = [];
protected const MAX_VERSIONS = 5;
+ protected string $timestampKey;
+ protected string $iconKey;
+ protected string $iconHistoryKey;
+ protected static string $allIcons = 'icons_all_used';
+ protected static string $updateIcons = 'icons_needs_update';
+ protected static string $iconMap = 'icons_map';
+
+
+
/**
* Factory method - get or create instance for a source
*/
@@ -34,6 +43,9 @@
if (!isset(self::$instances[$source])) {
self::$instances[$source] = new self($source);
}
+ self::$instances[$source]->setTimestampKey(BASE.'icons_'.$source.'_timestamp');
+ self::$instances[$source]->setIconKey(BASE.'icons_'.$source);
+ self::$instances[$source]->setIconHistoryKey(BASE.'icons_history_'.$source);
return self::$instances[$source];
}
@@ -72,6 +84,19 @@
$this->registerInstanceHooks();
}
+ protected function setIconKey(string $key):void
+ {
+ $this->iconKey = $key;
+ }
+ protected function setTimestampKey(string $key):void
+ {
+ $this->timestampKey = $key;
+ }
+ protected function setIconHistoryKey(string $key):void
+ {
+ $this->iconHistoryKey = $key;
+ }
+
/**
@@ -124,7 +149,7 @@
*/
protected function loadStoredIcons(): void
{
- $allIcons = get_option(BASE.'usedIcons', []);
+ $allIcons = get_option(BASE.self::$allIcons, []);
$storedIcons = $allIcons[$this->source] ?? [];
// Merge stored icons with any existing icons (like custom icons)
@@ -304,20 +329,19 @@
*/
protected function saveIcons(): void
{
- $allIcons = [];
- foreach (self::$instances as $source => $instance) {
- $allIcons[$source] = $instance->icons;
- }
+ $allIcons = array_map(function ($instance) {
+ return $instance->icons;
+ }, self::$instances);
- update_option(BASE.'usedIcons', $allIcons);
+ update_option(BASE.self::$allIcons, $allIcons);
// Track WHICH source needs updating
- $needsUpdate = get_option(BASE.'icons_needs_update', []);
+ $needsUpdate = get_option(BASE.self::$updateIcons, []);
if (!is_array($needsUpdate)) {
$needsUpdate = [];
}
$needsUpdate[$this->source] = true;
- update_option(BASE.'icons_needs_update', $needsUpdate);
+ update_option(BASE.self::$updateIcons, $needsUpdate);
}
/**
@@ -345,7 +369,7 @@
protected function addMap(): void
{
- $map = get_option(BASE.'iconMap');
+ $map = get_option(BASE.self::$iconMap);
if (!$map) {
$map = [
'seo' => 'robot'
@@ -362,7 +386,7 @@
if (Site::hasAnyIntegration()) {
$map['integrations'] = 'plugs-connected';
}
- update_option(BASE.'iconMap', $map);
+ update_option(BASE.self::$iconMap, $map);
}
$this->map = apply_filters('jvbMapIcons', $map);
@@ -404,10 +428,13 @@
public static function checkCSS(): void
{
- $needsUpdate = get_option(BASE.'icons_needs_update', []);
+ $needsUpdate = get_option(BASE.self::$updateIcons, []);
+ $needsUpdate = array_filter($needsUpdate, function ($item) {
+ return $item === true;
+ });
if (!empty($needsUpdate)) {
error_log('Regenerating CSS for sources: ' . implode(', ', array_keys($needsUpdate)));
- delete_option(BASE.'icons_needs_update');
+ delete_option(BASE.self::$updateIcons);
self::regenerateAllCSS($needsUpdate);
}
}
@@ -422,7 +449,7 @@
}
// Load all icons from database option
- $allIcons = get_option(BASE.'usedIcons', []);
+ $allIcons = get_option(BASE.self::$allIcons, []);
// If no specific sources provided, regenerate all
if (empty($sourcesToUpdate)) {
@@ -535,7 +562,7 @@
}
// Track usage - only if not already tracked
- if (!isset($this->icons[$style])) {
+ if (!array_key_exists($style, $this->icons)) {
$this->icons[$style] = [];
}
@@ -649,7 +676,7 @@
public function registerStyle(): void
{
- $timestamp = Cache::for('icons_'.$this->source)->getTimestamp();
+ $timestamp = get_option($this->timestampKey);
$handle = 'jvb-icons-' . $this->source;
wp_register_style(
@@ -687,7 +714,7 @@
}
}
}
-
+ update_option($this->timestampKey, time());
return $this->minifyCss($css);
}
@@ -743,9 +770,8 @@
*/
public function clearIconCache(): void
{
- delete_option(BASE . 'icon_usage_list'); // Legacy
- delete_option(BASE.'usedIcons');
- delete_option(BASE.'iconMap');
+ delete_option(self::$allIcons);
+ delete_option(self::$iconMap);
// Clear cache for all sources
foreach (self::$instances as $source => $instance) {
@@ -777,12 +803,12 @@
$history = array_slice($history, 0, self::MAX_VERSIONS);
}
- update_option(BASE.'icon_css_history_' . $this->source, $history);
+ update_option($this->iconHistoryKey, $history);
}
public function getVersionHistory(): array
{
- return get_option(BASE.'icon_css_history_' . $this->source, []);
+ return get_option($this->iconHistoryKey, []);
}
public function restoreVersion(int $timestamp): bool
@@ -818,12 +844,12 @@
public function forceRefresh(): void
{
$this->clearIconCache();
- $needsUpdate = get_option(BASE.'icons_needs_update', []);
+ $needsUpdate = get_option(BASE.self::$updateIcons, []);
if (!is_array($needsUpdate)) {
$needsUpdate = [];
}
$needsUpdate[$this->source] = true;
- update_option(BASE.'icons_needs_update', $needsUpdate);
+ update_option(BASE.self::$updateIcons, $needsUpdate);
Cache::for('icons_'.$this->source)->flush();
}
@@ -834,7 +860,7 @@
return false;
}
- $history = get_option(BASE.'icon_css_history_' . $this->source, []);
+ $history = get_option($this->iconHistoryKey, []);
$merged_icons = [];
// Collect icons from selected versions
diff --git a/inc/managers/InvitationsManager.php b/inc/managers/InvitationsManager.php
index 45178b4..0f95ad8 100644
--- a/inc/managers/InvitationsManager.php
+++ b/inc/managers/InvitationsManager.php
@@ -390,7 +390,7 @@
} catch (Exception $e) {
$this->table->rollback();
- JVB()->error()->log(
+ Errors::getInstance()->log(
'invitation_create',
'Error processing invitations: ' . $e->getMessage(),
['user_id' => $userID],
diff --git a/inc/managers/Login.php b/inc/managers/Login.php
index c344023..77e3d2b 100644
--- a/inc/managers/Login.php
+++ b/inc/managers/Login.php
@@ -771,7 +771,7 @@
if (!Site::hasIntegration('cloudflare')) {
return;
}
- JVB()->connect('cloudflare')->renderTurnstile();
+ Cloudflare::getInstance()->renderTurnstile();
}
protected function maybeTurnstileScripts(): void
diff --git a/inc/managers/MagicLinks.php b/inc/managers/MagicLinks.php
index 3217948..4846d4a 100644
--- a/inc/managers/MagicLinks.php
+++ b/inc/managers/MagicLinks.php
@@ -6,6 +6,7 @@
use JVBase\Instance;
use JVBase\integrations\services\Cloudflare;
use JVBase\meta\Form;
+use JVBase\rest\routes\LoginRoutes;
use JVBase\ui\Tabs;
use WP_User;
use WP_Error;
@@ -380,7 +381,7 @@
#[NoReturn] protected function processSignup(array $token_data): void
{
if (!array_key_exists('email', $token_data) || !array_key_exists('name', $token_data)) {
- JVB()->error()->log('MagicLinkManager', 'Could not process Signup');
+ Errors::getInstance()->log('MagicLinkManager', 'Could not process Signup');
$this->cleanURL();
}
$user_id = wp_create_user(
@@ -427,7 +428,7 @@
protected function processReferralSignup(array $token_data): void
{
if (!array_key_exists('email', $token_data) || !array_key_exists('name', $token_data)) {
- JVB()->error()->log('[MagicLinkManager]Could not process Referral Signup');
+ Errors::getInstance()->log('[MagicLinkManager]Could not process Referral Signup');
return;
}
@@ -447,13 +448,13 @@
'role' => $role
]);
if (!is_wp_error($user_id)) {
- $response = JVB()->routes('login')->login($email, $pass, true);
- if ($response) {
+ $response = LoginRoutes::getInstance()->login($email, $pass, true);
+ if (!is_wp_error($response)) {
wp_safe_redirect(home_url('/dash?welcome=1&referral=1'));
exit;
}
} else {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[MagicLinkManager]',
$user_id->get_error_message(),
$token_data
@@ -470,7 +471,7 @@
$user = get_user_by('ID', $token_data['user_id']);
if (!$user) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'MagicLinkManager',
'Invalid user, could not reset password',
);
diff --git a/inc/managers/OperationQueue.php b/inc/managers/OperationQueue.php
index 949e5c6..77ba35a 100644
--- a/inc/managers/OperationQueue.php
+++ b/inc/managers/OperationQueue.php
@@ -547,7 +547,7 @@
];
} catch (Exception $e) {
- JVB()->error()->log('queue', $e->getMessage(), $data, 'high');
+ Errors::getInstance()->log('queue', $e->getMessage(), $data, 'high');
return new WP_Error('queue_failed', $e->getMessage());
}
}
@@ -1029,7 +1029,7 @@
);
// Log this as a critical error
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[OperationQueue]:restartStuckOperations',
"Operation failed after maximum retries",
[
@@ -1057,7 +1057,7 @@
);
// Log the backoff
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[OperationQueue]:restartStuckOperations',
"Operation requeued with exponential backoff",
[
@@ -1184,7 +1184,7 @@
if (!is_array($filterResult) || !isset($filterResult['success'])) {
// Log invalid filter response and quit early
$invalid_response = is_object($filterResult) ? get_class($filterResult) : gettype($filterResult);
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[OperationQueue]:processOperation',
"Invalid filter response format - expected array with 'success' key",
[
@@ -1348,7 +1348,7 @@
} catch (Exception $e) {
// Handle exception...
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[OperationQueue]:processOperation',
"Exception during operation processing: " . $e->getMessage(),
[
@@ -1887,7 +1887,7 @@
return $value;
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[OperationQueue]:getOperationValue',
'Error retrieving operation value: ' . $e->getMessage(),
[
diff --git a/inc/managers/Referrals.php b/inc/managers/Referrals.php
index 71769f7..3fc2f45 100644
--- a/inc/managers/Referrals.php
+++ b/inc/managers/Referrals.php
@@ -66,11 +66,6 @@
$this->cache = Cache::for('referrals', WEEK_IN_SECONDS);
// $this->requestCache = Cache::for('referral_requests', WEEK_IN_SECONDS)->connect('referrals', true);
$this->statsCache = Cache::for('referral_stats', WEEK_IN_SECONDS)->connect('referrals', true)->user();
- if (JVB_TESTING) {
- $this->cache->flush();
-// $this->requestCache->flush();
- $this->statsCache->flush();
- }
$this->referralPage = $this->getReferralPageId();
$this->settings = $this->getRewardSettings();
@@ -852,7 +847,7 @@
public function getTopReferrers(int $limit = 10, string $period = 'all'): array
{
return $this->statsCache->remember(
- $this->statsCache->generateKey(['per_page' => $limit, 'period' => $period]),
+ ['per_page' => $limit, 'period' => $period],
function() use ($limit, $period) {
$where = '';
if ($period !== 'all') {
diff --git a/inc/managers/Responses.php b/inc/managers/Responses.php
index 73bf4dc..555c688 100644
--- a/inc/managers/Responses.php
+++ b/inc/managers/Responses.php
@@ -157,6 +157,11 @@
'message' => 'Response content is empty'
];
}
+
+ $registrar = Registrar::getInstance($type);
+ if ($registrar) {
+ $type = $registrar->getBased();
+ }
$created = $this->responses->insert([
'item_id' => $item_id,
'user_id' => $user_id,
@@ -337,15 +342,19 @@
return $responses;
}
- public function getAllItemResponses(int $itemID, array $args = [], bool $includeChildren = true):array
+ public function getAllItemResponses(int $itemID, array $oldArgs = [], bool $includeChildren = true):array
{
- $args = wp_parse_args($args, [
+ $args = wp_parse_args($oldArgs, [
'orderby' => 'created_at',
'order' => 'DESC',
'page' => 1,
'per_page' => 20,
]);
+ if (array_key_exists('type', $oldArgs) || array_key_exists('content', $oldArgs) || array_key_exists('post_type', $oldArgs)) {
+ $args['type'] = jvbCheckBase($oldArgs['type']??$oldArgs['content']??$oldArgs['post_type']);
+ }
+
$where = [
'item_id' => $itemID,
'parent_id' => null
diff --git a/inc/managers/SEO/render/SchemaOutput.php b/inc/managers/SEO/render/SchemaOutput.php
index 41ce0c8..c26af60 100644
--- a/inc/managers/SEO/render/SchemaOutput.php
+++ b/inc/managers/SEO/render/SchemaOutput.php
@@ -98,9 +98,7 @@
if (!is_front_page()) {
$website = SchemaHelper::getInstance()::schema('website');
if (!empty($website)) {
- if (JVB_TESTING) {
- Cache::for('websiteSchema')->flush();
- }
+
$website = Cache::for('websiteSchema')->remember(
'schema',
function () {
diff --git a/inc/managers/SEO/render/Traits/_Properties/reviewTrait.php b/inc/managers/SEO/render/Traits/_Properties/reviewTrait.php
index 4c677b7..5e0ddc3 100644
--- a/inc/managers/SEO/render/Traits/_Properties/reviewTrait.php
+++ b/inc/managers/SEO/render/Traits/_Properties/reviewTrait.php
@@ -1,6 +1,7 @@
<?php
namespace JVBase\managers\SEO\render\Traits\_Properties;
+use JVBase\integrations\services\GoogleMyBusiness;
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;
@@ -169,7 +170,8 @@
{
$userID = (int) get_post_meta($meta->id(), BASE.'profile_link', true);
if ($userID && $userID > 0) {
- $integration = JVB()->connect('gmb', $userID);
+ $integration = GoogleMyBusiness::getInstance();
+ $integration->switchUser($userID);
if ($integration && $integration->isSetUp()){
$fetched = $integration->getReviews(20);
diff --git a/inc/managers/TaxonomyRelationships.php b/inc/managers/TaxonomyRelationships.php
index 1462dd2..dc7a2d0 100644
--- a/inc/managers/TaxonomyRelationships.php
+++ b/inc/managers/TaxonomyRelationships.php
@@ -197,7 +197,7 @@
{
$term_posts = $this->cache->remember(
- $this->cache->generateKey(['id' => $term_id, 'taxonomy' => $taxonomy]),
+ ['id' => $term_id, 'taxonomy' => $taxonomy],
function () use ($term_id, $taxonomy) {
global $wpdb;
return $wpdb->get_col($wpdb->prepare(
@@ -212,7 +212,7 @@
$related_term_posts = $this->cache->remember(
- $this->cache->generateKey(['id' => $related_term_id, 'taxonomy' => $related_taxonomy]),
+ ['id' => $related_term_id, 'taxonomy' => $related_taxonomy],
function () use($related_term_id, $related_taxonomy) {
global $wpdb;
return $wpdb->get_col($wpdb->prepare(
diff --git a/inc/managers/UserTermsManager.php b/inc/managers/UserTermsManager.php
index 80995cc..5ce2829 100644
--- a/inc/managers/UserTermsManager.php
+++ b/inc/managers/UserTermsManager.php
@@ -318,7 +318,7 @@
'result' => $results
];
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[UserTermsManager]:processOperation',
"Exception during operation processing: " . $e->getMessage(),
[
diff --git a/inc/managers/queue/Queue.php b/inc/managers/queue/Queue.php
index c668f4c..6fb6242 100644
--- a/inc/managers/queue/Queue.php
+++ b/inc/managers/queue/Queue.php
@@ -5,6 +5,7 @@
}
use JVBase\Instance;
+use JVBase\managers\Errors;
use JVBase\rest\routes\QueueRoutes;
use WP_Error;
use WP_REST_Request;
@@ -103,7 +104,7 @@
];
} catch (\Exception $e) {
- JVB()->error()->log('queue', $e->getMessage(), $data, 'high');
+ Errors::getInstance()->log('queue', $e->getMessage(), $data, 'high');
return new WP_Error('queue_failed', $e->getMessage());
}
}
diff --git a/inc/managers/queue/executors/ContentExecutor.php b/inc/managers/queue/executors/ContentExecutor.php
index 2755eb9..bc6ee4b 100644
--- a/inc/managers/queue/executors/ContentExecutor.php
+++ b/inc/managers/queue/executors/ContentExecutor.php
@@ -2,6 +2,7 @@
namespace JVBase\managers\queue\executors;
use JVBase\managers\queue\{Executor, Operation, Progress, Result, Storage};
+use JVBase\managers\Errors;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
use Exception;
@@ -43,7 +44,7 @@
};
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[ContentExecutor]:execute',
$e->getMessage(),
[
diff --git a/inc/managers/queue/executors/IntegrationExecutor.php b/inc/managers/queue/executors/IntegrationExecutor.php
index 9af8556..3896fa5 100644
--- a/inc/managers/queue/executors/IntegrationExecutor.php
+++ b/inc/managers/queue/executors/IntegrationExecutor.php
@@ -3,6 +3,9 @@
use JVBase\managers\queue\{Executor, Operation, Progress, Result};
use Exception;
+use JVBase\integrations\Integrations;
+use JVBase\integrations\ServiceMap;
+use JVBase\managers\Errors;
if (!defined('ABSPATH')) {
exit;
@@ -28,11 +31,8 @@
*/
final class IntegrationExecutor implements Executor
{
- /**
- * Map of integration service names to class identifiers.
- * Populated on first use from JVB()->connect().
- */
- private array $integrationCache = [];
+ use ServiceMap;
+
public function execute(Operation $operation, Progress $progress): Result
{
@@ -60,7 +60,7 @@
};
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[IntegrationExecutor]:execute',
$e->getMessage(),
[
@@ -105,7 +105,7 @@
if ($userId === 0) {
$userId = null;
}
- return JVB()->connect($serviceName, $userId);
+ return $this->getServiceUser($serviceName, $userId);
}
/*****************************************************************
diff --git a/inc/meta/Storage.php b/inc/meta/Storage.php
index 2cb37cf..f5b24a2 100644
--- a/inc/meta/Storage.php
+++ b/inc/meta/Storage.php
@@ -3,6 +3,7 @@
use Exception;
use JVBase\managers\Cache;
+use JVBase\managers\Errors;
if (!defined('ABSPATH')) {
exit;
@@ -163,14 +164,13 @@
$this->wpdb->query('COMMIT');
// Update post modified timestamp
- Cache::invalidateItem($item->objectType, $item->id);
$this->clearCache($item);
return true;
} catch (Exception $e) {
$this->wpdb->query('ROLLBACK');
- JVB()->error()->log('meta_storage', $e->getMessage(), [
+ Errors::getInstance()->log('meta_storage', $e->getMessage(), [
'item_id' => $item->id,
'object_type' => $item->objectType,
'fields' => array_keys($dirty)
@@ -326,7 +326,7 @@
$results[$meta->item()->id ?? 'options'] = false;
}
- JVB()->error()->log('meta_storage', 'Bulk save failed: ' . $e->getMessage(), [], 'error');
+ Errors::getInstance()->log('meta_storage', 'Bulk save failed: ' . $e->getMessage(), [], 'error');
return $results;
}
@@ -609,12 +609,21 @@
public function clearCache(Item $item): void
{
- match ($item->objectType) {
- 'post' => clean_post_cache($item->id),
- 'term' => clean_term_cache($item->id),
- 'user', 'integrations' => clean_user_cache($item->id),
- default => null
- };
+ switch ($item->objectType) {
+ case 'post':
+ Cache::clearPost($item->id);
+ clean_post_cache($item->id);
+ break;
+ case 'term':
+ Cache::clearTerm($item->id);
+ clean_term_cache($item->id);
+ break;
+ case 'user':
+ case 'integrations':
+ Cache::clearUser($item->id);
+ clean_user_cache($item->id);
+ break;
+ }
}
// ─────────────────────────────────────────────────────────────
diff --git a/inc/registrar/Posts.php b/inc/registrar/Posts.php
index de0f72a..8922af7 100644
--- a/inc/registrar/Posts.php
+++ b/inc/registrar/Posts.php
@@ -356,7 +356,7 @@
}
if (is_wp_error($registered)) {
- JVB()->error()->log('JVBase\registrar\Posts', 'Could not register post type', $registered->get_error_messages());
+ Errors::getInstance()->log('JVBase\registrar\Posts', 'Could not register post type', $registered->get_error_messages());
}
}
diff --git a/inc/registrar/Registrar.php b/inc/registrar/Registrar.php
index 3cc1b10..821c6db 100644
--- a/inc/registrar/Registrar.php
+++ b/inc/registrar/Registrar.php
@@ -1070,9 +1070,6 @@
if ($block['blockName'] !== 'core/post-content') {
return $content;
}
- if (JVB_TESTING) {
- Cache::for($this->slug)->flush();
- }
$per_page = 10;
$page = $_GET['tp']??1;
@@ -1089,7 +1086,7 @@
'order' => 'desc',
]);
- $cache = Cache::for($this->slug)->connect('taxonomy');
+ $cache = Cache::for($this->slug, 'term');
$max = $cache->remember(
'max',
function () {
@@ -1131,7 +1128,7 @@
$out = $nav. Cache::for($this->slug)->remember(
- $cache->generateKey(['type' =>'contentArchive', ... $args]),
+ ['type' =>'contentArchive', ... $args],
function() use ($args) {
diff --git a/inc/registrar/config/seo/Schema.php b/inc/registrar/config/seo/Schema.php
index c87147d..e12796f 100644
--- a/inc/registrar/config/seo/Schema.php
+++ b/inc/registrar/config/seo/Schema.php
@@ -158,9 +158,7 @@
public function outputContentTaxArchiveSchema():array
{
$ID = get_the_ID();
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
return $this->cache->remember(
$ID,
function() use ($ID) {
@@ -264,13 +262,7 @@
$itemList->setItemListElement($itemListItems);
$class->setMainEntity($itemList);
- $schema = $class->outputSchema();
-
- if (JVB_TESTING) {
-// error_log('Generated archive schema: '.print_r($schema, true));
- }
-
- return $schema;
+ return $class->outputSchema();
}
);
}
diff --git a/inc/rest/RegisterRoutes.php b/inc/rest/RegisterRoutes.php
deleted file mode 100644
index 76c0710..0000000
--- a/inc/rest/RegisterRoutes.php
+++ /dev/null
@@ -1,359 +0,0 @@
-<?php
-namespace JVBase\rest;
-
-if (!defined('ABSPATH')) {
- exit;
-}
-use JVBase\meta\Meta;
-use WP_Error;
-use WP_REST_Request;
-use WP_REST_Response;
-
-/**
- * @deprecated
- */
-class RegisterRoutes extends RestRouteManager {
-
- protected array $config;
- protected array $tables = [];
- protected $wpdb;
- public function __construct(
- string $content,
- array $config
- ) {
- $this->route = $content;
- $this->config = $config;
- $this->cache_name = $content;
-
-
- parent::__construct();
-
- global $wpdb;
- $this->wpdb = $wpdb;
-
- if (jvbCheck('invitable', $this->config)) {
- foreach ($this->config['for_content'] as $c) {
- $this->tables[$c] = BASE .'invitations_'.$c;
- }
- }
-
- $this->action = 'dash-';
- add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
- }
-
- public function registerRoutes()
- {
- register_rest_route($this->namespace, "/{$this->route}", [
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'handleGET'],
- 'permission_callback' => [$this, 'checkPermission'],
- ],
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'handlePOST'],
- 'permission_callback' => [$this, 'checkPermission'],
- ]
- ]);
-
- if (jvbCheck('invitable', $this->config)) {
- register_rest_route($this->namespace, "/{$this->route}/members", [
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'getInvitations'],
- 'permission_callback' => [$this, 'checkPermission'],
- ],
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'handleActions'],
- 'permission_callback' => [$this, 'checkPermission'],
- ]
- ]);
- }
-
- if (jvbCheck('verify_entry', $this->config)) {
- register_rest_Route($this->namespace, "/{$this->route}/requests", [
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'handleInvite'],
- 'permission_callback' => [$this, 'checkPermission']
- ]
- ]);
- }
-
- }
-
- public function checkPermission(WP_REST_Request $request):bool
- {
- if ($this->route === 'options' && !current_user_can('manage_options')) {
- return false;
- } elseif (array_key_exists('is_owned_by', $this->config)) {
- $term = $request->get_param('term_id');
- if (!$this->checkTerm([
- 'term_id' => $term,
- 'taxonomy' => $this->route
- ])) {
- return false;
- }
- if (!current_user_can('manage_'.$this->route.'_'.$term)) {
- return false;
- }
- }
- return parent::checkPermission($request);
- }
-
- public function handleGET(WP_REST_Request $request):WP_REST_Response
- {
-
- }
-
- public function handlePOST(WP_REST_Request $request):WP_REST_Response
- {
- $data = $request->get_params();
- $user = $data['user'];
- if (!$this->checkUser($user) || !$this->userCheck($user)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'Looks like you may not be who you say you are...'
- ]);
- }
- if ($this->route === 'shop' && !$this->checkTerm([
- 'term_id' => $data['shop'],
- 'taxonomy' => $this->route
- ])) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'This shop doesn\'t exist?'
- ]);
- }
- $queue = Queue::getInstance();
- unset($data['user']);
- $operationID = $data['id'];
- unset($data['id']);
-
- $queue->queueOperation(
- $this->route.'_update',
- $user,
- $data,
- [
- 'operation_id' => $operationID,
- 'priority' => 'high',
- ]
- );
- return new WP_REST_Response([
- 'success' => true,
- 'message' => 'Successfully queued for processing'
- ]);
- }
-
- public function processOperation(WP_Error|array $result, object $operation, array $data):WP_Error|array
- {
- switch ($operation->type) {
- case $this->route.'_update':
- return $this->handleUpdateOperation($operation->user_id, $data);
- default:
- return $result;
- }
- }
- protected function handleUpdateOperation(int $userID, array $data):WP_Error|array
- {
- if ($this->route === 'options') {
- if (!user_can($userID, 'manage_options')) {
- return [
- 'success' => false,
- 'error' => 'User cannot change options'
- ];
- }
- $meta = Meta::forOptions($this->route);
- } else {
- $termID = (int) $data['term_id'];
- if (!user_can($userID, 'manage_'.$this->route.'_'.$termID)) {
- return [
- 'success' => false,
- 'error' => 'User cannot manage this '.$this->route
- ];
- }
- $meta = Meta::forTerm($termID);
- }
-
- $results = [];
-
- $allowed = array_filter($data, function ($v, $k) {
- return array_key_exists($v, $this->config['fields']??[]);
- }, ARRAY_FILTER_USE_BOTH);
-
-
- foreach ($allowed as $name => $value) {
- if (empty($value)) {
- $results[] = $meta->delete($name);
- } else {
- $results[] = $meta->set($name, $value);
- }
- }
- //Allow plugins & themes to process extra data here
- //Example: custom image generation logic
- $results = array_merge($results, apply_filters('jvb_'.$this->route.'_update_extra', [], $data));
-
- return [
- 'success' => true,
- 'message' => $this->route.' successfully updated',
- 'results' => $results
- ];
- }
- public function getInvitations(WP_REST_Request $request):WP_REST_Response
- {
- $termID = (int) $request->get_param('term_id');
- if (!$this->checkTerm(['term_id' => $termID, 'taxonomy' => $this->route])) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'Invalid shop'
- ]);
- }
- $status = $request->get_param('status') ?? 'all';
- $page = $request->get_param('page') ?? 1;
- $role = $request->get_param('content') ?? $this->config['for_content'][0];
- return JVB()->routes('invites')->getTermInvitations(['to_term' => $termID, 'status' => $status, 'page' => $page, 'taxonomy' => $this->route, 'role' => $role]);
- }
-
- public function handleActions(WP_REST_Request $request):WP_REST_Response
- {
- $action = $request->get_param('action');
- $termID = (int)$request->get_param('term_id');
- $userID = (int)$request->get_param('user');
- if (!$this->checkTerm(['term_id' => $termID, 'taxonomy' => $this->route]) || !$this->checkUser($userID)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'Invalid shop or user'
- ]);
- }
-
- switch ($action) {
- case 'add_user':
- $return = $this->addUserToTerm($userID, $termID);
- break;
- case 'remove_user':
- $return = $this->removeUserFromTerm($userID, $termID);
- break;
- case 'add_invitation':
- $invitation = JVB()->routes('invites')->createInvitation(
- sanitize_text_field($request->get_param('name')),
- sanitize_email($request->get_param('email')),
- $userID,
- sanitize_text_field($request->get_param('role')) ?? $this->config['for_content'][0],
- $termID,
- $this->route
- );
- if (is_wp_error($invitation)) {
- $return = [
- 'success' => false,
- 'message' => $invitation->get_error_message()
- ];
- }else {
- $return = [
- 'success' => true,
- 'message' => 'Invitation sent successfully'
- ];
- }
- break;
- case 'remove_invitation':
-
- $targetUser = sanitize_text_field($request->get_param('target_user'));
- $return = $this->removeTermInvite($userID, $termID, $targetUser);
- break;
- case 'process_request':
- $request_id = sanitize_text_field($request->get_param('request_id'));
- $decision = $request->get_param('decision');
- $notes = $request->get_param('notes');
- $return = $this->processTermRequest($request_id, $decision, $notes, $userID);
- break;
- default:
- $return = [
- 'success' => false,
- 'message' => 'invalid action'
- ];
- }
- return new WP_REST_Response($return);
- }
-
-
- public function handleInvite(WP_REST_Request $request):WP_REST_Response
- {
-
- }
-
- public function requestEntry(int $userID, string $role, int $termID, string $taxonomy):bool
- {
- if (!$this->checkUser($userID) || !$this->checkTerm(['term_id' => $termID, 'taxonomy' => $taxonomy])) {
- return false;
- }
-
- $tableName = $this->wpdb->prefix . BASE . $role . '_' . $taxonomy . '_requests';
-
- //Check if request already exists
- $existing = $this->wpdb->get_var($this->wpdb->prepare(
- "SELECT id FROM {$tableName} WHERE user_id = %d AND term_id = %d",
- $userID,
- $termID
- ));
-
- if ($existing) {
- return false;
- }
-
- //get the user's profile id
- $profileID = get_user_meta($userID, BASE.'profile_link', true);
- if (!$profileID) {
- return false;
- }
-
- $result = $this->wpdb->insert(
- $tableName,
- [
- 'user_id' => $userID,
- 'content_id' => $profileID,
- 'term_id' => $termID,
- 'status' => 'requested',
- 'created_date' => current_time('mysql')
- ]
- );
-
- if ($result === false) {
- return false;
- }
-
- $this->notifyManagers($termID, $userID, $profileID);
- return true;
- }
-
- protected function notifyManagers(int $termID, int $userID, int $profileID):void
- {
- if (!$this->checkTerm(['term_id' => $termID, 'taxonomy' => $this->route]) || !$this->checkUser($userID)) {
- return;
- }
-
- $termMeta = Meta::forTerm($termID);
- $managers = explode(',', $termMeta->get('managers'));
- $owner = explode(',', $termMeta->get('owner'));
-
- $owners = array_unique(array_merge($managers, $owner));
-
- //Get requester's info
- $userName = get_the_title($profileID);
- $termName = get_term($termID, BASE.$this->route)->name;
-
-
- //Notify managers
- NotificationManager::getInstance()->addNotification(
- $owners,
- 'entry_request',
- [
- 'profile_id' => $profileID,
- 'user_name' => $userName,
- 'user_id' => $userID,
- 'term_id' => $termID,
- 'term_name' => $termName
- ]
- );
-
- }
-}
diff --git a/inc/rest/Rest.php b/inc/rest/Rest.php
index 4741e66..621329e 100644
--- a/inc/rest/Rest.php
+++ b/inc/rest/Rest.php
@@ -4,9 +4,11 @@
use JVBase\Instance;
use JVBase\integrations\services\Cloudflare;
use JVBase\managers\Cache;
+use JVBase\managers\Errors;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
use JVBase\base\Site;
+use JVBase\rest\routes\TermRoutes;
use WP_REST_Request;
use WP_REST_Response;
use Exception;
@@ -634,7 +636,7 @@
]);
try {
- JVB()->error()->log('security_audit', $event, $context, 'info');
+ Errors::getInstance()->log('security_audit', $event, $context, 'info');
} catch (Exception $e) {
error_log("Security Audit: {$event} - " . json_encode($context));
}
@@ -646,7 +648,7 @@
protected function logError(string $message, array $context = [], string $severity = 'error'): void
{
try {
- JVB()->error()->log(static::class, $message, $context, $severity);
+ Errors::getInstance()->log(static::class, $message, $context, $severity);
} catch (Exception $e) {
error_log(static::class . " Error: {$message} - " . json_encode($context));
}
@@ -898,7 +900,7 @@
'name' => $term->name,
'slug' => $term->slug,
'parent' => $term->parent,
- 'path' => JVB()->routes('term')->getTermPath($term->term_id, $term->name, $taxonomy),
+ 'path' => TermRoutes::getInstance()->getTermPath($term->term_id, $term->name, $taxonomy),
'taxonomy' => jvbNoBase($term->taxonomy),
'count' => $term->count,
];
diff --git a/inc/rest/RestRouteManager.php b/inc/rest/RestRouteManager.php
index e2efa84..a474aaa 100644
--- a/inc/rest/RestRouteManager.php
+++ b/inc/rest/RestRouteManager.php
@@ -3,6 +3,8 @@
use DateTime;
use DateTimeZone;
+use JVBase\integrations\services\Cloudflare;
+use JVBase\managers\Errors;
use JVBase\registrar\Registrar;
use JVBase\managers\OperationQueue;
use JVBase\managers\Cache;
@@ -208,7 +210,7 @@
protected function logError(string $message, array $context = [], string $severity = 'error')
{
try {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'artist_invitations', // component
$message,
$context,
@@ -917,7 +919,7 @@
// Use existing error handler
try {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'security_audit',
$event,
$context,
@@ -1045,7 +1047,7 @@
protected function verifyTurnstile(string $token): bool
{
- if (!Site::hasIntegration('cloudflare') || !JVB()->connect('cloudflare')->isSetUp()) {
+ if (!Site::hasIntegration('cloudflare') || !Cloudflare::getInstance()->isSetUp()) {
return true;
}
@@ -1053,6 +1055,6 @@
return false;
}
- return JVB()->connect('cloudflare')->verifyTurnstile($token);
+ return Cloudflare::getInstance()->verifyTurnstile($token);
}
}
diff --git a/inc/rest/routes/ContentRoutes.php b/inc/rest/routes/ContentRoutes.php
index 7d5ef42..8f5f5de 100644
--- a/inc/rest/routes/ContentRoutes.php
+++ b/inc/rest/routes/ContentRoutes.php
@@ -49,9 +49,7 @@
$this->termCache->user();
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
add_action('init', [$this, 'registerContentExecutors'], 5);
}
@@ -279,8 +277,8 @@
$args['s'] = sanitize_text_field($params['search']);
}
- $key = $this->cache->generateKey($args);
- $cached = $this->cache->get($key);
+
+ $cached = $this->cache->get($args);
if ($cached) {
return $cached;
}
@@ -308,7 +306,7 @@
];
- $this->cache->set($key, $data);
+ $this->cache->set($args, $data);
return Response::success($data);
}
@@ -343,14 +341,14 @@
$args['s'] = sanitize_text_field($params['search']);
}
- $key = $this->cache->generateKey($args);
+
// Check HTTP cache headers with the specific content type
// $cache_check = $this->checkHeaders($request, $key);
// if ($cache_check) {
// return $cache_check;
// }
- $cache = $this->cache->get($key);
+ $cache = $this->cache->get($args);
if ($cache) {
return Response::success($cache);
}
@@ -389,7 +387,7 @@
$this->taxonomies = [];
$data['items'] =array_map([$this, 'prepareTerm'], $terms);
- $this->cache->set($key, $data);
+ $this->cache->set($args, $data);
return Response::success($data);
}
diff --git a/inc/rest/routes/ContentTermsRoutes.php b/inc/rest/routes/ContentTermsRoutes.php
index 8886996..8f2270a 100644
--- a/inc/rest/routes/ContentTermsRoutes.php
+++ b/inc/rest/routes/ContentTermsRoutes.php
@@ -261,9 +261,8 @@
$status = $request->get_param('status');
$page = (int)$request->get_param('page');
- $cacheKey = $this->cache->generateKey(compact('termID', 'status', 'page'));
- return $this->cache->remember($cacheKey, function() use ($termID, $status, $page) {
+ return $this->cache->remember(compact('termID', 'status', 'page'), function() use ($termID, $status, $page) {
$perPage = 20;
$offset = ($page - 1) * $perPage;
@@ -272,7 +271,7 @@
if ($status === 'active') {
$query = $query->where(['end_date' => null]);
} elseif ($status === 'inactive') {
- $query = $query->whereNotNull('end_date');
+ $query = $query->where(['end_date'=> ['NOT NULL', null]]);
}
$total = $query->countResults();
@@ -334,9 +333,7 @@
$status = $request->get_param('status');
$page = (int)$request->get_param('page');
- $cacheKey = $this->cache->generateKey(compact('termID', 'status', 'page'));
-
- return $this->cache->remember($cacheKey, function() use ($termID, $status, $page) {
+ return $this->cache->remember(compact('termID', 'status', 'page'), function() use ($termID, $status, $page) {
$perPage = 20;
$offset = ($page - 1) * $perPage;
diff --git a/inc/rest/routes/FeedRoutes.php b/inc/rest/routes/FeedRoutes.php
index 5d43c6a..01c0585 100644
--- a/inc/rest/routes/FeedRoutes.php
+++ b/inc/rest/routes/FeedRoutes.php
@@ -36,9 +36,7 @@
parent::__construct();
$this->cache = Cache::for('feed');
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
}
diff --git a/inc/rest/routes/Invitations.php b/inc/rest/routes/Invitations.php
index 90f0385..9dbb49f 100644
--- a/inc/rest/routes/Invitations.php
+++ b/inc/rest/routes/Invitations.php
@@ -88,8 +88,8 @@
];
// Check cache
- $key = $this->cache->generateKey($args);
- if ($cached = $this->cache->get($key)) {
+
+ if ($cached = $this->cache->get($args)) {
return $this->success($cached);
}
@@ -99,7 +99,7 @@
: $this->getUserInvitations($args);
// Cache result
- $this->cache->set($key, $result);
+ $this->cache->set($args, $result);
return $this->success($result);
}
@@ -107,7 +107,7 @@
/**
* Get invitations for a specific term
*/
- protected function getTermInvitations(array $args): array
+ public function getTermInvitations(array $args): array
{
// Check permission
if (!Roles::getInstance()()->isManager($args['user'], $args['to_term'])) {
diff --git a/inc/rest/routes/LoginRoutes.php b/inc/rest/routes/LoginRoutes.php
index 47fa450..67f209d 100644
--- a/inc/rest/routes/LoginRoutes.php
+++ b/inc/rest/routes/LoginRoutes.php
@@ -159,15 +159,8 @@
error_log('[handleLogin]Turnstile succeeded');
}
- // Attempt authentication
- $user = wp_authenticate($email, $password);
-
+ $user = $this->login($email, $password, $remember);
if (is_wp_error($user)) {
- $this->auditLog('login_failed', [
- 'email' => $email,
- 'error' => $user->get_error_code(),
- ]);
-
return $this->error(
$this->getLoginErrorMessage($user),
$user->get_error_code(),
@@ -175,21 +168,6 @@
);
}
- // Set auth cookie
- wp_clear_auth_cookie();
- wp_set_current_user($user->ID);
- wp_set_auth_cookie($user->ID, $remember);
-
- // Store session fingerprint
- $this->storeSessionFingerprint($user->ID, $request);
-
- do_action('wp_login', $user->user_login, $user);
-
- $this->auditLog('login_success', [
- 'user_id' => $user->ID,
- 'email' => $email,
- ]);
-
// Get redirect URL
$redirect = $this->getRedirectUrl($user, $redirect_to);
@@ -201,6 +179,40 @@
]);
}
+ public function login(string $email, string $password, bool $remember, ?WP_REST_Request $request = null):WP_User|WP_Error
+ {
+ // Attempt authentication
+ $user = wp_authenticate($email, $password);
+
+ if (is_wp_error($user)) {
+ $this->auditLog('login_failed', [
+ 'email' => $email,
+ 'error' => $user->get_error_code(),
+ ]);
+
+ return $user;
+ }
+
+ // Set auth cookie
+ wp_clear_auth_cookie();
+ wp_set_current_user($user->ID);
+ wp_set_auth_cookie($user->ID, $remember);
+
+ // Store session fingerprint
+ if ($request) {
+ $this->storeSessionFingerprint($user->ID, $request);
+ }
+
+
+ do_action('wp_login', $user->user_login, $user);
+
+ $this->auditLog('login_success', [
+ 'user_id' => $user->ID,
+ 'email' => $email,
+ ]);
+ return $user;
+ }
+
/**
* Handle user registration
*/
@@ -506,87 +518,6 @@
]);
}
- /************************************************************
- * SESSION FINGERPRINTING
- *
- * Detects session hijacking by validating that session hasn't
- * moved to a different device/network. Uses IP class (not full IP)
- * to allow mobile network changes without breaking sessions.
- ************************************************************/
-
- /**
- * Store session fingerprint for hijacking detection
- */
- protected function storeSessionFingerprint(int $user_id, WP_REST_Request $request): void
- {
- if (!defined('JVB_SESSION_FINGERPRINT') || !JVB_SESSION_FINGERPRINT) {
- return;
- }
-
- $fingerprint = $this->generateSessionFingerprint($request);
- update_user_meta($user_id, BASE . 'session_fingerprint', $fingerprint);
- update_user_meta($user_id, BASE . 'session_timestamp', time());
- }
-
- /**
- * Generate session fingerprint for hijacking detection
- */
- protected function generateSessionFingerprint(WP_REST_Request $request): string
- {
- return hash('sha256', implode('|', [
- $request->get_header('User-Agent') ?? '',
- // Use IP class instead of full IP to allow for mobile network changes
- $this->getIPClass(
- $request->get_header('X-Forwarded-For')
- ?: $request->get_header('X-Real-IP')
- ?: $_SERVER['REMOTE_ADDR'] ?? ''
- )
- ]));
- }
-
- /**
- * Get IP class (first 3 octets) for session validation
- * Allows for minor IP changes (common with mobile networks)
- */
- protected function getIPClass(string $ip): string
- {
- $parts = explode('.', $ip);
- return implode('.', array_slice($parts, 0, 3));
- }
-
- /**
- * Validate session fingerprint against stored value
- */
- protected function validateSessionFingerprint(int $user_id, WP_REST_Request $request): bool
- {
- // Only enforce if enabled in config
- if (!defined('JVB_SESSION_FINGERPRINT') || !JVB_SESSION_FINGERPRINT) {
- return true;
- }
-
- $stored = get_user_meta($user_id, BASE . 'session_fingerprint', true);
- $current = $this->generateSessionFingerprint($request);
-
- if (empty($stored)) {
- // First request - store fingerprint
- update_user_meta($user_id, BASE . 'session_fingerprint', $current);
- update_user_meta($user_id, BASE . 'session_timestamp', time());
- return true;
- }
-
- // Compare using timing-safe comparison
- return hash_equals($stored, $current);
- }
-
- /**
- * Clear session fingerprint (call on logout)
- */
- protected function clearSessionFingerprint(int $user_id): void
- {
- delete_user_meta($user_id, BASE . 'session_fingerprint');
- delete_user_meta($user_id, BASE . 'session_timestamp');
- }
-
/**************************************************************
* HELPERS
**************************************************************/
diff --git a/inc/rest/routes/NewsRoutes.php b/inc/rest/routes/NewsRoutes.php
index 5040862..3c626d8 100644
--- a/inc/rest/routes/NewsRoutes.php
+++ b/inc/rest/routes/NewsRoutes.php
@@ -108,8 +108,8 @@
public function getNews(WP_REST_Request $request):WP_REST_Response
{
$args = $this->buildQueryArgs($request);
- $key = $this->cache->generateKey($args);
- $cache = $this->cache->get($key);
+
+ $cache = $this->cache->get($args);
if ($cache) {
return $this->success($cache);
}
@@ -125,7 +125,7 @@
'total_pages' => $query->max_num_pages
];
- $this->cache->set($key, $results);
+ $this->cache->set($args, $results);
return $this->success($results);
}
@@ -325,7 +325,7 @@
$artist = jvbContentFromUser($post->post_author);
$upvotes = (int) get_post_meta($post->ID, BASE.'upvotes', true);
$downvotes = (int) get_post_meta($post->ID, BASE.'downvotes', true);
- $comments = JVB()->routes('comments')->getItemResponse($post->ID, BASE.'news');
+ $comments = ResponseRoutes::getInstance()->getItemResponse($post->ID, ['post_type' => BASE.'news']);
return [
'id' => $post->ID,
diff --git a/inc/rest/routes/QueueRoutes.php b/inc/rest/routes/QueueRoutes.php
index 3540edc..f9a8142 100644
--- a/inc/rest/routes/QueueRoutes.php
+++ b/inc/rest/routes/QueueRoutes.php
@@ -25,9 +25,7 @@
parent::__construct();
$this->cache = Cache::for($this->cacheName, 'custom', $this->cacheTtl)->user();
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
}
/**
diff --git a/inc/rest/routes/ResponseRoutes.php b/inc/rest/routes/ResponseRoutes.php
index 0e8589d..967e9c6 100644
--- a/inc/rest/routes/ResponseRoutes.php
+++ b/inc/rest/routes/ResponseRoutes.php
@@ -119,7 +119,7 @@
/**
* Get responses with karma calculations
*/
- protected function getItemResponse(int $item_id, array $args = []): array|WP_Error
+ public function getItemResponse(int $item_id, array $args = []): array|WP_Error
{
$responses = Responses::getInstance()->getAllItemResponses($item_id, $args);
// Format responses
diff --git a/inc/rest/routes/ShopRoutes.php b/inc/rest/routes/ShopRoutes.php
index 26b9dfa..5c9b3ac 100644
--- a/inc/rest/routes/ShopRoutes.php
+++ b/inc/rest/routes/ShopRoutes.php
@@ -3,6 +3,7 @@
use JVBase\JVB;
use JVBase\managers\Emails;
+use JVBase\managers\Errors;
use JVBase\managers\ImageGenerator;
use JVBase\managers\UploadManager;
use JVBase\registrar\Registrar;
@@ -164,7 +165,7 @@
foreach ($setData as $name => $value) {
if ($name === 'shop') {
- JVB()->routes('shop')->requestShopAdmission($operation->user_id, $value);
+ $this->requestShopAdmission($operation->user_id, $value);
$setData['requested_shop'] = $value;
unset($setData['shop']);
}
@@ -1007,7 +1008,7 @@
return true;
} catch (Exception $e) {
$wpdb->query('ROLLBACK');
- JVB()->error()->log(
+ Errors::getInstance()->log(
'shop',
"Error accepting artist invitation: " . $e->getMessage(),
[
@@ -1075,7 +1076,7 @@
return true;
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'shop',
"Error declining artist invitation: " . $e->getMessage(),
[
@@ -1157,7 +1158,7 @@
return true;
} catch (Exception $e) {
$wpdb->query('ROLLBACK');
- JVB()->error()->logError("Error adding artist to shop: " . $e->getMessage(), [
+ Errors::getInstance()->logError("Error adding artist to shop: " . $e->getMessage(), [
'user_id' => $user_id,
'shop_id' => $shop_id
]);
@@ -1241,7 +1242,7 @@
return true;
} catch (Exception $e) {
$wpdb->query('ROLLBACK');
- JVB()->error()->log(
+ Errors::getInstance()->log(
'shop',
"Error removing artist from shop: " . $e->getMessage(),
[
diff --git a/inc/rest/routes/TermRoutes.php b/inc/rest/routes/TermRoutes.php
index 8178cad..38772cb 100644
--- a/inc/rest/routes/TermRoutes.php
+++ b/inc/rest/routes/TermRoutes.php
@@ -3,6 +3,7 @@
use JVBase\Instance;
use JVBase\managers\Cache;
+use JVBase\managers\Errors;
use JVBase\managers\TaxonomyRelationships;
use JVBase\registrar\Registrar;
use JVBase\rest\Rest;
@@ -27,9 +28,7 @@
$this->cacheName = 'terms';
parent::__construct();
$this->cache = Cache::for('terms', 'term');
- if (JVB_TESTING) {
- $this->cache->flush();
- }
+
$this->per_page = 20;
@@ -559,7 +558,7 @@
$membership = Site::membership();
if ($membership && $membership->has('term_approval')) {
- $approval_routes = JVB()->routes('approvals');
+ $approval_routes = ApprovalRoutes::getInstance();
$request_id = $approval_routes->createTermApprovalRequest(
$user_id,
$taxonomy,
@@ -602,7 +601,7 @@
], 201); // 201 Created
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'terms',
'Term creation failed: ' . $e->getMessage(),
['user_id' => $user_id, 'taxonomy' => $taxonomy, 'name' => $name]
diff --git a/inc/rest/routes/UploadRoutes.php b/inc/rest/routes/UploadRoutes.php
index 0187f75..23d2fd0 100644
--- a/inc/rest/routes/UploadRoutes.php
+++ b/inc/rest/routes/UploadRoutes.php
@@ -708,7 +708,7 @@
return $this->queued($ID['operation_id'], 'Files uploaded and posts queued for creation');
} catch (Exception $e) {
- JVB()->error()->log(
+ Errors::getInstance()->log(
'[UploadRoutes]:handleGroupingRequest',
$e->getMessage(),
[
diff --git a/inc/utility/Image.php b/inc/utility/Image.php
index 384a699..23e2844 100644
--- a/inc/utility/Image.php
+++ b/inc/utility/Image.php
@@ -17,18 +17,14 @@
public function __construct()
{
- $this->cache = Cache::for('images')->connect('post');
- $this->imgData = Cache::for('imageData')->connect('post');
- if (JVB_TESTING) {
- $this->cache->flush();
- $this->imgData->flush();
- }
+ $this->cache = Cache::for('images', 'post');
+ $this->imgData = Cache::for('imageData', 'post');
}
public function formatImage(int $ID, string $start = 'tiny', string $replace = 'large', bool $addLink = true, ?string $postSlug = null):string
{
$return = $this->cache->remember(
- $this->cache->generateKey(['ID' => $ID, 'start' => $start, 'replace' => $replace]),
+ ['ID' => $ID, 'start' => $start, 'replace' => $replace],
function() use ($ID, $start, $replace) {
// Define size order for progressive enhancement
$sizeOrder = ['tiny', 'directory-preview', 'thumbnail', 'medium', 'large', 'full'];
@@ -188,9 +184,7 @@
public static function SVG(string $slug):string
{
$cache = Cache::for('svgs');
- if (JVB_TESTING) {
- $cache->flush();
- }
+
return $cache->remember(
$slug,
function() use ($slug) {
diff --git a/inc/utility/Video.php b/inc/utility/Video.php
index f71c050..0feffeb 100644
--- a/inc/utility/Video.php
+++ b/inc/utility/Video.php
@@ -15,12 +15,8 @@
public function __construct()
{
- $this->cache = Cache::for('videos')->connect('post');
- $this->vidData = Cache::for('vidData')->connect('post');
- if (JVB_TESTING) {
- $this->cache->flush();
- $this->vidData->flush();
- }
+ $this->cache = Cache::for('videos', 'post');
+ $this->vidData = Cache::for('vidData', 'post');
}
public static function get(int $ID, array $args = []):string
{
@@ -29,7 +25,7 @@
public function formatVideo(int $ID, array $args = []):string
{
return $this->cache->remember(
- $this->cache->generateKey(array_merge(['id' => $ID], $args)),
+ array_merge(['id' => $ID], $args),
function() use ($ID, $args) {
$url = wp_get_attachment_url($ID);
$meta = wp_get_attachment_metadata($ID);
diff --git a/jvb.php b/jvb.php
index 6494ea5..d7df5f8 100644
--- a/jvb.php
+++ b/jvb.php
@@ -121,11 +121,7 @@
add_filter('show_admin_bar', '__return_false');
//}
-//if (JVB_TESTING) {
-// error_log('In testing mode...');
-//} else {
-// error_log('Not in testing mode...');
-//}
+
const JVB_DIR = WP_PLUGIN_DIR . '/jvb';
define('JVB_URL', plugin_dir_url(__FILE__));
@@ -514,15 +510,15 @@
{
echo '<div class="screen-reader-text live-region" aria-live="polite" role="status"></div>';
}
+/*
+add_action('wp_head', 'jvbFrontendBase',1);
+function jvbFrontendBase():void
+{
-//add_action('wp_head', 'jvbFrontendBase',1);
-//function jvbFrontendBase():void
-//{
-// ?>
-<!-- <script type="text/javascript">window.jvbBase = '--><?php //= BASE ?>//';</script>
-// <?php
-//}
-
+ <script type="text/javascript">window.jvbBase = '<?= BASE ?>';</script>
+ <?php
+}
+*/
add_action('after_setup_theme', 'jvbImageSize');
@@ -549,23 +545,6 @@
// return $result;
//}, 10, 3);
-add_filter('rest_authentication_errors', function($result) {
-
- // Don't override existing authentication
- if (is_wp_error($result) || $result === true) {
- return $result;
- }
-
- // Try to authenticate from cookie
- $cookie_user = wp_validate_auth_cookie('', 'logged_in');
-
- if ($cookie_user) {
- wp_set_current_user($cookie_user);
- return true;
- }
- return $result;
-}, 99);
-
add_action('wp_footer', 'jvb_back_to_top');
function jvb_back_to_top():void
diff --git a/src/forms/render.php b/src/forms/render.php
index 9865bf3..14a5bb2 100644
--- a/src/forms/render.php
+++ b/src/forms/render.php
@@ -1,55 +1,7 @@
<?php
+
+use JVBase\meta\Form;
+
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
-/**
- * Form Block Render
- *
- * @package Edmonton_Ink
- */
-
-/**
- * Renders the form block on the frontend
- *
- * @param array $attributes The block attributes.
- * @param string $content The block content.
- * @param WP_Block $block The block instance.
- * @return string The rendered output.
- */
-function jvbRenderFormBlock(array $attributes, string $content, WP_Block $block):string
-{
- // Get form type from attributes
- $form_type = isset($attributes['formType']) ? $attributes['formType'] : '';
-
- // If no form type selected, return a message
- if (empty($form_type)) {
- return '<div class="jvb-form-error">No form type selected. Please edit this block and select a form type.</div>';
- }
-
- // Get other attributes
- $show_labels = isset($attributes['showLabels']) ? $attributes['showLabels'] : true;
- $custom_email_to = isset($attributes['customEmailTo']) ? $attributes['customEmailTo'] : '';
-
- // Set custom options for the form
- $form_options = array();
-
- // Set custom email recipient if provided
- if (!empty($custom_email_to)) {
- $form_options['email_to'] = $custom_email_to;
- }
-
- // Render the form with the specified options
- $form_output = JVB()->forms()->renderForm($form_type);
-
- // Get block classes
- $wrapper_attributes = get_block_wrapper_attributes([
- 'class' => 'jvb-forms'
- ]);
-
- // Return the wrapped form
- return sprintf(
- '<div %1$s>%2$s</div>',
- $wrapper_attributes,
- $form_output
- );
-}
diff --git a/templates/dashboard/sections/favourites.php b/templates/dashboard/sections/favourites.php
index 78f756a..238d78e 100644
--- a/templates/dashboard/sections/favourites.php
+++ b/templates/dashboard/sections/favourites.php
@@ -1,4 +1,7 @@
<?php
+
+use JVBase\managers\Favourites;
+
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
@@ -8,10 +11,11 @@
}
$user_id = get_current_user_id();
-$JVB = JVB();
-$favourites = $JVB->routes('favourites');
-$counts =$favourites->getFavouriteCounts($user_id, false);
-$lists =get_user_meta($user_id, BASE.'favourite_lists', true)?:[];
+
+$favourites = Favourites::getInstance();
+$counts =$favourites->getFavouriteCounts($user_id);
+$lists = $favourites->getLists(['user_id' => $user_id]);
+
global $types;
global $feed_types;
--
Gitblit v1.10.0