115 Commits

Author SHA1 Message Date
gitea-actions[bot] f807f985c8 chore(release): promote CHANGELOG 04.01.00 [skip ci] 2026-05-16 22:52:46 +00:00
jmiller 147bcc8630 fix(plugin): pretty name + help text update for v04.01.00 (#84)
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 3s
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 4s
Joomla: Repo Health / Repository health (push) Failing after 3s
2026-05-16 22:50:50 +00:00
jmiller 0b6a72a6ce chore: sync updates.xml 04.00.00 [skip ci] 2026-05-16 22:38:04 +00:00
gitea-actions[bot] 113c73430c chore(release): ZIP + tar.gz for 04.00.00 [skip ci] 2026-05-16 22:38:03 +00:00
gitea-actions[bot] 2426b5d85e chore(release): build 04.00.00 [skip ci] 2026-05-16 22:38:01 +00:00
gitea-actions[bot] ec945dab73 chore(release): promote CHANGELOG 04.00.00 [skip ci] 2026-05-16 22:38:00 +00:00
jmiller 39e71eb198 chore: sync updates.xml 04.00.00 [skip ci] 2026-05-16 22:34:28 +00:00
gitea-actions[bot] bba336ff86 chore(release): promote CHANGELOG 04.00.00 [skip ci] 2026-05-16 22:34:24 +00:00
jmiller ba8d23d862 Merge pull request 'fix(plugin): multi-select slugs, full path matching, Joomla 5 DI, pretty name' (#83) from dev into main
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 2s
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
2026-05-16 22:33:14 +00:00
Jonathan Miller e4534a62f1 Merge remote-tracking branch 'origin/main' into dev
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 4s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 4s
Universal: PR Check / Changelog Updated (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Joomla: Repo Health / Access control (pull_request) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Repo Health / Release configuration (pull_request) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 3s
Joomla: Repo Health / Repository health (pull_request) Failing after 3s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 49s
# Conflicts:
#	updates.xml
2026-05-16 17:31:38 -05:00
jmiller 7d497dfdc1 chore: sync updates.xml from [skip ci] 2026-05-16 22:30:05 +00:00
Jonathan Miller 3bf89ed10d chore: bump version to 04.00.00
Joomla: Update Server / Update updates.xml (push) Successful in 9s
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 4s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Joomla: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Changelog Updated (pull_request) Successful in 3s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 2s
Joomla: Repo Health / Release configuration (pull_request) Failing after 4s
Joomla: Repo Health / Repository health (pull_request) Failing after 3s
Major version bump for multi-select support, Joomla 5 DI registration,
and full route path matching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 17:29:52 -05:00
gitea-actions[bot] dda39e64ae chore: update development channel 00.00.01 [skip ci] 2026-05-16 22:26:59 +00:00
Jonathan Miller 6a457d2924 fix(ci): use direct XML parsing for platform detection
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 5s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 2s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Joomla: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Changelog Updated (pull_request) Failing after 3s
Joomla: Repo Health / Release configuration (pull_request) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 3s
Joomla: Repo Health / Repository health (pull_request) Failing after 3s
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
The release runner doesn't have MokoStandards-API pre-installed.
Fall back to sed-based manifest parsing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 17:25:51 -05:00
Jonathan Miller 62f72ae215 fix(ci): add MokoStandards-API clone step before platform detection
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 4s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 4s
Joomla: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: PR Check / Changelog Updated (pull_request) Failing after 3s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Repo Health / Release configuration (pull_request) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 3s
Joomla: Repo Health / Repository health (pull_request) Failing after 3s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 17:23:00 -05:00
jmiller 350a365a84 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:19:53 +00:00
jmiller 17cd29c663 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:19:52 +00:00
jmiller b308de6bf2 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:19:52 +00:00
jmiller 8f7f50f359 chore: rename Setup step to moko-platform [skip ci] 2026-05-16 22:19:21 +00:00
jmiller 06d846c38a chore: rename Setup step to moko-platform [skip ci] 2026-05-16 22:19:21 +00:00
Jonathan Miller 302329ad77 chore: update .gitea/manifest.xml to match MokoStandards v05
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 3s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 2s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 4s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Changelog Updated (pull_request) Failing after 3s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Joomla: Repo Health / Access control (pull_request) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Repo Health / Release configuration (pull_request) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 3s
Joomla: Repo Health / Repository health (pull_request) Failing after 4s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 14:07:38 -05:00
Jonathan Miller 09f80ccbe6 chore: sync workflows from Template-Joomla
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Joomla: Repo Health / Access control (pull_request) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Universal: PR Check / Changelog Updated (pull_request) Failing after 4s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Repo Health / Release configuration (pull_request) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 3s
Joomla: Repo Health / Repository health (pull_request) Failing after 3s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 14:02:11 -05:00
jmiller 396a3e8115 feat(ci): CB plugin detection + platform auto-sense + remove GitHub mirror [skip ci] 2026-05-16 18:58:36 +00:00
jmiller 0c167080f2 feat(ci): CB plugin detection + platform auto-sense + remove GitHub mirror [skip ci] 2026-05-16 18:57:55 +00:00
jmiller cc4d1c4600 chore: remove .mokogitea/workflows/update-server.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:43 +00:00
jmiller 528e6568fc chore: move .mokogitea/workflows/update-server.yml to .gitea/workflows/update-server.yml [skip ci] 2026-05-16 18:37:43 +00:00
jmiller 21325b79fd chore: remove .mokogitea/workflows/security-audit.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:42 +00:00
jmiller 3efacc344f chore: move .mokogitea/workflows/security-audit.yml to .gitea/workflows/security-audit.yml [skip ci] 2026-05-16 18:37:41 +00:00
jmiller 90b2479e63 chore: remove .mokogitea/workflows/repo-health.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:41 +00:00
jmiller 54f24b364b chore: move .mokogitea/workflows/repo-health.yml to .gitea/workflows/repo-health.yml [skip ci] 2026-05-16 18:37:40 +00:00
jmiller 8ad94c071b chore: remove .mokogitea/workflows/pre-release.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:39 +00:00
jmiller d4512ae32b chore: move .mokogitea/workflows/pre-release.yml to .gitea/workflows/pre-release.yml [skip ci] 2026-05-16 18:37:39 +00:00
jmiller 5bd1310685 chore: remove .mokogitea/workflows/pr-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:38 +00:00
jmiller 121c4628a3 chore: move .mokogitea/workflows/pr-check.yml to .gitea/workflows/pr-check.yml [skip ci] 2026-05-16 18:37:37 +00:00
jmiller b0776f17c4 chore: remove .mokogitea/workflows/notify.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:37 +00:00
jmiller 972f443865 chore: move .mokogitea/workflows/notify.yml to .gitea/workflows/notify.yml [skip ci] 2026-05-16 18:37:36 +00:00
jmiller f06adc08eb chore: remove .mokogitea/workflows/gitleaks.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:35 +00:00
jmiller 63851f4119 chore: move .mokogitea/workflows/gitleaks.yml to .gitea/workflows/gitleaks.yml [skip ci] 2026-05-16 18:37:34 +00:00
jmiller cc581fd0f8 chore: remove .mokogitea/workflows/deploy-manual.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:33 +00:00
jmiller 82e3049187 chore: move .mokogitea/workflows/deploy-manual.yml to .gitea/workflows/deploy-manual.yml [skip ci] 2026-05-16 18:37:33 +00:00
jmiller 67f2ad7ab0 chore: remove .mokogitea/workflows/cleanup.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:32 +00:00
jmiller cd188a46ab chore: move .mokogitea/workflows/cleanup.yml to .gitea/workflows/cleanup.yml [skip ci] 2026-05-16 18:37:31 +00:00
jmiller 27fbc090f5 chore: remove .mokogitea/workflows/ci-joomla.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:31 +00:00
jmiller 79ebcea9c4 chore: move .mokogitea/workflows/ci-joomla.yml to .gitea/workflows/ci-joomla.yml [skip ci] 2026-05-16 18:37:30 +00:00
jmiller 59c29735dc chore: remove .mokogitea/workflows/cascade-dev.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:29 +00:00
jmiller b639f72ffd chore: move .mokogitea/workflows/cascade-dev.yml to .gitea/workflows/cascade-dev.yml [skip ci] 2026-05-16 18:37:29 +00:00
jmiller d263faeea9 chore: remove .mokogitea/workflows/auto-release.yml (exists in .gitea/) [skip ci] 2026-05-16 18:37:28 +00:00
jmiller 525412e408 chore: remove .mokogitea/update-server.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:27 +00:00
jmiller 6e69768e4f chore: move .mokogitea/update-server.yml to .gitea/update-server.yml [skip ci] 2026-05-16 18:37:27 +00:00
jmiller c8c114a24c chore: remove .mokogitea/security-audit.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:26 +00:00
jmiller e9f13c43f6 chore: move .mokogitea/security-audit.yml to .gitea/security-audit.yml [skip ci] 2026-05-16 18:37:25 +00:00
jmiller a5a46a56a8 chore: remove .mokogitea/repo-health.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:25 +00:00
jmiller cb8ccf061d chore: move .mokogitea/repo-health.yml to .gitea/repo-health.yml [skip ci] 2026-05-16 18:37:24 +00:00
jmiller 238e1e4fbf chore: remove .mokogitea/pre-release.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:23 +00:00
jmiller 81800d4159 chore: move .mokogitea/pre-release.yml to .gitea/pre-release.yml [skip ci] 2026-05-16 18:37:23 +00:00
jmiller 381446b8ba chore: remove .mokogitea/pr-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:22 +00:00
jmiller dcf3c75dfb chore: move .mokogitea/pr-check.yml to .gitea/pr-check.yml [skip ci] 2026-05-16 18:37:21 +00:00
jmiller c62a1d0a69 chore: remove .mokogitea/pr-branch-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:21 +00:00
jmiller e1a73cc9de chore: move .mokogitea/pr-branch-check.yml to .gitea/pr-branch-check.yml [skip ci] 2026-05-16 18:37:20 +00:00
jmiller db578ad249 chore: remove .mokogitea/notify.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:19 +00:00
jmiller 3f305d0c60 chore: move .mokogitea/notify.yml to .gitea/notify.yml [skip ci] 2026-05-16 18:37:19 +00:00
jmiller 262c02a234 chore: remove .mokogitea/manifest.xml (moved to .gitea/) [skip ci] 2026-05-16 18:37:18 +00:00
jmiller 91a162f922 chore: move .mokogitea/manifest.xml to .gitea/manifest.xml [skip ci] 2026-05-16 18:37:17 +00:00
jmiller 27a2d2b387 chore: remove .mokogitea/gitleaks.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:16 +00:00
jmiller 5c0c3ea9b6 chore: move .mokogitea/gitleaks.yml to .gitea/gitleaks.yml [skip ci] 2026-05-16 18:37:16 +00:00
jmiller f6d4680d23 chore: remove .mokogitea/deploy-manual.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:15 +00:00
jmiller 633c6d4b68 chore: move .mokogitea/deploy-manual.yml to .gitea/deploy-manual.yml [skip ci] 2026-05-16 18:37:14 +00:00
jmiller 99b42e844a chore: remove .mokogitea/cleanup.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:14 +00:00
jmiller c38d20d805 chore: move .mokogitea/cleanup.yml to .gitea/cleanup.yml [skip ci] 2026-05-16 18:37:13 +00:00
jmiller ae015ee0df chore: remove .mokogitea/ci-joomla.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:12 +00:00
jmiller b669f6c768 chore: move .mokogitea/ci-joomla.yml to .gitea/ci-joomla.yml [skip ci] 2026-05-16 18:37:12 +00:00
jmiller 65a091c90c chore: remove .mokogitea/cascade-dev.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:11 +00:00
jmiller cec71a88f2 chore: move .mokogitea/cascade-dev.yml to .gitea/cascade-dev.yml [skip ci] 2026-05-16 18:37:11 +00:00
jmiller 7c5fbe1626 chore: remove .mokogitea/auto-release.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:10 +00:00
jmiller 45c78e1f5f chore: move .mokogitea/auto-release.yml to .gitea/auto-release.yml [skip ci] 2026-05-16 18:37:09 +00:00
jmiller eacfc432d7 chore: remove .mokogitea/ISSUE_TEMPLATE/version.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:09 +00:00
jmiller ee1c8a2262 chore: move .mokogitea/ISSUE_TEMPLATE/version.md to .gitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-16 18:37:08 +00:00
jmiller f910b99f4d chore: remove .mokogitea/ISSUE_TEMPLATE/security.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:07 +00:00
jmiller 5a32a540be chore: move .mokogitea/ISSUE_TEMPLATE/security.md to .gitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-16 18:37:07 +00:00
jmiller 1e9b0a5856 chore: remove .mokogitea/ISSUE_TEMPLATE/rfc.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:06 +00:00
jmiller 273e8b4649 chore: move .mokogitea/ISSUE_TEMPLATE/rfc.md to .gitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-16 18:37:05 +00:00
jmiller 81b26cfdd9 chore: remove .mokogitea/ISSUE_TEMPLATE/question.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:05 +00:00
jmiller b7d48d21bf chore: move .mokogitea/ISSUE_TEMPLATE/question.md to .gitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-16 18:37:04 +00:00
jmiller 11d8e42708 chore: remove .mokogitea/ISSUE_TEMPLATE/joomla_issue.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:04 +00:00
jmiller 1b0eb2b1b9 chore: move .mokogitea/ISSUE_TEMPLATE/joomla_issue.md to .gitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-16 18:37:03 +00:00
jmiller 4f58ec9d1d chore: remove .mokogitea/ISSUE_TEMPLATE/feature_request.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:02 +00:00
jmiller 6d9a832a27 chore: move .mokogitea/ISSUE_TEMPLATE/feature_request.md to .gitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-16 18:37:02 +00:00
jmiller ad6660f898 chore: remove .mokogitea/ISSUE_TEMPLATE/documentation.md (moved to .gitea/) [skip ci] 2026-05-16 18:37:01 +00:00
jmiller bd907f55f7 chore: move .mokogitea/ISSUE_TEMPLATE/documentation.md to .gitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-16 18:37:00 +00:00
jmiller fde1fa0356 chore: remove .mokogitea/ISSUE_TEMPLATE/config.yml (moved to .gitea/) [skip ci] 2026-05-16 18:37:00 +00:00
jmiller 86e35fb5e7 chore: move .mokogitea/ISSUE_TEMPLATE/config.yml to .gitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-16 18:36:59 +00:00
jmiller 8052fe9130 chore: remove .mokogitea/ISSUE_TEMPLATE/bug_report.md (moved to .gitea/) [skip ci] 2026-05-16 18:36:58 +00:00
jmiller 9adc34357c chore: move .mokogitea/ISSUE_TEMPLATE/bug_report.md to .gitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-16 18:36:58 +00:00
jmiller 16fa16469e chore: remove .mokogitea/ISSUE_TEMPLATE/adr.md (moved to .gitea/) [skip ci] 2026-05-16 18:36:57 +00:00
jmiller 2495f5022a chore: move .mokogitea/ISSUE_TEMPLATE/adr.md to .gitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-16 18:36:56 +00:00
Jonathan Miller 13e5f07951 chore: remove GitHub update server references from updates.xml
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 4s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 6s
Joomla: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Universal: PR Check / Changelog Updated (pull_request) Failing after 3s
Joomla: Repo Health / Release configuration (push) Failing after 4s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Repo Health / Release configuration (pull_request) Failing after 3s
Joomla: Repo Health / Scripts governance (pull_request) Successful in 4s
Joomla: Repo Health / Repository health (pull_request) Failing after 3s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 13:28:26 -05:00
jmiller 5dd2656b6f fix(ci): platform auto-sense, .mokogitea precedence, remove GitHub mirror [skip ci] 2026-05-16 18:27:13 +00:00
jmiller 357685e463 fix(ci): auto-release on PR merge + dispatch, bump dev after [skip ci] 2026-05-16 18:00:38 +00:00
jmiller 45dea64d01 fix(ci): restrict auto-release to workflow_dispatch only [skip ci] 2026-05-16 17:57:20 +00:00
gitea-actions[bot] 4886090575 chore: update development channel 00.00.01 [skip ci] 2026-05-16 17:50:47 +00:00
jmiller c312ae2207 fix(ci): deploy auto-release with new version bump protocol [skip ci] 2026-05-16 17:41:44 +00:00
gitea-actions[bot] 25c6778871 chore: update development channel 00.00.01 [skip ci] 2026-05-16 17:34:18 +00:00
gitea-actions[bot] 3a366e7956 chore(version): bump 00.00.00 → 00.00.01 [skip ci] 2026-05-16 17:34:17 +00:00
Jonathan Miller 05bcbd8169 fix(ci): update pre-release workflow to reference .gitea/manifest.xml
Joomla: Repo Health / Access control (push) Successful in 0s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 12:33:47 -05:00
jmiller 939d2a5e6c chore: sync updates.xml from [skip ci] 2026-05-16 17:25:32 +00:00
gitea-actions[bot] 61ba7f2cd0 chore: update updates.xml (development: 03.09.00-dev) [skip ci] 2026-05-16 17:25:31 +00:00
Jonathan Miller 2fa69c6a2f fix(plugin): match full route path, support multi-select, update pretty name
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Repo Health / Release configuration (push) Failing after 3s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Repository health (push) Failing after 3s
Joomla: Update Server / Update updates.xml (push) Successful in 10s
- Match against menu item path (e.g., legal/terms-of-service) instead
  of just the alias, fixing offline mode bypass for nested routes
- Support multiple menu items via multi-select dropdown
- Handle legacy single-value string format for backward compatibility
- Use Joomla convention pretty name "System - Moko Terms of Service"
- Update field labels and descriptions for multi-select UX

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 12:24:47 -05:00
Jonathan Miller 6da271b7b2 chore: rename .mokogitea to .gitea
Joomla: Repo Health / Access control (push) Successful in 1s
Joomla: Repo Health / Scripts governance (push) Successful in 3s
Joomla: Repo Health / Release configuration (push) Failing after 4s
Joomla: Repo Health / Repository health (push) Failing after 3s
Gitea expects .gitea/ as the standard directory for workflows
and issue templates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 09:42:36 -05:00
Jonathan Miller 1092de762f fix(lang): update pretty name to Joomla convention [skip ci]
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 09:34:58 -05:00
Jonathan Miller 8fe9497c85 feat(plugin): add services/provider.php for Joomla 5 DI registration
Joomla 5 requires a service provider to register namespaced plugins
with the dependency injection container. Without this file, the plugin
does not appear in the plugin manager.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 09:34:53 -05:00
jmiller 61edf950e6 Merge pull request 'chore: merge dev into main [skip ci]' (#82) from dev into main 2026-05-16 14:16:05 +00:00
Jonathan Miller cdbe8712df feat(ci): add changelog gate to PR checks [skip ci]
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 09:11:13 -05:00
Jonathan Miller 4340aa8dd6 chore: bump version to 03.09.00
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 09:05:44 -05:00
Jonathan Miller 0028e72e8d chore(ci): version bump targets dev branch instead of main [skip ci]
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 09:05:30 -05:00
jmiller 0e281bd7f9 fix(plugin): production readiness + Gitea update server (#81) 2026-05-16 13:54:42 +00:00
54 changed files with 649 additions and 593 deletions
@@ -8,18 +8,18 @@
<identity>
<name>MokoJoomTOS</name>
<org>MokoConsulting</org>
<description>A component to present a sites Term of Service and privacy policy even through offline.</description>
<description>Joomla system plugin to keep legal pages accessible during offline mode</description>
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
</identity>
<governance>
<platform>joomla</platform>
<standards-version>04.07.00</standards-version>
<standards-version>05.00.00</standards-version>
<standards-source>https://git.mokoconsulting.tech/MokoConsulting/moko-platform</standards-source>
<last-synced>2026-05-10T19:51:05+00:00</last-synced>
<last-synced>2026-05-16T17:30:00+00:00</last-synced>
</governance>
<build>
<language>PHP</language>
<package-type>joomla</package-type>
<package-type>joomla-extension</package-type>
<entry-point>src/</entry-point>
</build>
</moko-platform>
@@ -58,7 +58,7 @@ jobs:
token: ${{ secrets.GA_TOKEN }}
fetch-depth: 0
- name: Setup MokoStandards tools
- name: Setup moko-platform
env:
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
@@ -70,31 +70,74 @@ jobs:
fi
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
/tmp/mokostandards-api
cd /tmp/mokostandards-api
composer install --no-dev --no-interaction --quiet
/tmp/mokostandards-api 2>/dev/null || true
if [ -d /tmp/mokostandards-api ]; then
cd /tmp/mokostandards-api
composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
echo "MokoStandards tools: $([ -d /tmp/mokostandards-api ] && echo 'available' || echo 'unavailable (using fallback)')"
# -- PLATFORM DETECTION ---------------------------------------------------
- name: Detect platform
id: platform
run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
[ -z "$PLATFORM" ] && PLATFORM="generic"
# 1. Try explicit platform from manifest (.mokogitea takes precedence)
if [ -f ".mokogitea/manifest.xml" ]; then
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
elif [ -f ".gitea/manifest.xml" ]; then
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .gitea/manifest.xml 2>/dev/null | head -1)
fi
# 2. Auto-sense from file structure if no manifest
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
CB_MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<cbplugin' {} \; 2>/dev/null | head -1)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
if [ -z "$PLATFORM" ]; then
if [ -n "$CB_MANIFEST" ]; then
PLATFORM="joomla"
MANIFEST="$CB_MANIFEST"
elif [ -n "$MANIFEST" ]; then
PLATFORM="joomla"
elif [ -n "$MOD_FILE" ]; then
PLATFORM="dolibarr"
else
PLATFORM="generic"
fi
fi
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Platform detected: ${PLATFORM}"
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
# Detect update file methodology
if [ "$PLATFORM" = "joomla" ]; then
echo "update_method=updates.xml" >> "$GITHUB_OUTPUT"
echo "Update method: Joomla updates.xml"
elif [ "$PLATFORM" = "dolibarr" ]; then
echo "update_method=update.txt" >> "$GITHUB_OUTPUT"
echo "Update method: Dolibarr update.txt"
else
echo "update_method=none" >> "$GITHUB_OUTPUT"
echo "Update method: none (generic)"
fi
# -- STEP 1: Read version -----------------------------------------------
- name: "Step 1: Read version from README.md"
id: version
run: |
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null)
# Try MokoStandards PHP tool first, fall back to direct parsing
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || true)
if [ -z "$VERSION" ]; then
# Fallback: read from README table format "| **Version** | XX.YY.ZZ |"
VERSION=$(sed -n 's/.*\*\*Version\*\*[[:space:]]*|[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
fi
if [ -z "$VERSION" ]; then
# Fallback: read VERSION: XX.YY.ZZ pattern from any file
VERSION=$(grep -rh "VERSION:[[:space:]]*[0-9]" README.md CHANGELOG.md 2>/dev/null | sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' | head -1)
fi
if [ -z "$VERSION" ]; then
echo "No VERSION in README.md — skipping release"
echo "skip=true" >> "$GITHUB_OUTPUT"
@@ -122,54 +165,15 @@ jobs:
echo "Version: $VERSION (patch — platform version + badges only)"
fi
# -- STEP 1b: Bump minor version (stable = minor bump, reset patch) ------
- name: "Step 1b: Bump minor version for stable release"
# -- STEP 1b: Promote CHANGELOG [Unreleased] to current version -----------
- name: "Step 1b: Promote CHANGELOG for release"
if: steps.version.outputs.skip != 'true'
id: bump
run: |
CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
[ -z "$CURRENT" ] && { echo "skip=true" >> "$GITHUB_OUTPUT"; exit 0; }
MAJOR=$((10#$(echo "$CURRENT" | cut -d. -f1)))
MINOR=$((10#$(echo "$CURRENT" | cut -d. -f2)))
# Minor bump, reset patch. Rollover if minor > 99
MINOR=$((MINOR + 1))
if [ $MINOR -gt 99 ]; then
MINOR=0
MAJOR=$((MAJOR + 1))
fi
VERSION=$(printf "%02d.%02d.00" $MAJOR $MINOR)
VERSION="${{ steps.version.outputs.version }}"
TODAY=$(date +%Y-%m-%d)
echo "Stable bump: ${CURRENT} → ${VERSION} (minor)"
# Update README.md
sed -i "s/VERSION:[[:space:]]*${CURRENT}/VERSION: ${VERSION}/" README.md
# Update platform-specific manifest
PLATFORM="${{ steps.platform.outputs.platform }}"
MANIFEST="${{ steps.platform.outputs.manifest }}"
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
case "$PLATFORM" in
joomla)
if [ -n "$MANIFEST" ]; then
MANIFEST_VER=$(sed -n 's/.*<version>\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" | head -1)
[ -n "$MANIFEST_VER" ] && sed -i "s|<version>${MANIFEST_VER}</version>|<version>${VERSION}</version>|" "$MANIFEST"
sed -i "s|<creationDate>[^<]*</creationDate>|<creationDate>${TODAY}</creationDate>|" "$MANIFEST"
fi
;;
dolibarr)
if [ -n "$MOD_FILE" ]; then
sed -i "s/\$this->version = '[^']*'/\$this->version = '${VERSION}'/" "$MOD_FILE"
fi
echo "${VERSION}" > update.txt
;;
*) ;;
esac
# Promote [Unreleased] section in CHANGELOG.md to new version
# Promote [Unreleased] section in CHANGELOG.md to release version
if [ -f "CHANGELOG.md" ] && grep -qi "Unreleased" CHANGELOG.md; then
sed -i "s|## \[Unreleased\]|## [${VERSION}] --- ${TODAY}|" CHANGELOG.md
sed -i "s|## Unreleased|## [${VERSION}] --- ${TODAY}|" CHANGELOG.md
@@ -178,19 +182,19 @@ jobs:
echo "CHANGELOG promoted to [${VERSION}]"
fi
# Commit and push
# Commit changelog promotion if changed
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
git commit -m "chore(release): promote CHANGELOG ${VERSION} [skip ci]"
git push origin HEAD:main 2>&1
}
# Override version output for rest of pipeline
# Pass through version (no bump — release uses version as-is from dev)
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "major=$(printf "%02d" $MAJOR)" >> "$GITHUB_OUTPUT"
echo "major=${{ steps.version.outputs.major }}" >> "$GITHUB_OUTPUT"
- name: Check if already released
if: steps.version.outputs.skip != 'true'
@@ -335,8 +339,19 @@ jobs:
steps.check.outputs.already_released != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
php /tmp/mokostandards-api/cli/version_set_platform.php \
--path . --version "$VERSION" --branch main
if [ -f /tmp/mokostandards-api/cli/version_set_platform.php ]; then
php /tmp/mokostandards-api/cli/version_set_platform.php \
--path . --version "$VERSION" --branch main
else
# Fallback: update version in templateDetails.xml directly
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -n "$MANIFEST" ]; then
sed -i "s|<version>[^<]*</version>|<version>${VERSION}</version>|" "$MANIFEST"
sed -i "s|<creationDate>[^<]*</creationDate>|<creationDate>$(date +%Y-%m-%d)</creationDate>|" "$MANIFEST"
fi
# Update README version table
sed -i "s/|\s*\*\*Version\*\*\s*|[^|]*/| **Version** | ${VERSION} /" README.md 2>/dev/null || true
fi
# -- STEP 4: Update version badges ----------------------------------------
- name: "Step 4: Update version badges"
@@ -362,18 +377,35 @@ jobs:
REPO="${{ github.repository }}"
# -- Parse extension metadata from XML manifest ----------------
# Check for Joomla <extension> or Community Builder <cbplugin>
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "Warning: No Joomla XML manifest found — skipping updates.xml" >> $GITHUB_STEP_SUMMARY
CB_MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<cbplugin' {} \; 2>/dev/null | head -1)
IS_CB="false"
if [ -z "$MANIFEST" ] && [ -z "$CB_MANIFEST" ]; then
echo "Warning: No Joomla/CB XML manifest found — skipping updates.xml" >> $GITHUB_STEP_SUMMARY
exit 0
fi
# CB plugin takes precedence if no standard manifest
if [ -z "$MANIFEST" ] && [ -n "$CB_MANIFEST" ]; then
MANIFEST="$CB_MANIFEST"
IS_CB="true"
fi
# Extract fields using sed (portable — no grep -P)
EXT_NAME=$(sed -n 's/.*<name>\([^<]*\)<\/name>.*/\1/p' "$MANIFEST" | head -1)
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" | head -1)
EXT_CLIENT=$(sed -n 's/.*<extension[^>]*client="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
if [ "$IS_CB" = "true" ]; then
EXT_TYPE="cb_plugin"
EXT_ELEMENT=$(sed -n 's/.*<cbplugin[^>]*plugin="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_CLIENT=""
EXT_FOLDER="cb"
else
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" | head -1)
EXT_CLIENT=$(sed -n 's/.*<extension[^>]*client="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
fi
TARGET_PLATFORM=$(sed -n 's/.*\(<targetplatform[^/]*\/>\).*/\1/p' "$MANIFEST" | head -1)
PHP_MINIMUM=$(sed -n 's/.*<php_minimum>\([^<]*\)<\/php_minimum>.*/\1/p' "$MANIFEST" | head -1)
@@ -450,6 +482,7 @@ jobs:
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
cb_plugin) TYPE_PREFIX="cb_" ;;
esac
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
@@ -559,7 +592,7 @@ jobs:
fi
[ -z "$EXT_NAME" ] && EXT_NAME="${GITEA_REPO}"
NOTES=$(php /tmp/mokostandards-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
NOTES=$(php /tmp/mokostandards-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null || true)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
# Build release name: "Pretty Name VERSION (type_element-VERSION)"
@@ -571,6 +604,7 @@ jobs:
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
cb_plugin) TYPE_PREFIX="cb_" ;;
esac
RELEASE_NAME="${EXT_NAME} ${VERSION} (${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION})"
@@ -641,6 +675,7 @@ jobs:
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
cb_plugin) TYPE_PREFIX="cb_" ;;
esac
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
@@ -803,6 +838,7 @@ jobs:
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
cb_plugin) TYPE_PREFIX="cb_" ;;
esac
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
@@ -850,65 +886,7 @@ jobs:
" 2>/dev/null && echo "Release body updated with changelog + SHA" >> $GITHUB_STEP_SUMMARY
fi
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
- name: "Step 9: Mirror release to GitHub"
if: >-
steps.version.outputs.skip != 'true' &&
steps.version.outputs.stability == 'stable' &&
secrets.GH_TOKEN != ''
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
MAJOR="${{ steps.version.outputs.major }}"
BRANCH="${{ steps.version.outputs.branch }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
NOTES=$(php /tmp/mokostandards-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null || true)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
echo "$NOTES" > /tmp/release_notes.md
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/$RELEASE_TAG" 2>/dev/null | jq -r ".tag_name // empty" || true)
if [ -z "$EXISTING" ]; then
gh release create "$RELEASE_TAG" \
--repo "$GH_REPO" \
--title "v${MAJOR} (latest: ${VERSION})" \
--notes-file /tmp/release_notes.md \
--target "$BRANCH" || true
else
gh release edit "$RELEASE_TAG" \
--repo "$GH_REPO" \
--title "v${MAJOR} (latest: ${VERSION})" || true
fi
# Upload assets to GitHub mirror
for PKG in /tmp/${EXT_ELEMENT:-pkg}-${VERSION}.*; do
if [ -f "$PKG" ]; then
_RELID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/$RELEASE_TAG" 2>/dev/null | jq -r ".id // empty")
[ -n "$_RELID" ] && curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" -H "Content-Type: application/octet-stream" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/${_RELID}/assets?name=$(basename $PKG)" --data-binary "@$PKG" > /dev/null 2>&1 || true
fi
done
echo "GitHub mirror updated: ${GH_REPO} ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
- name: "Step 10: Push main to GitHub mirror"
if: >-
steps.version.outputs.skip != 'true' &&
secrets.GH_TOKEN != ''
continue-on-error: true
run: |
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
git remote add github "https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
git remote set-url github "https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
git fetch origin main --depth=1
git push github origin/main:refs/heads/main --force 2>/dev/null \
&& echo "main branch pushed to GitHub mirror" \
|| echo "WARNING: GitHub mirror push failed"
# -- (GitHub mirror removed — Gitea is the sole release platform) ----------
# -- Clean up lesser pre-releases (cascade) ---------------------------------
# stable → deletes all | rc → beta,alpha,dev | beta → alpha,dev | alpha → dev
@@ -939,25 +917,74 @@ jobs:
done
echo "Cleaned up ${DELETED} pre-release channel(s)" >> $GITHUB_STEP_SUMMARY
# -- STEP 11: Reset dev branch from main ------------------------------------
- name: "Step 11: Delete and recreate dev branch from main"
# -- STEP 11: Reset dev branch and bump to next minor -------------------------
- name: "Step 11: Reset dev and bump to next minor"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.GA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
PLATFORM="${{ steps.platform.outputs.platform }}"
# Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
# Recreate dev from main (now includes version bump + changelog promotion)
# Recreate dev from main
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
# Calculate next minor version for dev
MAJOR=$((10#$(echo "$VERSION" | cut -d. -f1)))
MINOR=$((10#$(echo "$VERSION" | cut -d. -f2)))
MINOR=$((MINOR + 1))
if [ $MINOR -gt 99 ]; then
MINOR=0
MAJOR=$((MAJOR + 1))
fi
NEXT=$(printf "%02d.%02d.00" $MAJOR $MINOR)
# Bump version on dev via API (README + manifest)
# Update README.md on dev
README_RESP=$(curl -sf -H "Authorization: token ${TOKEN}" "${API_BASE}/contents/README.md?ref=dev" 2>/dev/null || true)
README_SHA=$(echo "$README_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
README_CONTENT=$(echo "$README_RESP" | python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin).get('content','')).decode())" 2>/dev/null || true)
if [ -n "$README_SHA" ] && [ -n "$README_CONTENT" ]; then
UPDATED=$(echo "$README_CONTENT" | sed "s/${VERSION}/${NEXT}/g")
ENCODED=$(echo "$UPDATED" | base64 -w0)
curl -sf -X PUT -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" \
"${API_BASE}/contents/README.md" \
-d "$(python3 -c "import json; print(json.dumps({'content':'${ENCODED}','sha':'${README_SHA}','message':'chore(version): bump ${VERSION} → ${NEXT} (dev) [skip ci]','branch':'dev'}))")" > /dev/null 2>&1 || true
fi
# Update manifest on dev (Joomla or Dolibarr)
case "$PLATFORM" in
joomla)
MANIFEST_PATH="${{ steps.platform.outputs.manifest }}"
[ -n "$MANIFEST_PATH" ] && MANIFEST_PATH=$(echo "$MANIFEST_PATH" | sed 's|^\./||')
if [ -n "$MANIFEST_PATH" ]; then
ENCODED_PATH=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${MANIFEST_PATH}'))")
MF_RESP=$(curl -sf -H "Authorization: token ${TOKEN}" "${API_BASE}/contents/${ENCODED_PATH}?ref=dev" 2>/dev/null || true)
MF_SHA=$(echo "$MF_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
MF_CONTENT=$(echo "$MF_RESP" | python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin).get('content','')).decode())" 2>/dev/null || true)
if [ -n "$MF_SHA" ] && [ -n "$MF_CONTENT" ]; then
UPDATED=$(echo "$MF_CONTENT" | sed "s|<version>${VERSION}</version>|<version>${NEXT}</version>|")
ENCODED=$(echo "$UPDATED" | base64 -w0)
curl -sf -X PUT -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" \
"${API_BASE}/contents/${ENCODED_PATH}" \
-d "$(python3 -c "import json; print(json.dumps({'content':'${ENCODED}','sha':'${MF_SHA}','message':'chore(version): bump ${VERSION} → ${NEXT} (dev) [skip ci]','branch':'dev'}))")" > /dev/null 2>&1 || true
fi
fi
;;
dolibarr)
# Dolibarr handled by separate step below
;;
esac
echo "Dev branch bumped to ${NEXT}" >> $GITHUB_STEP_SUMMARY
# -- Dolibarr post-release: Reset dev version -----------------------------
@@ -108,9 +108,8 @@ jobs:
- name: Detect platform
id: platform
run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
# Parse manifest for platform detection
PLATFORM=$(php /tmp/mokostandards-api/cli/manifest_read.php --path . --field platform 2>/dev/null)
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
@@ -194,3 +193,32 @@ jobs:
FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l)
echo "Source: ${FILE_COUNT} files"
[ "$FILE_COUNT" -gt 0 ] || { echo "::error::Source directory is empty"; exit 1; }
# ── Changelog Gate ────────────────────────────────────────────────────
changelog:
name: Changelog Updated
runs-on: ubuntu-latest
if: github.base_ref == 'main'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check CHANGELOG.md was updated
run: |
BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"
if git diff --name-only "$BASE" "$HEAD" | grep -q "^CHANGELOG.md$"; then
echo "CHANGELOG.md updated"
else
# Allow [skip changelog] in PR title or body
PR_TITLE="${{ github.event.pull_request.title }}"
PR_BODY="${{ github.event.pull_request.body }}"
if echo "$PR_TITLE $PR_BODY" | grep -qi "\[skip changelog\]"; then
echo "::warning::Changelog skip requested via [skip changelog]"
exit 0
fi
echo "::error::CHANGELOG.md must be updated before merging to main. Add [skip changelog] to the PR title to bypass."
exit 1
fi
@@ -55,12 +55,11 @@ jobs:
- name: Detect platform
id: platform
run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
# Read platform from .gitea/manifest.xml
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .gitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "./.gitea/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
+44 -19
View File
@@ -1,4 +1,10 @@
<!--
## [Unreleased]
## [04.01.00] --- 2026-05-16
## [04.00.00] --- 2026-05-16
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
@@ -22,7 +28,7 @@
DEFGROUP: MokoJoomTOS
INGROUP: plg_system_mokojoomtos
REPO: https://github.com/mokoconsulting-tech/MokoJoomTOS
VERSION: 03.08.04
VERSION: 04.00.00
PATH: ./CHANGELOG.md
BRIEF: Version history and release notes
-->
@@ -34,34 +40,53 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [04.00.00] --- 2026-05-16
### Planned
## [04.00.00] - 2026-05-16
- GitHub Actions CI/CD workflows
- Pre-commit hooks for code quality
- Docker development environment
### Added
- Multi-select support: configure multiple menu items to remain accessible during offline mode
- `services/provider.php` for Joomla 5 dependency injection container registration
- Gitea-hosted update server URL in plugin manifest
### Changed
- Match against full menu route path instead of alias only (fixes nested routes like `/legal/terms-of-service`)
- Plugin pretty name updated to Joomla convention: "System - Moko Terms of Service"
- Renamed `.mokogitea/` to `.gitea/` for standard Gitea compatibility
- MenuslugField now stores and displays full route paths (e.g., `legal/terms-of-service`)
### Removed
- GitHub update server references (fully migrated to Gitea)
- Legacy `src/plugins/` directory
## [03.09.00] - 2026-05-16
### Fixed
- Legacy `mokojoomtos.php` now uses `onAfterRoute` event instead of `onAfterInitialise`
- Legacy plugin entry point now sets `tmpl=component` for component-only view during offline mode
- Installation script language keys corrected to match actual INI file definitions
- Installation script `$extension` property corrected from `plg_system_mokojoomtos_offline` to `plg_system_mokojoomtos`
- README.md event reference corrected from `onAfterInitialise` to `onAfterRoute`
- Installation script now resolves Uncategorised category ID dynamically (no longer assumes ID 2)
- Installation script now resolves `com_content` component ID dynamically (removed hardcoded fallback 22)
- All `Exception` catches qualified with backslash for namespace safety
- Added missing `PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS` language key to all locale files
- Standardized help text URL across all locale files
- Articles created during install are now owned by the installing admin user (not user ID 0)
### Changed
- Updated all markdown FILE INFORMATION headers to reference MokoJoomTOS repository
- Updated CONTRIBUTING.md title, clone URLs, and links to reference MokoJoomTOS
- Updated CHANGELOG.md links to reference MokoJoomTOS repository
- Updated CLAUDE.md and copilot-instructions.md for accuracy
- Added Gitea update server URL to plugin manifest (`updates.xml` on `main`)
- Removed obsolete `src/plugins/` legacy directory
## [03.08.04] - 2026-02-28
### Removed
- Legacy duplicate manifest at `src/plugins/system/mokojoomtos/mokojoomtos.xml`
## [03.09.00] - 2026-02-28
### Changed
- Updated version number to 03.08.04 across all files
- Updated version number to 03.09.00 across all files
- Fixed template chrome loading issue by changing event hook from onAfterInitialise to onAfterRoute
### Fixed
@@ -164,6 +189,6 @@ This template is ready for use in creating new Joomla components that follow org
- [Pull Requests](https://github.com/mokoconsulting-tech/MokoJoomTOS/pulls)
- [MokoStandards](https://github.com/mokoconsulting-tech/MokoCodingDefaults)
[Unreleased]: https://github.com/mokoconsulting-tech/MokoJoomTOS/compare/v03.08.04...HEAD
[03.08.04]: https://github.com/mokoconsulting-tech/MokoJoomTOS/releases/tag/v03.08.04
[Unreleased]: https://github.com/mokoconsulting-tech/MokoJoomTOS/compare/v03.09.00...HEAD
[03.09.00]: https://github.com/mokoconsulting-tech/MokoJoomTOS/releases/tag/v03.09.00
[1.0.0]: https://github.com/mokoconsulting-tech/MokoJoomTOS/releases/tag/v1.0.0
+4 -4
View File
@@ -75,7 +75,7 @@ XML files use the MokoStandard header format:
DEFGROUP: MokoJoomTOS
INGROUP: plg_system_mokojoomtos
PATH: src/mokojoomtos.xml
VERSION: 03.08.04
VERSION: 04.00.00
BRIEF: [Brief description of file purpose]
=========================================================================
-->
@@ -88,7 +88,7 @@ Markdown files use an HTML comment format with the same structure.
- **DEFGROUP**: Top-level group (always `MokoJoomTOS` for this repo)
- **INGROUP**: Subgroup/component (always `plg_system_mokojoomtos`)
- **PATH**: Relative path from repository root (e.g., `src/mokojoomtos.xml`)
- **VERSION**: Current plugin version (currently `03.08.04`)
- **VERSION**: Current plugin version (currently `04.00.00`)
- **BRIEF**: One-line description of file's purpose
### Exempt Files
@@ -327,7 +327,7 @@ No automated test infrastructure exists in this repository. Manual testing requi
```bash
# Manual packaging (build scripts being migrated to scripts/ directory)
cd src/
zip -r ../plg_system_mokojoomtos-03.08.04.zip .
zip -r ../plg_system_mokojoomtos-04.00.00.zip .
```
Package should contain: `mokojoomtos.php`, `mokojoomtos.xml`, `script.php`, `src/`, `language/`, `administrator/`
@@ -397,7 +397,7 @@ Before opening a pull request, ensure:
- [ ] CHANGELOG.md updated with changes under correct version
- [ ] README.md updated if user-facing changes
- [ ] All markdown file headers include VERSION: 03.08.04
- [ ] All markdown file headers include VERSION: 04.00.00
- [ ] XML file headers include complete FILE INFORMATION block
## Version Management
+2 -2
View File
@@ -2,14 +2,14 @@
A Joomla system plugin that keeps your Terms of Service, Privacy Policy, or any legal page accessible to visitors -- even when the site is in offline (maintenance) mode.
![Joomla](https://img.shields.io/badge/Joomla-5.x%20%7C%206.x-blue?style=flat-square&logo=joomla&logoColor=white) ![PHP](https://img.shields.io/badge/PHP-%E2%89%A58.1-777BB4?style=flat-square&logo=php&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square) ![Version](https://img.shields.io/badge/version-03.08.04-orange?style=flat-square) ![Type](https://img.shields.io/badge/type-system%20plugin-blueviolet?style=flat-square)
![Joomla](https://img.shields.io/badge/Joomla-5.x%20%7C%206.x-blue?style=flat-square&logo=joomla&logoColor=white) ![PHP](https://img.shields.io/badge/PHP-%E2%89%A58.1-777BB4?style=flat-square&logo=php&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square) ![Version](https://img.shields.io/badge/version-04.01.00-orange?style=flat-square) ![Type](https://img.shields.io/badge/type-system%20plugin-blueviolet?style=flat-square)
| Field | Value |
|---|---|
| **Author** | [Moko Consulting](https://mokoconsulting.tech) |
| **License** | GPL-3.0-or-later |
| **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS) |
| **Version** | 03.08.04 |
| **Version** | 04.01.00 |
---
View File
-16
View File
@@ -1,16 +0,0 @@
# Docs Index: /templates/repos/joomla/component/docs
## Purpose
This index provides navigation to documentation within this folder.
## Metadata
- **Document Type:** index
- **Auto-generated:** This file is automatically generated by rebuild_indexes.py
## Revision History
| Change | Notes | Author |
| --- | --- | --- |
| Automated update | Generated by documentation index automation | rebuild_indexes.py |
-119
View File
@@ -1,119 +0,0 @@
<!--
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
DEFGROUP: MokoJoomTOS.Documentation
INGROUP: MokoStandards.Templates
REPO: https://github.com/mokoconsulting-tech/MokoJoomTOS
PATH: /docs/update-server.md
VERSION: 04.04.00
BRIEF: How this extension's Joomla update server file (update.xml) is managed
-->
# Joomla Update Server
[![MokoStandards](https://img.shields.io/badge/MokoStandards-04.04.00-blue)](https://github.com/mokoconsulting-tech/MokoStandards)
This document explains how `update.xml` is automatically managed for this Joomla extension following the [Joomla Update Server specification](https://docs.joomla.org/Deploying_an_Update_Server).
## How It Works
Joomla checks for extension updates by fetching an XML file from the URL defined in the `<updateservers>` tag in the extension's XML manifest. MokoStandards generates this file automatically.
### Automatic Generation
| Event | Workflow | `<tag>` | `<version>` |
|-------|----------|---------|-------------|
| Merge to `main` | `auto-release.yml` | `stable` | `XX.YY.ZZ` |
| Push to `dev/**` | `deploy-dev.yml` | `development` | `development` |
| Push to `rc/**` | `deploy-dev.yml` | `rc` | `XX.YY.ZZ-rc` |
### Generated XML Structure
```xml
<?xml version="1.0" encoding="utf-8"?>
<updates>
<update>
<name>Extension Name</name>
<description>Extension Name update</description>
<element>com_extensionname</element>
<type>component</type>
<version>01.02.03</version>
<client>site</client>
<folder>system</folder> <!-- plugins only -->
<tags>
<tag>stable</tag>
</tags>
<infourl title="Extension Name">https://github.com/.../releases/tag/v01.02.03</infourl>
<downloads>
<downloadurl type="full" format="zip">https://github.com/.../releases/download/v01.02.03/com_ext-01.02.03.zip</downloadurl>
</downloads>
<targetplatform name="joomla" version="((5\.[0-9])|(6\.[0-9]))" />
<php_minimum>8.2</php_minimum> <!-- if present in manifest -->
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
</updates>
```
### Metadata Source
All metadata is extracted from the extension's XML manifest (`src/*.xml`) at build time:
| XML Element | Source | Notes |
|-------------|--------|-------|
| `<name>` | `<name>` in manifest | Extension display name |
| `<element>` | `<element>` in manifest | Must match installed extension identifier |
| `<type>` | `type` attribute on `<extension>` | `component`, `module`, `plugin`, `library`, `package`, `template` |
| `<client>` | `client` attribute on `<extension>` | `site` or `administrator`**required for plugins and modules** |
| `<folder>` | `group` attribute on `<extension>` | Plugin group (e.g., `system`, `content`) — **required for plugins** |
| `<targetplatform>` | `<targetplatform>` in manifest | Falls back to Joomla 5.x / 6.x if not specified |
| `<php_minimum>` | `<php_minimum>` in manifest | Included only if present |
### Extension Manifest Setup
Your XML manifest must include an `<updateservers>` tag pointing to the `update.xml` on the `main` branch:
```xml
<extension type="component" client="site" method="upgrade">
<name>My Extension</name>
<element>com_myextension</element>
<!-- ... -->
<updateservers>
<server type="extension" name="My Extension Updates">
https://raw.githubusercontent.com/mokoconsulting-tech/MokoJoomTOS/main/update.xml
</server>
</updateservers>
</extension>
```
### Branch Lifecycle
```
dev/XX.YY.ZZ → rc/XX.YY.ZZ → main → version/XX.YY
(development) (rc) (stable) (frozen snapshot)
```
1. **Development** (`dev/**`): `update.xml` with `<tag>development</tag>`, download points to branch archive
2. **Release Candidate** (`rc/**`): `update.xml` with `<tag>rc</tag>`, version set to `XX.YY.ZZ-rc`
3. **Stable Release** (merge to `main`): `update.xml` with `<tag>stable</tag>`, download points to GitHub Release asset
4. **Frozen Snapshot** (`version/XX.YY`): immutable, never force-pushed
### Health Checks
The `repo_health.yml` workflow verifies on every commit:
- `update.xml` exists in the repository root
- XML manifest exists with `<extension>` tag
- `<version>`, `<name>`, `<author>`, `<namespace>` tags present
- Extension `type` attribute is valid
- Language `.ini` files exist
- `index.html` directory listing protection in `src/`, `src/admin/`, `src/site/`
---
*Managed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). See [docs/workflows/update-server.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/workflows/update-server.md) for the full specification.*
@@ -3,17 +3,17 @@
; License GNU General Public License version 3 or later; see LICENSE
; Note: All ini files need to be saved as UTF-8
PLG_SYSTEM_MOKOJOOMTOS="System - Offline Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS="System - Moko Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION="Allows Terms of Service to be accessible via menu slug when the site is in offline mode. Simply configure the menu slug (e.g., 'terms-of-service') and that page will remain accessible even when the site is offline."
; Configuration
PLG_SYSTEM_MOKOJOOMTOS_FIELDSET_BASIC="Basic Settings"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Terms of Service Menu Slug"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Enter the menu slug for your Terms of Service page (e.g., 'terms-of-service'). This page will be accessible even when the site is offline. The slug must match the menu item alias exactly."
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Offline-Accessible Menu Items"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Select one or more menu items that should remain accessible when the site is in offline mode. Hold Ctrl/Cmd to select multiple items."
; Help
PLG_SYSTEM_MOKOJOOMTOS_HELP_LABEL="How to Use This Plugin"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create a Joomla article for your Terms of Service.<br/><strong>Step 2:</strong> Create a menu item pointing to that article.<br/><strong>Step 3:</strong> Set the menu item alias/slug (e.g., 'terms-of-service').<br/><strong>Step 4:</strong> Enter that same slug above.<br/><strong>Step 5:</strong> When your site goes offline, visitors can still access yoursite.com/terms-of-service"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create articles for your legal pages (Terms of Service, Privacy Policy, etc.).<br/><strong>Step 2:</strong> Create menu items pointing to those articles.<br/><strong>Step 3:</strong> Select the menu items above (hold Ctrl/Cmd to select multiple).<br/><strong>Step 4:</strong> When your site goes offline, visitors can still access the selected pages.<br/><br/><em>Tip:</em> The dropdown shows the full URL path for each menu item (e.g., /legal/terms-of-service)."
; Errors
PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS="Error loading menu items: %s"
@@ -3,5 +3,5 @@
; License GNU General Public License version 3 or later; see LICENSE
; Note: All ini files need to be saved as UTF-8
PLG_SYSTEM_MOKOJOOMTOS="System - Offline Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS="System - Moko Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION="Allows Terms of Service to be accessible via menu slug when site is offline"
@@ -3,17 +3,17 @@
; License GNU General Public License version 3 or later; see LICENSE
; Note: All ini files need to be saved as UTF-8
PLG_SYSTEM_MOKOJOOMTOS="System - Offline Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS="System - Moko Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION="Allows Terms of Service to be accessible via menu slug when the site is in offline mode. Simply configure the menu slug (e.g., 'terms-of-service') and that page will remain accessible even when the site is offline."
; Configuration
PLG_SYSTEM_MOKOJOOMTOS_FIELDSET_BASIC="Basic Settings"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Terms of Service Menu Slug"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Enter the menu slug for your Terms of Service page (e.g., 'terms-of-service'). This page will be accessible even when the site is offline. The slug must match the menu item alias exactly."
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Offline-Accessible Menu Items"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Select one or more menu items that should remain accessible when the site is in offline mode. Hold Ctrl/Cmd to select multiple items."
; Help
PLG_SYSTEM_MOKOJOOMTOS_HELP_LABEL="How to Use This Plugin"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create a Joomla article for your Terms of Service.<br/><strong>Step 2:</strong> Create a menu item pointing to that article.<br/><strong>Step 3:</strong> Set the menu item alias/slug (e.g., 'terms-of-service').<br/><strong>Step 4:</strong> Enter that same slug above.<br/><strong>Step 5:</strong> When your site goes offline, visitors can still access yoursite.com/terms-of-service"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create articles for your legal pages (Terms of Service, Privacy Policy, etc.).<br/><strong>Step 2:</strong> Create menu items pointing to those articles.<br/><strong>Step 3:</strong> Select the menu items above (hold Ctrl/Cmd to select multiple).<br/><strong>Step 4:</strong> When your site goes offline, visitors can still access the selected pages.<br/><br/><em>Tip:</em> The dropdown shows the full URL path for each menu item (e.g., /legal/terms-of-service)."
; Errors
PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS="Error loading menu items: %s"
@@ -3,5 +3,5 @@
; License GNU General Public License version 3 or later; see LICENSE
; Note: All ini files need to be saved as UTF-8
PLG_SYSTEM_MOKOJOOMTOS="System - Offline Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS="System - Moko Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION="Allows Terms of Service to be accessible via menu slug when site is offline"
@@ -3,17 +3,17 @@
; License GNU General Public License version 3 or later; see LICENSE
; Note: All ini files need to be saved as UTF-8
PLG_SYSTEM_MOKOJOOMTOS="System - Offline Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS="System - Moko Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION="Allows Terms of Service to be accessible via menu slug when the site is in offline mode. Simply configure the menu slug (e.g., 'terms-of-service') and that page will remain accessible even when the site is offline."
; Configuration
PLG_SYSTEM_MOKOJOOMTOS_FIELDSET_BASIC="Basic Settings"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Terms of Service Menu Slug"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Enter the menu slug for your Terms of Service page (e.g., 'terms-of-service'). This page will be accessible even when the site is offline. The slug must match the menu item alias exactly."
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Offline-Accessible Menu Items"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Select one or more menu items that should remain accessible when the site is in offline mode. Hold Ctrl/Cmd to select multiple items."
; Help
PLG_SYSTEM_MOKOJOOMTOS_HELP_LABEL="How to Use This Plugin"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create a Joomla article for your Terms of Service.<br/><strong>Step 2:</strong> Create a menu item pointing to that article.<br/><strong>Step 3:</strong> Set the menu item alias/slug (e.g., 'terms-of-service').<br/><strong>Step 4:</strong> Enter that same slug above.<br/><strong>Step 5:</strong> When your site goes offline, visitors can still access yoursite.com/terms-of-service"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create articles for your legal pages (Terms of Service, Privacy Policy, etc.).<br/><strong>Step 2:</strong> Create menu items pointing to those articles.<br/><strong>Step 3:</strong> Select the menu items above (hold Ctrl/Cmd to select multiple).<br/><strong>Step 4:</strong> When your site goes offline, visitors can still access the selected pages.<br/><br/><em>Tip:</em> The dropdown shows the full URL path for each menu item (e.g., /legal/terms-of-service)."
; Errors
PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS="Error loading menu items: %s"
@@ -3,17 +3,17 @@
; License GNU General Public License version 3 or later; see LICENSE
; Note: All ini files need to be saved as UTF-8
PLG_SYSTEM_MOKOJOOMTOS="System - Offline Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS="System - Moko Terms of Service"
PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION="Allows Terms of Service to be accessible via menu slug when the site is in offline mode. Simply configure the menu slug (e.g., 'terms-of-service') and that page will remain accessible even when the site is offline."
; Configuration
PLG_SYSTEM_MOKOJOOMTOS_FIELDSET_BASIC="Basic Settings"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Terms of Service Menu Slug"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Enter the menu slug for your Terms of Service page (e.g., 'terms-of-service'). This page will be accessible even when the site is offline. The slug must match the menu item alias exactly."
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL="Offline-Accessible Menu Items"
PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC="Select one or more menu items that should remain accessible when the site is in offline mode. Hold Ctrl/Cmd to select multiple items."
; Help
PLG_SYSTEM_MOKOJOOMTOS_HELP_LABEL="How to Use This Plugin"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create a Joomla article for your Terms of Service.<br/><strong>Step 2:</strong> Create a menu item pointing to that article.<br/><strong>Step 3:</strong> Set the menu item alias/slug (e.g., 'terms-of-service').<br/><strong>Step 4:</strong> Enter that same slug above.<br/><strong>Step 5:</strong> When your site goes offline, visitors can still access yoursite.com/terms-of-service"
PLG_SYSTEM_MOKOJOOMTOS_HELP_DESC="<strong>Step 1:</strong> Create articles for your legal pages (Terms of Service, Privacy Policy, etc.).<br/><strong>Step 2:</strong> Create menu items pointing to those articles.<br/><strong>Step 3:</strong> Select the menu items above (hold Ctrl/Cmd to select multiple).<br/><strong>Step 4:</strong> When your site goes offline, visitors can still access the selected pages.<br/><br/><em>Tip:</em> The dropdown shows the full URL path for each menu item (e.g., /legal/terms-of-service)."
; Errors
PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS="Error loading menu items: %s"
+81 -72
View File
@@ -8,98 +8,107 @@
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Uri\Uri;
/**
* MokoJoomTOS Offline Mode Bypass Plugin
* MokoJoomTOS Offline Mode Bypass Plugin (Legacy)
*
* Allows Terms of Service menu to be accessible via slug when the site
* Allows configured menu items to remain accessible when the site
* is in offline mode.
*
* @since 1.0.0
*/
class PlgSystemMokojoomtos extends CMSPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 1.0.0
*/
protected $autoloadLanguage = true;
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 1.0.0
*/
protected $autoloadLanguage = true;
/**
* Application object
*
* @var \Joomla\CMS\Application\CMSApplication
* @since 1.0.0
*/
protected $app;
/**
* Application object
*
* @var \Joomla\CMS\Application\CMSApplication
* @since 1.0.0
*/
protected $app;
/**
* After route event handler
*
* Checks if the current request is for the Terms of Service slug and if
* the site is in offline mode. If both conditions are met, temporarily
* disables offline mode and sets component-only view for this request.
*
* This event fires after routing but before template selection, making it
* the correct place to set tmpl=component to prevent template chrome loading.
*
* @return void
*
* @since 03.08.04
*/
public function onAfterRoute()
{
// Only process for site application
if (!$this->app->isClient('site'))
{
return;
}
/**
* After route event handler
*
* @return void
*
* @since 04.00.00
*/
public function onAfterRoute()
{
// Only process for site application
if (!$this->app->isClient('site'))
{
return;
}
// Get the global configuration
$config = $this->app->getConfig();
// Get the global configuration
$config = $this->app->getConfig();
// Only proceed if site is offline
if (!$config->get('offline'))
{
return;
}
// Only proceed if site is offline
if (!$config->get('offline'))
{
return;
}
// Get the configured Terms of Service slug
$tosSlug = trim($this->params->get('tos_slug', 'terms-of-service'));
// Get the configured slugs (stored as array for multi-select)
$slugs = $this->params->get('tos_slug', []);
if (empty($tosSlug))
{
return;
}
// Handle legacy single-value string format
if (is_string($slugs))
{
$slugs = array_filter([trim($slugs)]);
}
// Get the current URI path
$uri = Uri::getInstance();
$path = trim($uri->getPath(), '/');
if (empty($slugs))
{
return;
}
// Remove the base path if present
$base = trim(Uri::base(true), '/');
if (!empty($base) && strpos($path, $base) === 0)
{
$path = trim(substr($path, strlen($base)), '/');
}
// Get the current URI path
$uri = Uri::getInstance();
$path = trim($uri->getPath(), '/');
// Check if the path matches the Terms of Service slug
if ($path === $tosSlug || strpos($path, $tosSlug . '/') === 0)
{
// Temporarily disable offline mode for this request
$config->set('offline', 0);
// Remove the base path if present
$base = trim(Uri::base(true), '/');
if (!empty($base) && strpos($path, $base) === 0)
{
$path = trim(substr($path, strlen($base)), '/');
}
// Set component-only view (no template chrome)
$input = $this->app->input;
$input->set('tmpl', 'component');
// Check if the path matches any configured slug
foreach ($slugs as $slug)
{
$slug = trim($slug);
if (empty($slug))
{
continue;
}
// Also set in GET superglobal to ensure recognition
$_GET['tmpl'] = 'component';
}
}
if ($path === $slug || strpos($path, $slug . '/') === 0)
{
// Temporarily disable offline mode for this request
$config->set('offline', 0);
// Set component-only view (no template chrome)
$input = $this->app->input;
$input->set('tmpl', 'component');
// Also set in GET superglobal to ensure recognition
$_GET['tmpl'] = 'component';
return;
}
}
}
}
+6 -6
View File
@@ -25,19 +25,19 @@
DEFGROUP: MokoJoomTOS
INGROUP: plg_system_mokojoomtos
PATH: src/mokojoomtos.xml
VERSION: 03.08.04
VERSION: 04.00.00
BRIEF: Plugin manifest XML file for MokoJoomTOS system plugin
=========================================================================
-->
<extension type="plugin" group="system" method="upgrade">
<name>plg_system_mokojoomtos</name>
<name>System - Moko Terms of Service</name>
<author>Moko Consulting</author>
<creationDate>2026-01-01</creationDate>
<creationDate>2026-05-16</creationDate>
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
<license>GNU General Public License version 3 or later; see LICENSE</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl>
<version>03.08.04</version>
<version>00.00.01</version>
<description>PLG_SYSTEM_MOKOJOOMTOS_XML_DESCRIPTION</description>
<namespace path="src">Joomla\Plugin\System\MokoJoomTOS</namespace>
@@ -47,6 +47,7 @@
<files>
<filename plugin="mokojoomtos">mokojoomtos.php</filename>
<folder>src</folder>
<folder>services</folder>
<folder>language</folder>
<folder>administrator</folder>
</files>
@@ -68,8 +69,7 @@
type="menuslug"
label="PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_LABEL"
description="PLG_SYSTEM_MOKOJOOMTOS_FIELD_TOS_SLUG_DESC"
default="terms-of-service"
required="true"
multiple="true"
/>
<field
+44
View File
@@ -0,0 +1,44 @@
<?php
/**
* @package MokoJoomTOS
* @subpackage plg_system_mokojoomtos
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
defined('_JEXEC') or die;
use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use Joomla\Plugin\System\MokoJoomTOS\Extension\MokoJoomTOS;
return new class () implements ServiceProviderInterface {
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 04.00.00
*/
public function register(Container $container)
{
$container->set(
PluginInterface::class,
function (Container $container) {
$plugin = new MokoJoomTOS(
$container->get(DispatcherInterface::class),
(array) PluginHelper::getPlugin('system', 'mokojoomtos')
);
$plugin->setApplication(Factory::getApplication());
return $plugin;
}
);
}
};
+97 -90
View File
@@ -10,7 +10,6 @@ namespace Joomla\Plugin\System\MokoJoomTOS\Extension;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Uri\Uri;
use Joomla\Event\SubscriberInterface;
@@ -18,106 +17,114 @@ use Joomla\Event\SubscriberInterface;
/**
* MokoJoomTOS Offline Mode Bypass Plugin
*
* Allows Terms of Service menu to be accessible via slug when the site
* Allows configured menu items to remain accessible when the site
* is in offline mode.
*
* @since 1.0.0
*/
final class MokoJoomTOS extends CMSPlugin implements SubscriberInterface
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 1.0.0
*/
protected $autoloadLanguage = true;
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 1.0.0
*/
protected $autoloadLanguage = true;
/**
* Application object
*
* @var \Joomla\CMS\Application\CMSApplication
* @since 1.0.0
*/
protected $app;
/**
* Returns an array of events this subscriber will listen to.
*
* @return array
*
* @since 1.0.0
*/
public static function getSubscribedEvents(): array
{
return [
'onAfterRoute' => 'onAfterRoute',
];
}
/**
* Returns an array of events this subscriber will listen to.
*
* @return array
*
* @since 1.0.0
*/
public static function getSubscribedEvents(): array
{
return [
'onAfterRoute' => 'onAfterRoute',
];
}
/**
* After route event handler
*
* Checks if the current request matches any configured menu slug and if
* the site is in offline mode. If both conditions are met, temporarily
* disables offline mode and sets component-only view for this request.
*
* This event fires after routing but before template selection, making it
* the correct place to set tmpl=component to prevent template chrome loading.
*
* @return void
*
* @since 1.0.0
*/
public function onAfterRoute()
{
// Only process for site application
if (!$this->getApplication()->isClient('site'))
{
return;
}
/**
* After route event handler
*
* Checks if the current request is for the Terms of Service slug and if
* the site is in offline mode. If both conditions are met, temporarily
* disables offline mode and sets component-only view for this request.
*
* This event fires after routing but before template selection, making it
* the correct place to set tmpl=component to prevent template chrome loading.
*
* @return void
*
* @since 1.0.0
*/
public function onAfterRoute()
{
// Only process for site application
if (!$this->app->isClient('site'))
{
return;
}
// Get the global configuration
$config = $this->getApplication()->getConfig();
// Get the global configuration
$config = $this->app->getConfig();
// Only proceed if site is offline
if (!$config->get('offline'))
{
return;
}
// Only proceed if site is offline
if (!$config->get('offline'))
{
return;
}
// Get the configured Terms of Service slug
$tosSlug = trim($this->params->get('tos_slug', 'terms-of-service'));
if (empty($tosSlug))
{
return;
}
// Get the configured slugs (stored as array for multi-select)
$slugs = $this->params->get('tos_slug', []);
// Get the current URI path
$uri = Uri::getInstance();
$path = trim($uri->getPath(), '/');
// Remove the base path if present
$base = trim(Uri::base(true), '/');
if (!empty($base) && strpos($path, $base) === 0)
{
$path = trim(substr($path, strlen($base)), '/');
}
// Handle legacy single-value string format
if (is_string($slugs))
{
$slugs = array_filter([trim($slugs)]);
}
// Check if the path matches the Terms of Service slug
if ($path === $tosSlug || strpos($path, $tosSlug . '/') === 0)
{
// Temporarily disable offline mode for this request
$config->set('offline', 0);
// Set component-only view (no template chrome)
// This ensures clean display without full site template
$input = $this->app->input;
$input->set('tmpl', 'component');
// Also set it in the GET superglobal to ensure it's recognized
$_GET['tmpl'] = 'component';
}
}
if (empty($slugs))
{
return;
}
// Get the current URI path
$uri = Uri::getInstance();
$path = trim($uri->getPath(), '/');
// Remove the base path if present
$base = trim(Uri::base(true), '/');
if (!empty($base) && strpos($path, $base) === 0)
{
$path = trim(substr($path, strlen($base)), '/');
}
// Check if the path matches any configured slug
foreach ($slugs as $slug)
{
$slug = trim($slug);
if (empty($slug))
{
continue;
}
if ($path === $slug || strpos($path, $slug . '/') === 0)
{
// Temporarily disable offline mode for this request
$config->set('offline', 0);
// Set component-only view (no template chrome)
$input = $this->getApplication()->input;
$input->set('tmpl', 'component');
// Also set in GET superglobal to ensure recognition
$_GET['tmpl'] = 'component';
return;
}
}
}
}
+66 -68
View File
@@ -17,83 +17,81 @@ use Joomla\CMS\Language\Text;
/**
* Menu Slug Field
*
* Provides a dropdown list of menu items with their aliases (slugs)
* Provides a multi-select dropdown of menu items with their full route paths
*
* @since 1.0.0
*/
class MenuslugField extends ListField
{
/**
* The form field type.
*
* @var string
* @since 1.0.0
*/
protected $type = 'Menuslug';
/**
* The form field type.
*
* @var string
* @since 1.0.0
*/
protected $type = 'Menuslug';
/**
* Method to get the field options.
*
* @return array The field option objects.
*
* @since 1.0.0
*/
protected function getOptions()
{
$options = parent::getOptions();
/**
* Method to get the field options.
*
* @return array The field option objects.
*
* @since 1.0.0
*/
protected function getOptions()
{
$options = parent::getOptions();
try
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(['alias', 'title', 'menutype']))
->from($db->quoteName('#__menu'))
->where($db->quoteName('published') . ' = 1')
->where($db->quoteName('client_id') . ' = 0')
->where($db->quoteName('alias') . ' != ' . $db->quote(''))
->order($db->quoteName('menutype') . ', ' . $db->quoteName('title'));
try
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(['path', 'alias', 'title', 'menutype']))
->from($db->quoteName('#__menu'))
->where($db->quoteName('published') . ' = 1')
->where($db->quoteName('client_id') . ' = 0')
->where($db->quoteName('alias') . ' != ' . $db->quote(''))
->order($db->quoteName('menutype') . ', ' . $db->quoteName('title'));
$db->setQuery($query);
$menuItems = $db->loadObjectList();
$db->setQuery($query);
$menuItems = $db->loadObjectList();
if ($menuItems)
{
$lastMenuType = '';
foreach ($menuItems as $item)
{
// Add menu type separator for better organization
if ($item->menutype !== $lastMenuType)
{
if ($lastMenuType !== '')
{
// Add a separator between menu types
$options[] = (object) [
'value' => '',
'text' => '──────────────',
'disable' => true
];
}
$lastMenuType = $item->menutype;
}
if ($menuItems)
{
$lastMenuType = '';
$displayText = $item->title !== '' ? $item->title : ucwords(str_replace(['-', '_'], ' ', $item->alias));
$options[] = (object) [
'value' => $item->alias,
'text' => $displayText . ' (' . $item->alias . ')'
];
}
}
}
catch (\Exception $e)
{
// Log error but don't break the form
Factory::getApplication()->enqueueMessage(
Text::sprintf('PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS', $e->getMessage()),
'warning'
);
}
foreach ($menuItems as $item)
{
// Add menu type separator for better organization
if ($item->menutype !== $lastMenuType)
{
if ($lastMenuType !== '')
{
$options[] = (object) [
'value' => '',
'text' => '──────────────',
'disable' => true
];
}
$lastMenuType = $item->menutype;
}
return $options;
}
$displayText = $item->title !== '' ? $item->title : ucwords(str_replace(['-', '_'], ' ', $item->alias));
$options[] = (object) [
'value' => $item->path,
'text' => $displayText . ' (/' . $item->path . ')'
];
}
}
}
catch (\Exception $e)
{
Factory::getApplication()->enqueueMessage(
Text::sprintf('PLG_SYSTEM_MOKOJOOMTOS_ERROR_LOADING_MENU_ITEMS', $e->getMessage()),
'warning'
);
}
return $options;
}
}
+92 -38
View File
@@ -1,44 +1,98 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
VERSION: 03.08.04
VERSION: 04.00.00
-->
Joomla Extension Update Server XML
See: https://docs.joomla.org/Deploying_an_Update_Server
This file is the update server manifest for MokoJoomTOS.
The Joomla installer polls this URL to check for new versions.
The manifest.xml in this repository must reference BOTH update servers:
<updateservers>
<server type="extension" priority="1" name="MokoJoomTOS Update Server (Gitea)">
https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/raw/branch/main/updates.xml
</server>
<server type="extension" priority="2" name="MokoJoomTOS Update Server (GitHub)">
https://raw.githubusercontent.com/mokoconsulting-tech/MokoJoomTOS/main/updates.xml
</server>
</updateservers>
When a new release is made, run `make release` or the release workflow to
prepend a new <update> entry to this file automatically.
-->
<updates>
<update>
<name>plg_system_mokojoomtos</name>
<description>MokoJoomTOS — Moko Consulting Joomla plugin</description>
<element>plg_system_mokojoomtos</element>
<type>plugin</type>
<folder>system</folder>
<version>03.08.04</version>
<downloads>
<downloadurl type="full" format="zip">
https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/download/v03/plg_system_mokojoomtos-03.08.04.zip
</downloadurl>
<downloadurl type="full" format="zip">
https://github.com/mokoconsulting-tech/MokoJoomTOS/releases/download/v03/plg_system_mokojoomtos-03.08.04.zip
</downloadurl>
</downloads>
<targetplatform name="joomla" version="[56].*"/>
<php_minimum>8.1</php_minimum>
</update>
<update>
<name>plg_system_mokojoomtos</name>
<description>plg_system_mokojoomtos update</description>
<element>mokojoomtos</element>
<type>plugin</type>
<version>04.00.00</version>
<client>site</client>
<folder>system</folder>
<tags><tag>development</tag></tags>
<infourl title="plg_system_mokojoomtos">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/download/stable/plg_system_mokojoomtos-04.00.00.zip</downloadurl>
</downloads>
<sha256>6d8c6a03d6dc0a784a4442c9c46e1a79e8f65b3da7091c5857958653c5b6efe3</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
<update>
<name>plg_system_mokojoomtos</name>
<description>plg_system_mokojoomtos update</description>
<element>mokojoomtos</element>
<type>plugin</type>
<version>04.00.00</version>
<client>site</client>
<folder>system</folder>
<tags><tag>alpha</tag></tags>
<infourl title="plg_system_mokojoomtos">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/download/stable/plg_system_mokojoomtos-04.00.00.zip</downloadurl>
</downloads>
<sha256>6d8c6a03d6dc0a784a4442c9c46e1a79e8f65b3da7091c5857958653c5b6efe3</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
<update>
<name>plg_system_mokojoomtos</name>
<description>plg_system_mokojoomtos update</description>
<element>mokojoomtos</element>
<type>plugin</type>
<version>04.00.00</version>
<client>site</client>
<folder>system</folder>
<tags><tag>beta</tag></tags>
<infourl title="plg_system_mokojoomtos">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/download/stable/plg_system_mokojoomtos-04.00.00.zip</downloadurl>
</downloads>
<sha256>6d8c6a03d6dc0a784a4442c9c46e1a79e8f65b3da7091c5857958653c5b6efe3</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
<update>
<name>plg_system_mokojoomtos</name>
<description>plg_system_mokojoomtos update</description>
<element>mokojoomtos</element>
<type>plugin</type>
<version>04.00.00</version>
<client>site</client>
<folder>system</folder>
<tags><tag>rc</tag></tags>
<infourl title="plg_system_mokojoomtos">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/download/stable/plg_system_mokojoomtos-04.00.00.zip</downloadurl>
</downloads>
<sha256>6d8c6a03d6dc0a784a4442c9c46e1a79e8f65b3da7091c5857958653c5b6efe3</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
<update>
<name>plg_system_mokojoomtos</name>
<description>plg_system_mokojoomtos update</description>
<element>mokojoomtos</element>
<type>plugin</type>
<version>04.00.00</version>
<client>site</client>
<folder>system</folder>
<tags><tag>stable</tag></tags>
<infourl title="plg_system_mokojoomtos">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomTOS/releases/download/stable/plg_system_mokojoomtos-04.00.00.zip</downloadurl>
</downloads>
<sha256>6d8c6a03d6dc0a784a4442c9c46e1a79e8f65b3da7091c5857958653c5b6efe3</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
</updates>