From 471e0a7cc90c75d7a166e0fca7628554ebac4d80 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Mon, 6 Jul 2026 11:14:26 -0500 Subject: [PATCH 1/2] fix: honest install success for MokoSuiteSupport package installer The package postflight showed the "license key required" next-steps message even when a bundled child extension failed to install. Joomla only logs a failed sub-install but still runs postflight. Add missingChildExtensions(): verify every declared in the package manifest actually landed in #__extensions (plugins match on element+type+folder with plg__ prefix stripping; component matches element+type). Gate the license message on it and enqueue an error listing any missing children. Fails open so a query/IO glitch never turns a good install into a false failure. Claude-Session: https://claude.ai/code/session_01B9aZHSWbiiZykJD88pYx8R --- CHANGELOG.md | 1 + source/script.php | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe50a54..2601923 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - **CLAUDE.md** — repo-specific with channels, key patterns ### Fixed +- **Installer** — honest install success: the package postflight now verifies every bundled child extension (component + system plugin) actually landed in `#__extensions` before showing the license/next-steps message, and enqueues an error listing any missing ones instead. Fails open so a transient query/IO glitch never fakes a failure. - **WebhookChannelHelper** — conversation race condition on concurrent webhooks (FOR UPDATE transaction) ### Removed diff --git a/source/script.php b/source/script.php index 0701e72..de6fbaf 100644 --- a/source/script.php +++ b/source/script.php @@ -16,9 +16,113 @@ class Pkg_MokoSuiteSupportInstallerScript { public function postflight(string $type, InstallerAdapter $adapter): void { + // Be honest about success. Joomla's package installer only LOGS a failed child + // sub-install but still runs this postflight, so don't show the license / + // next-steps message if a bundled extension is actually missing. Fails open + // (see missingChildExtensions) so a query/IO glitch never fakes a failure. + $missing = $this->missingChildExtensions($adapter); + + if (!empty($missing)) + { + Factory::getApplication()->enqueueMessage( + '

MokoSuiteSupport did not install correctly.

' + . '

The following bundled extensions are missing: ' + . htmlspecialchars(implode(', ', $missing), ENT_QUOTES) . '

' + . '

Please uninstall MokoSuiteSupport and reinstall the full package.

', + 'error' + ); + + return; + } + + // Warn if no license key is configured (success / next-steps path) $this->warnMissingLicenseKey(); } + /** + * Verify every child extension declared in the package manifest actually landed + * in #__extensions. Returns readable labels of any that are missing. + * + * Matching per Joomla's #__extensions uniqueness: + * - type = the "type" attribute + * - element = the "id" attribute, EXCEPT for plugins the manifest often + * declares the full `plg__` id, so strip a leading + * `plg__` to get the real element; components/modules use id as-is + * - plugins ALSO match folder = the "group" attribute + * + * FAILS OPEN: any error (unreadable manifest, query failure) returns [] so a + * transient glitch never turns a good install into a false failure. + * + * @param InstallerAdapter $adapter The package installer adapter. + * + * @return string[] + */ + private function missingChildExtensions(InstallerAdapter $adapter): array + { + try + { + $manifest = $adapter->getParent()->getManifest(); + + if (!$manifest || !isset($manifest->files) || !isset($manifest->files->file)) + { + return []; + } + + $db = Factory::getDbo(); + $missing = []; + + foreach ($manifest->files->file as $file) + { + $attrs = $file->attributes(); + $id = isset($attrs['id']) ? (string) $attrs['id'] : ''; + $exType = isset($attrs['type']) ? (string) $attrs['type'] : ''; + + if ($id === '' || $exType === '') + { + continue; + } + + $group = isset($attrs['group']) ? (string) $attrs['group'] : ''; + $element = $id; + + // Plugin element in #__extensions is the id minus any leading plg__. + if ($exType === 'plugin' && $group !== '') + { + $prefix = 'plg_' . $group . '_'; + + if (strpos($element, $prefix) === 0) + { + $element = substr($element, \strlen($prefix)); + } + } + + $query = $db->getQuery(true) + ->select('COUNT(*)') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = ' . $db->quote($element)) + ->where($db->quoteName('type') . ' = ' . $db->quote($exType)); + + if ($exType === 'plugin' && $group !== '') + { + $query->where($db->quoteName('folder') . ' = ' . $db->quote($group)); + } + + if ((int) $db->setQuery($query)->loadResult() === 0) + { + $label = trim((string) $file); + $missing[] = $label !== '' ? preg_replace('/\.zip$/i', '', $label) : $id; + } + } + + return $missing; + } + catch (\Throwable $e) + { + // Fail open — never fake a failure on a glitch. + return []; + } + } + private function warnMissingLicenseKey(): void { try From b1a023a6730c22cee2e9482141a4d8d3b2430d6a Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 6 Jul 2026 16:14:50 +0000 Subject: [PATCH 2/2] chore(version): pre-release bump to 01.00.34-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- CODE_OF_CONDUCT.md | 2 +- GOVERNANCE.md | 2 +- SECURITY.md | 2 +- source/packages/com_mokosuitesupport/mokosuitesupport.xml | 2 +- .../packages/plg_system_mokosuitesupport/mokosuitesupport.xml | 2 +- .../plg_webservices_mokosuitesupport/mokosuitesupport.xml | 2 +- source/pkg_mokosuitesupport.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 8c665ee..c1ca9f4 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.00.33 +# VERSION: 01.00.34 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index e6459fd..6fb756a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,7 +14,7 @@ DEFGROUP: Template-Joomla INGROUP: Template-Joomla.Documentation REPO: https://github.com/mokoconsulting-tech/Template-Joomla/ - VERSION: 01.00.33 + VERSION: 01.00.34 PATH: ./CODE_OF_CONDUCT.md BRIEF: Community expectations and enforcement guidelines NOTE: Adapted with attribution from the Contributor Covenant v2.1 diff --git a/GOVERNANCE.md b/GOVERNANCE.md index a9eddc3..22d8bfc 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -19,7 +19,7 @@ DEFGROUP: mokoconsulting-tech.Template-Joomla INGROUP: MokoStandards.Governance REPO: https://github.com/mokoconsulting-tech/Template-Joomla - VERSION: 01.00.33 + VERSION: 01.00.34 PATH: /GOVERNANCE.md BRIEF: Project governance rules, roles, and decision process for Template-Joomla --> diff --git a/SECURITY.md b/SECURITY.md index 11cf069..a4e6127 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -23,7 +23,7 @@ DEFGROUP: Template-Joomla INGROUP: Template-Joomla.Documentation REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla PATH: /SECURITY.md -VERSION: 01.00.33 +VERSION: 01.00.34 BRIEF: Security vulnerability reporting and handling policy --> diff --git a/source/packages/com_mokosuitesupport/mokosuitesupport.xml b/source/packages/com_mokosuitesupport/mokosuitesupport.xml index c8f6fc0..340c3ca 100644 --- a/source/packages/com_mokosuitesupport/mokosuitesupport.xml +++ b/source/packages/com_mokosuitesupport/mokosuitesupport.xml @@ -5,7 +5,7 @@ 2026-06-23 Copyright (C) 2026 Moko Consulting. GPL-3.0-or-later - 01.00.33 + 01.00.34 Moko\Component\MokoSuiteSupport servicessrctmpl diff --git a/source/packages/plg_system_mokosuitesupport/mokosuitesupport.xml b/source/packages/plg_system_mokosuitesupport/mokosuitesupport.xml index 1ce0a2f..e076786 100644 --- a/source/packages/plg_system_mokosuitesupport/mokosuitesupport.xml +++ b/source/packages/plg_system_mokosuitesupport/mokosuitesupport.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.00.33 + 01.00.34 8.3 PLG_SYSTEM_MOKOSUITESUPPORT_DESC Moko\Plugin\System\MokoSuiteSupport diff --git a/source/packages/plg_webservices_mokosuitesupport/mokosuitesupport.xml b/source/packages/plg_webservices_mokosuitesupport/mokosuitesupport.xml index ca43767..1b157fd 100644 --- a/source/packages/plg_webservices_mokosuitesupport/mokosuitesupport.xml +++ b/source/packages/plg_webservices_mokosuitesupport/mokosuitesupport.xml @@ -3,7 +3,7 @@ Web Services - MokoSuite Support mokosuitesupport Moko Consulting - 01.00.33 + 01.00.34 GPL-3.0-or-later Moko\Plugin\WebServices\MokoSuiteSupport srcservices diff --git a/source/pkg_mokosuitesupport.xml b/source/pkg_mokosuitesupport.xml index 9c4f68c..8cbc164 100644 --- a/source/pkg_mokosuitesupport.xml +++ b/source/pkg_mokosuitesupport.xml @@ -2,7 +2,7 @@ Package - MokoSuite Support mokosuitesupport - 01.00.33 + 01.00.34 2026-06-21 Moko Consulting hello@mokoconsulting.tech