From 1d2252e8b4a1cfffb4514faf92e2948b302d8a6c Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Thu, 28 May 2026 10:28:53 -0500 Subject: [PATCH] fix: auto-cleanup stale plugin update site on install/update Add cleanupPluginUpdateSite() to script.php postflight that removes the plugin-level update site entry from #__update_sites and #__update_sites_extensions. This prevents Joomla from checking for plugin-level updates that don't exist, which caused download failures on stable-only sites. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- CHANGELOG.md | 1 + src/packages/plg_system_mokowaas/script.php | 72 +++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73fc6898..cb7b58c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Trusted IP session bypass: moved from `onAfterInitialise` to `boot()` so Joomla's session lifetime is extended before the session handler validates it (was too late, Joomla expired the session first) - updates.xml: removed stale pre-release entries pointing to non-existent dev artifacts, legacy plugin update entry that caused stable sites to attempt dev downloads - Removed duplicate `` from inner plugin manifest — only the package-level manifest should register the update server +- Auto-cleanup of stale plugin-level update site entries on install/update (cleans `#__update_sites` and `#__update_sites_extensions`) ## [02.06.00] - 2026-05-25 diff --git a/src/packages/plg_system_mokowaas/script.php b/src/packages/plg_system_mokowaas/script.php index 8713f018..65ec942b 100644 --- a/src/packages/plg_system_mokowaas/script.php +++ b/src/packages/plg_system_mokowaas/script.php @@ -123,6 +123,7 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface if ($type === 'install' || $type === 'update') { $this->enableAndLockPlugin(); + $this->cleanupPluginUpdateSite(); $this->ensureMokoCassiopeia(); $this->installLanguageOverrides(); $this->updateLoginSupportUrls(); @@ -210,6 +211,77 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface $db->execute(); } + /** + * Remove the plugin-level update site so only the package-level one remains. + * + * Earlier versions registered an update server in the plugin manifest + * (plg_system_mokowaas) in addition to the package manifest (pkg_mokowaas). + * This caused Joomla to check for plugin-level updates that don't exist, + * leading to failed downloads. Only the package update site should exist. + * + * @return void + * + * @since 02.11.02 + */ + private function cleanupPluginUpdateSite() + { + $db = Factory::getDbo(); + + // Find the extension_id for the plugin + $query = $db->getQuery(true) + ->select($db->quoteName('extension_id')) + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = ' . $db->quote('mokowaas')) + ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) + ->where($db->quoteName('folder') . ' = ' . $db->quote('system')); + $db->setQuery($query); + $pluginId = (int) $db->loadResult(); + + if (!$pluginId) + { + return; + } + + // Find update_site_ids linked to the plugin (not the package) + $query = $db->getQuery(true) + ->select($db->quoteName('update_site_id')) + ->from($db->quoteName('#__update_sites_extensions')) + ->where($db->quoteName('extension_id') . ' = ' . $pluginId); + $db->setQuery($query); + $siteIds = $db->loadColumn(); + + if (empty($siteIds)) + { + return; + } + + // Delete the link rows + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__update_sites_extensions')) + ->where($db->quoteName('extension_id') . ' = ' . $pluginId) + )->execute(); + + // Delete orphaned update_sites rows (only if no other extension uses them) + foreach ($siteIds as $siteId) + { + $query = $db->getQuery(true) + ->select('COUNT(*)') + ->from($db->quoteName('#__update_sites_extensions')) + ->where($db->quoteName('update_site_id') . ' = ' . (int) $siteId); + $db->setQuery($query); + + if ((int) $db->loadResult() === 0) + { + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__update_sites')) + ->where($db->quoteName('update_site_id') . ' = ' . (int) $siteId) + )->execute(); + } + } + } + /** * Ensure MokoOnyx is installed, locked, and set as default. *