diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml index 1dcd58b..8891b59 100644 --- a/.mokogitea/manifest.xml +++ b/.mokogitea/manifest.xml @@ -9,7 +9,7 @@ Template - MokoOnyx MokoConsulting MokoOnyx - Joomla site template (successor to MokoCassiopeia) - 02.19.00 + 02.19.02 GNU General Public License v3 diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 6958f88..f450d94 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: moko-platform.Automation -# VERSION: 02.19.00 +# VERSION: 02.19.02 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c73908..6226b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,11 @@ DEFGROUP: Joomla.Template.Site INGROUP: MokoOnyx.Documentation PATH: ./CHANGELOG.md - VERSION: 02.19.00 + VERSION: 02.19.02 BRIEF: Changelog file documenting version history of MokoOnyx --> -# Changelog — MokoOnyx (VERSION: 02.19.00) +# Changelog — MokoOnyx (VERSION: 02.19.02) ## [Unreleased] ## [02.19.00] --- 2026-06-04 diff --git a/SECURITY.md b/SECURITY.md index 28608f9..d707c57 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,7 +10,7 @@ INGROUP: MokoOnyx.Governance REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx FILE: SECURITY.md - VERSION: 02.19.00 + VERSION: 02.19.02 BRIEF: Security policy and vulnerability reporting process for MokoOnyx. PATH: /SECURITY.md NOTE: This policy is process oriented and does not replace secure engineering practices. diff --git a/src/html/layouts/joomla/module/card.php b/src/html/layouts/joomla/module/card.php index 42e39a4..807b96b 100644 --- a/src/html/layouts/joomla/module/card.php +++ b/src/html/layouts/joomla/module/card.php @@ -10,7 +10,7 @@ * INGROUP: MokoOnyx * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx * PATH: /html/layouts/joomla/module/card.php - * VERSION: 02.19.00 + * VERSION: 02.19.02 * BRIEF: Custom card module chrome — renders module titles for all modules */ diff --git a/src/html/layouts/mokoonyx/article-metadata.php b/src/html/layouts/mokoonyx/article-metadata.php index ce119e9..2e21eee 100644 --- a/src/html/layouts/mokoonyx/article-metadata.php +++ b/src/html/layouts/mokoonyx/article-metadata.php @@ -11,7 +11,7 @@ * INGROUP: MokoOnyx.Layouts * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx * PATH: /src/html/layouts/mokoonyx/article-metadata.php - * VERSION: 02.19.00 + * VERSION: 02.19.02 * BRIEF: Article metadata footer layout -- renders jcfields grouped by field group */ diff --git a/src/media/css/a11y-high-contrast.css b/src/media/css/a11y-high-contrast.css index 3dd2da1..a7a5503 100644 --- a/src/media/css/a11y-high-contrast.css +++ b/src/media/css/a11y-high-contrast.css @@ -10,7 +10,7 @@ * INGROUP: MokoOnyx.Accessibility * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx * PATH: ./media/css/a11y-high-contrast.css - * VERSION: 02.19.00 + * VERSION: 02.19.02 * BRIEF: High-contrast stylesheet for accessibility toolbar */ diff --git a/src/script.php b/src/script.php index c48027e..35f6641 100644 --- a/src/script.php +++ b/src/script.php @@ -94,6 +94,7 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface $this->clearFaviconStamp(); $this->cleanMediaFolder(); $this->removeDeletedFiles(); + $this->removeDuplicateExtensions(); $this->lockExtension(); } @@ -484,6 +485,96 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface } } + /** + * Remove duplicate MokoOnyx extension entries from #__extensions. + * + * Re-installs or migrations can leave ghost rows. We keep the one + * that is locked (the active template) and delete any extras. + * Also removes stale MokoCassiopeia entries if present. + */ + private function removeDuplicateExtensions(): void + { + $db = Factory::getDbo(); + + // Find all MokoOnyx template entries + $rows = $db->setQuery( + $db->getQuery(true) + ->select(['extension_id', 'locked']) + ->from('#__extensions') + ->where($db->quoteName('element') . ' = ' . $db->quote(self::NEW_NAME)) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')) + ->order('locked DESC, extension_id ASC') + )->loadObjectList(); + + if (count($rows) > 1) { + $keep = (int) $rows[0]->extension_id; + $removed = 0; + + for ($i = 1; $i < count($rows); $i++) { + $staleId = (int) $rows[$i]->extension_id; + + $db->setQuery( + $db->getQuery(true) + ->delete('#__update_sites_extensions') + ->where('extension_id = ' . $staleId) + )->execute(); + + $db->setQuery( + $db->getQuery(true) + ->delete('#__extensions') + ->where('extension_id = ' . $staleId) + )->execute(); + + $removed++; + } + + if ($removed > 0) { + $this->logMessage("Removed {$removed} duplicate MokoOnyx extension(s). Kept ID {$keep}."); + } + } + + // Remove stale MokoCassiopeia if not set as default + $oldExt = (int) $db->setQuery( + $db->getQuery(true) + ->select('extension_id') + ->from('#__extensions') + ->where($db->quoteName('element') . ' = ' . $db->quote(self::OLD_NAME)) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')) + )->loadResult(); + + if ($oldExt) { + $isDefault = (int) $db->setQuery( + $db->getQuery(true) + ->select('COUNT(*)') + ->from('#__template_styles') + ->where($db->quoteName('template') . ' = ' . $db->quote(self::OLD_NAME)) + ->where($db->quoteName('home') . ' = 1') + )->loadResult(); + + if ($isDefault === 0) { + $db->setQuery( + $db->getQuery(true) + ->delete('#__update_sites_extensions') + ->where('extension_id = ' . $oldExt) + )->execute(); + + $db->setQuery( + $db->getQuery(true) + ->delete('#__extensions') + ->where('extension_id = ' . $oldExt) + )->execute(); + + $db->setQuery( + $db->getQuery(true) + ->delete('#__template_styles') + ->where($db->quoteName('template') . ' = ' . $db->quote(self::OLD_NAME)) + )->execute(); + + $this->logMessage('Removed stale MokoCassiopeia extension and styles.'); + } + } + } + /** * Remove files and directories that were shipped in previous versions * but have since been deleted from the package. diff --git a/src/templateDetails.xml b/src/templateDetails.xml index e905250..02d4690 100644 --- a/src/templateDetails.xml +++ b/src/templateDetails.xml @@ -32,11 +32,11 @@ - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml + https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/updates.xml mokoonyx - 02.19.00 + 02.19.02-dev script.php 2026-05-16 Jonathan Miller || Moko Consulting diff --git a/updates.xml b/updates.xml index f7ef071..8d493ff 100644 --- a/updates.xml +++ b/updates.xml @@ -1,7 +1,7 @@ @@ -11,13 +11,13 @@ mokoonyx template site - 02.18.04-dev + 02.19.02-dev 2026-06-04 https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/development - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.18.04-dev.zip + https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.19.02-dev.zip - 32e888ba865ab28a96afe1a1f76380c4a3b341389f730e9c6899bdcac9b2bd36 + 5811cc175564744865053f5a2cf259e66016c4e41f2d87571d19b1dd5f7fd8ba dev https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md Moko Consulting