fix: undefined $db in findImage(), pass cached product to buildProduct()

- Add missing Factory::getDbo() in findImage() category fallback — would
  cause fatal error on article pages with no images (found in PR review)
- Pass cached product to JsonLdBuilder::buildProduct() to avoid duplicate
  DB query (same pattern as buildArticle with cachedArticle)
- Fix orphaned PHPDoc block for getImageDimensions()
This commit is contained in:
Jonathan Miller
2026-06-21 15:40:01 -05:00
parent 0cc69b7d77
commit 28d44d6884
2 changed files with 27 additions and 23 deletions
@@ -218,7 +218,7 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface
$imageUrl = $image ? $this->resolveImageUrl($image) : '';
if ($option === 'com_mokoshop' && $view === 'product' && $id > 0) {
$schema = JsonLdBuilder::buildProduct($id, $title, $description, $imageUrl);
$schema = JsonLdBuilder::buildProduct($id, $title, $description, $imageUrl, $this->loadShopProduct($id));
} elseif ($option === 'com_content' && $view === 'article' && $id > 0) {
$schema = JsonLdBuilder::buildArticle($id, $title, $description, $imageUrl, $this->loadArticle($id));
} else {
@@ -464,6 +464,7 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface
// Fallback: check the article's category for an image
if ($view === 'article') {
$db = Factory::getDbo();
$catQuery = $db->getQuery(true)
->select($db->quoteName('cat.params'))
->from($db->quoteName('#__categories', 'cat'))
@@ -622,15 +623,6 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface
}
}
/**
* Get the actual pixel dimensions of a local image.
*
* Returns [width, height] or null for external URLs or unreadable images.
*
* @param string $image Image path (relative or absolute URL)
*
* @return array{0: int, 1: int}|null
*/
/**
* Load MokoSuiteShop product data by product ID.
*
@@ -661,6 +653,13 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface
return $cache[$productId];
}
/**
* Get the actual pixel dimensions of a local image.
*
* @param string $image Image path (relative or absolute URL)
*
* @return array{0: int, 1: int}|null
*/
private function getImageDimensions(string $image): ?array
{
// Cannot determine dimensions for external URLs
@@ -162,28 +162,33 @@ class JsonLdBuilder
/**
* Build Product schema for a MokoSuiteShop product.
*
* @param int $productId CRM product ID
* @param string $title Product title
* @param string $description Product description
* @param string $image Image URL (absolute)
* @param int $productId CRM product ID
* @param string $title Product title
* @param string $description Product description
* @param string $image Image URL (absolute)
* @param object|null $cachedProduct Pre-loaded product data (avoids duplicate query)
*
* @return array|null
*/
public static function buildProduct(int $productId, string $title, string $description, string $image): ?array
public static function buildProduct(int $productId, string $title, string $description, string $image, ?object $cachedProduct = null): ?array
{
if ($productId <= 0) {
return null;
}
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('p.sku, p.price, p.currency, p.stock_qty')
->from($db->quoteName('#__mokosuite_crm_products', 'p'))
->where($db->quoteName('p.id') . ' = ' . $productId)
->where($db->quoteName('p.published') . ' = 1');
$product = $cachedProduct;
$db->setQuery($query);
$product = $db->loadObject();
if (!$product) {
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('p.sku, p.price, p.currency, p.stock_qty')
->from($db->quoteName('#__mokosuite_crm_products', 'p'))
->where($db->quoteName('p.id') . ' = ' . $productId)
->where($db->quoteName('p.published') . ' = 1');
$db->setQuery($query);
$product = $db->loadObject();
}
if (!$product) {
return null;