11 Commits

Author SHA1 Message Date
gitea-actions[bot] 4a02861b90 chore(version): pre-release bump to 01.00.36-dev [skip ci] 2026-07-07 10:16:52 +00:00
jmiller 258cfe0968 Merge pull request 'feat(menu): admin menu short-name constant COM_MOKOSUITESUPPORT_SHORT (#14)' (#17) from fix/short-menu-constant into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
2026-07-07 10:15:34 +00:00
gitea-actions[bot] a6c50f5e79 chore(version): pre-release bump to 01.00.35-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Failing after 2s
2026-07-06 22:44:28 +00:00
jmiller 806660af44 feat(menu): use COM_MOKOSUITESUPPORT_SHORT + wire admin language (#14)
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 19s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 58s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Claude-Session: https://claude.ai/code/session_01B9aZHSWbiiZykJD88pYx8R
2026-07-06 22:44:06 +00:00
jmiller df5c18543d feat(menu): add COM_MOKOSUITESUPPORT_SHORT short-name constant (#14)
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 8s
Claude-Session: https://claude.ai/code/session_01B9aZHSWbiiZykJD88pYx8R
2026-07-06 22:43:53 +00:00
jmiller c51ed89df8 Merge pull request 'fix: honest install success for package installer' (#16) from fix/honest-install-success into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 13s
2026-07-06 16:17:51 +00:00
gitea-actions[bot] b1a023a673 chore(version): pre-release bump to 01.00.34-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
2026-07-06 16:14:50 +00:00
jmiller 471e0a7cc9 fix: honest install success for MokoSuiteSupport package installer
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 9s
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 <file> declared in the
package manifest actually landed in #__extensions (plugins match on
element+type+folder with plg_<group>_ 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
2026-07-06 11:14:26 -05:00
gitea-actions[bot] 2487c69b5e chore(version): pre-release bump to 01.00.33-dev [skip ci] 2026-07-05 23:09:57 +00:00
gitea-actions[bot] 67dfc6355c chore(version): auto-bump patch 01.00.32-dev [skip ci] 2026-07-05 23:09:44 +00:00
jmiller 7aa5c41159 Merge chore/normalize-docs: normalize doc/config refs
Universal: Auto Version Bump / Version Bump (push) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
2026-07-05 22:52:36 +00:00
11 changed files with 125 additions and 10 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Automation
# VERSION: 01.00.32
# VERSION: 01.00.36
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
+1
View File
@@ -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
+1 -1
View File
@@ -14,7 +14,7 @@
DEFGROUP: Template-Joomla
INGROUP: Template-Joomla.Documentation
REPO: https://github.com/mokoconsulting-tech/Template-Joomla/
VERSION: 01.00.32
VERSION: 01.00.36
PATH: ./CODE_OF_CONDUCT.md
BRIEF: Community expectations and enforcement guidelines
NOTE: Adapted with attribution from the Contributor Covenant v2.1
+1 -1
View File
@@ -19,7 +19,7 @@
DEFGROUP: mokoconsulting-tech.Template-Joomla
INGROUP: MokoStandards.Governance
REPO: https://github.com/mokoconsulting-tech/Template-Joomla
VERSION: 01.00.32
VERSION: 01.00.36
PATH: /GOVERNANCE.md
BRIEF: Project governance rules, roles, and decision process for Template-Joomla
-->
+1 -1
View File
@@ -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.32
VERSION: 01.00.36
BRIEF: Security vulnerability reporting and handling policy
-->
@@ -0,0 +1,7 @@
; MokoSuite Support - system language strings
; Copyright (C) 2026 Moko Consulting. All rights reserved.
; License GPL-3.0-or-later
COM_MOKOSUITESUPPORT="MokoSuite Support"
COM_MOKOSUITESUPPORT_SHORT="Support"
COM_MOKOSUITESUPPORT_XML_DESCRIPTION="MokoSuite Support component."
@@ -5,10 +5,13 @@
<creationDate>2026-06-23</creationDate>
<copyright>Copyright (C) 2026 Moko Consulting.</copyright>
<license>GPL-3.0-or-later</license>
<version>01.00.32</version>
<version>01.00.36</version>
<namespace path="src">Moko\Component\MokoSuiteSupport</namespace>
<administration>
<files folder="admin"><folder>services</folder><folder>src</folder><folder>tmpl</folder></files>
<menu>COM_MOKOSUITESUPPORT</menu>
<files folder="admin"><folder>language</folder><folder>services</folder><folder>src</folder><folder>tmpl</folder></files>
<menu>COM_MOKOSUITESUPPORT_SHORT</menu>
<languages folder="admin/language">
<language tag="en-GB">en-GB/com_mokosuitesupport.sys.ini</language>
</languages>
</administration>
</extension>
@@ -8,7 +8,7 @@
<license>GPL-3.0-or-later</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl>
<version>01.00.32</version>
<version>01.00.36</version>
<php_minimum>8.3</php_minimum>
<description>PLG_SYSTEM_MOKOSUITESUPPORT_DESC</description>
<namespace path="src">Moko\Plugin\System\MokoSuiteSupport</namespace>
@@ -3,7 +3,7 @@
<name>Web Services - MokoSuite Support</name>
<element>mokosuitesupport</element>
<author>Moko Consulting</author>
<version>01.00.32</version>
<version>01.00.36</version>
<license>GPL-3.0-or-later</license>
<namespace path="src">Moko\Plugin\WebServices\MokoSuiteSupport</namespace>
<files><folder>src</folder><folder>services</folder></files>
+1 -1
View File
@@ -2,7 +2,7 @@
<extension type="package" method="upgrade">
<name>Package - MokoSuite Support</name>
<packagename>mokosuitesupport</packagename>
<version>01.00.32</version>
<version>01.00.36</version>
<creationDate>2026-06-21</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
+104
View File
@@ -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(
'<h4>MokoSuiteSupport did not install correctly.</h4>'
. '<p>The following bundled extensions are missing: '
. htmlspecialchars(implode(', ', $missing), ENT_QUOTES) . '</p>'
. '<p>Please uninstall MokoSuiteSupport and reinstall the full package.</p>',
'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 <file> "type" attribute
* - element = the <file> "id" attribute, EXCEPT for plugins the manifest often
* declares the full `plg_<group>_<element>` id, so strip a leading
* `plg_<group>_` to get the real element; components/modules use id as-is
* - plugins ALSO match folder = the <file> "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_<group>_.
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