fix: address PR review findings — error handling and data integrity

- Add missing language field to batch-generated records
- Wrap batch insert in try-catch to handle duplicate key races
- Add logging to all empty catch blocks (script.php, MokoOG license check)
- Guard loadShopProduct() with try-catch for missing MokoSuiteShop tables
- Guard reviews query in JsonLdBuilder for missing #__mokoshop_reviews
This commit is contained in:
Jonathan Miller
2026-06-21 16:26:13 -05:00
parent 38af92b876
commit 46e30c950b
4 changed files with 63 additions and 41 deletions
@@ -90,6 +90,7 @@ class BatchController extends BaseController
$articles = $db->loadObjectList();
$created = 0;
$skipped = 0;
$now = Factory::getDate()->toSql();
foreach ($articles as $article) {
@@ -98,23 +99,28 @@ class BatchController extends BaseController
$ogImage = $this->extractImage($article);
$record = (object) [
'content_type' => 'com_content',
'content_id' => (int) $article->id,
'og_title' => $ogTitle,
'og_description' => $ogDescription,
'og_image' => $ogImage,
'og_type' => 'article',
'seo_title' => '',
'content_type' => 'com_content',
'content_id' => (int) $article->id,
'og_title' => $ogTitle,
'og_description' => $ogDescription,
'og_image' => $ogImage,
'og_type' => 'article',
'seo_title' => '',
'meta_description' => $article->metadesc ?: '',
'robots' => '',
'canonical_url' => '',
'published' => 1,
'created' => $now,
'modified' => $now,
'robots' => '',
'canonical_url' => '',
'language' => '*',
'published' => 1,
'created' => $now,
'modified' => $now,
];
$db->insertObject('#__mokoog_tags', $record);
$created++;
try {
$db->insertObject('#__mokoog_tags', $record);
$created++;
} catch (\RuntimeException $e) {
$skipped++;
}
}
echo new JsonResponse([
@@ -619,7 +619,8 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface
'warning'
);
} catch (\Throwable $e) {
// Don't break admin over a license check
// Don't break admin over a license check, but log for debugging
\Joomla\CMS\Log\Log::add('MokoOG license check: ' . $e->getMessage(), \Joomla\CMS\Log\Log::WARNING, 'mokoog');
}
}
@@ -638,17 +639,22 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface
return $cache[$productId];
}
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('p.id, p.sku, p.price, p.currency, p.stock_qty')
->select('c.title AS name, c.introtext AS description, c.images')
->from($db->quoteName('#__mokosuite_crm_products', 'p'))
->join('LEFT', $db->quoteName('#__content', 'c') . ' ON c.id = p.article_id')
->where($db->quoteName('p.id') . ' = ' . $productId)
->where($db->quoteName('p.published') . ' = 1');
try {
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('p.id, p.sku, p.price, p.currency, p.stock_qty')
->select('c.title AS name, c.introtext AS description, c.images')
->from($db->quoteName('#__mokosuite_crm_products', 'p'))
->join('LEFT', $db->quoteName('#__content', 'c') . ' ON c.id = p.article_id')
->where($db->quoteName('p.id') . ' = ' . $productId)
->where($db->quoteName('p.published') . ' = 1');
$db->setQuery($query);
$cache[$productId] = $db->loadObject();
$db->setQuery($query);
$cache[$productId] = $db->loadObject();
} catch (\RuntimeException $e) {
// MokoSuiteShop tables may not exist
$cache[$productId] = null;
}
return $cache[$productId];
}
@@ -224,21 +224,25 @@ class JsonLdBuilder
];
// Aggregate rating from reviews if available
$reviewQuery = $db->getQuery(true)
->select('COUNT(*) AS review_count, AVG(rating) AS avg_rating')
->from($db->quoteName('#__mokoshop_reviews'))
->where($db->quoteName('product_id') . ' = ' . $productId)
->where($db->quoteName('status') . ' = ' . $db->quote('approved'));
try {
$reviewQuery = $db->getQuery(true)
->select('COUNT(*) AS review_count, AVG(rating) AS avg_rating')
->from($db->quoteName('#__mokoshop_reviews'))
->where($db->quoteName('product_id') . ' = ' . $productId)
->where($db->quoteName('status') . ' = ' . $db->quote('approved'));
$db->setQuery($reviewQuery);
$rating = $db->loadObject();
$db->setQuery($reviewQuery);
$rating = $db->loadObject();
if ($rating && (int) $rating->review_count > 0) {
$schema['aggregateRating'] = [
'@type' => 'AggregateRating',
'ratingValue' => round((float) $rating->avg_rating, 1),
'reviewCount' => (int) $rating->review_count,
];
if ($rating && (int) $rating->review_count > 0) {
$schema['aggregateRating'] = [
'@type' => 'AggregateRating',
'ratingValue' => round((float) $rating->avg_rating, 1),
'reviewCount' => (int) $rating->review_count,
];
}
} catch (\RuntimeException $e) {
// Reviews table may not exist if MokoSuiteShop reviews module not installed
}
return $schema;
+9 -3
View File
@@ -82,7 +82,9 @@ class Pkg_MokoOGInstallerScript
$key = $db->loadResult();
if (!empty($key)) { $this->savedDownloadKey = $key; }
}
catch (\Throwable $e) {}
catch (\Throwable $e) {
\Joomla\CMS\Log\Log::add('MokoOG saveDownloadKey: ' . $e->getMessage(), \Joomla\CMS\Log\Log::WARNING, 'mokoog');
}
}
private function restoreDownloadKey(): void
@@ -112,7 +114,9 @@ class Pkg_MokoOGInstallerScript
)->execute();
}
}
catch (\Throwable $e) {}
catch (\Throwable $e) {
\Joomla\CMS\Log\Log::add('MokoOG restoreDownloadKey: ' . $e->getMessage(), \Joomla\CMS\Log\Log::WARNING, 'mokoog');
}
}
private function warnMissingLicenseKey(): void
@@ -147,6 +151,8 @@ class Pkg_MokoOGInstallerScript
'warning'
);
}
catch (\Throwable $e) {}
catch (\Throwable $e) {
\Joomla\CMS\Log\Log::add('MokoOG warnMissingLicenseKey: ' . $e->getMessage(), \Joomla\CMS\Log\Log::WARNING, 'mokoog');
}
}
}