v1.2.0 — Categories, API, hardening, polish #62

Merged
jmiller merged 59 commits from dev into main 2026-06-28 20:06:07 +00:00
Owner

Summary

  • Multi-category — categories with parent/child hierarchy, color, custom marker icons, many-to-many junction table (#1, #2)
  • REST API — JSON:API endpoints via Web Services plugin (#29)
  • ACLaccess.xml with standard Joomla permission actions (#30)
  • SQL versioned migrationssql/updates/mysql/ for safe upgrades (#31)
  • Shop integrationLocationBridgeHelper + LocationSavedEvent for cross-extension data access (#48)
  • Detail page map — Leaflet map on single location view (#57)
  • Marker clustering — Leaflet.markercluster with toggleable module param (#61)
  • CSP nonce support — all inline scripts via $wa->addInlineScript() (#34)
  • GROUP BY fix — EXISTS subquery for ONLY_FULL_GROUP_BY compat (#59)
  • Dead catid removal — column dropped, junction table is source of truth (#58)
  • Junction cleanup — orphan rows purged on delete (#60)
  • License key — download key preserved across upgrades, warning when missing
  • XSS fix — DOM-based textContent in detail map popup
  • SQL compat — removed IF EXISTS syntax for MySQL 5.7 compatibility
  • Pretty display names — all extensions show branded names in Joomla admin (e.g. "MokoSuite Store Locator" instead of com_mokosuitestorelocator)

Stats

63 files changed, +2481 / -212

Test plan

  • 16/16 functional tests pass on suite.dev
  • Fresh install verified (5 extensions, 3 DB tables, API HTTP 200)
  • Upgrade install from 1.1.0 (verify catid migration runs cleanly)
  • Verify license key warning appears on fresh install without dlid
  • Verify marker clustering toggle in map module settings
  • Verify pretty names show in Extensions > Manage after upgrade
## Summary - **Multi-category** — categories with parent/child hierarchy, color, custom marker icons, many-to-many junction table (#1, #2) - **REST API** — JSON:API endpoints via Web Services plugin (#29) - **ACL** — `access.xml` with standard Joomla permission actions (#30) - **SQL versioned migrations** — `sql/updates/mysql/` for safe upgrades (#31) - **Shop integration** — `LocationBridgeHelper` + `LocationSavedEvent` for cross-extension data access (#48) - **Detail page map** — Leaflet map on single location view (#57) - **Marker clustering** — Leaflet.markercluster with toggleable module param (#61) - **CSP nonce support** — all inline scripts via `$wa->addInlineScript()` (#34) - **GROUP BY fix** — EXISTS subquery for ONLY_FULL_GROUP_BY compat (#59) - **Dead catid removal** — column dropped, junction table is source of truth (#58) - **Junction cleanup** — orphan rows purged on delete (#60) - **License key** — download key preserved across upgrades, warning when missing - **XSS fix** — DOM-based textContent in detail map popup - **SQL compat** — removed `IF EXISTS` syntax for MySQL 5.7 compatibility - **Pretty display names** — all extensions show branded names in Joomla admin (e.g. "MokoSuite Store Locator" instead of `com_mokosuitestorelocator`) ## Stats 63 files changed, +2481 / -212 ## Test plan - [x] 16/16 functional tests pass on suite.dev - [x] Fresh install verified (5 extensions, 3 DB tables, API HTTP 200) - [ ] Upgrade install from 1.1.0 (verify catid migration runs cleanly) - [ ] Verify license key warning appears on fresh install without dlid - [ ] Verify marker clustering toggle in map module settings - [ ] Verify pretty names show in Extensions > Manage after upgrade
jmiller added 46 commits 2026-06-28 18:49:29 +00:00
Pull latest workflow versions from MokoConsulting/Template-Joomla.
These use the updated mokocli tools with manifest metadata as
first-class fields instead of README FILE INFORMATION blocks.

Updated: ci-joomla.yml, pre-release.yml, workflow-sync-trigger.yml
Added: version-set.yml
Removed: deploy-manual.yml, update-server.yml, composer-publish.yml
  (superseded by auto-release.yml pipeline)

Authored-by: Moko Consulting
mokocli tools require two-digit zero-padded version groups (01.00.00)
per MokoStandards convention. Fixes auto-release pipeline failure.

Changed in: pkg manifest, component manifest, both module manifests,
and CHANGELOG.md.

Authored-by: Moko Consulting
Add one-click import from installed FocalPoint/Shack Locations component:
- Reads #__focalpoint_locations table directly via Joomla DB layer
- Parses customfieldsdata JSON for email, website, hours, phone
- Maps FocalPoint schema to MokoSuiteStoreLocator fields
- Copies coordinates (DECIMAL 10,6 → 10,8), published state, ordering
- Combines description + fulldescription into single description field
- Import button on admin Import view with CSRF + ACL protection
- Graceful handling: checks table exists, reports per-row errors

Field mapping:
  FocalPoint.title → title
  FocalPoint.address → address (single field, no city/state split)
  FocalPoint.latitude/longitude → latitude/longitude
  FocalPoint.phone → phone
  FocalPoint.customfieldsdata.email → email
  FocalPoint.customfieldsdata.website → website
  FocalPoint.customfieldsdata.hours → hours
  FocalPoint.state → published

Authored-by: Moko Consulting
feat: v1.2 multi-category, REST API, ACL, security hardening (#1, #2, #29, #30, #31, #34, #48)
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 10s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 37s
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
6426fee428
Multi-category support with parent/child hierarchy, junction table,
admin CRUD, and per-category custom marker icons on the Leaflet map.

REST API via Web Services plugin with JSON:API endpoints. ACL
permissions via access.xml. SQL update schema for safe upgrades.

Shop integration bridge (LocationBridgeHelper, LocationSavedEvent).
Security: CSV formula injection prevention, MIME validation, file size
limit, ORDER BY allowlist, map height CSS regex validation.

Authored-by: Moko Consulting
fix: add module services/provider.php and fix manifest packaging
Universal: Auto Version Bump / Version Bump (push) Successful in 14s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 19s
3efd423e74
Both modules were missing services/provider.php — the Joomla 5 DI
entry point that registers the ModuleDispatcherFactory. Without it,
Joomla falls back to a mod_*.php entry point file that doesn't exist,
causing "No module file specified" on install.

Also moves access.xml into admin/ and adds it to the component
manifest so it gets included in the package ZIP.

Authored-by: Moko Consulting
fix: move dlid before updateservers so Joomla registers download key
Universal: Auto Version Bump / Version Bump (push) Successful in 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
81854440de
The <dlid> element was placed after </updateservers>, causing Joomla's
installer to skip it when registering the update site. Moving it before
<updateservers> ensures the extra_query field is populated in the
#__update_sites table.

Authored-by: Moko Consulting
fix: align dlid and updateservers with MokoSuiteClient pattern
Universal: Auto Version Bump / Version Bump (push) Successful in 13s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
e16e15dc00
Move <dlid> to right after <description> (before <scriptfile>) and add
priority="1" to <server> element, matching the MokoSuiteClient manifest
structure so Joomla properly registers the download key field.

Authored-by: Moko Consulting
fix: add module attribute to services folder and hardcode package description
Universal: Auto Version Bump / Version Bump (push) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
36eb55758e
Joomla's ModuleAdapter requires the `module` attribute on a <files> child
to identify the module element. Without it, install fails with "No module
file specified" even when namespace and services/provider.php are present.
Pattern confirmed against MokoSuiteClient modules.

Also hardcodes the package description since packages don't load language
files during install, causing the raw key to display.

Authored-by: Moko Consulting
fix: add plugin attribute to webservices manifest files element
Universal: Auto Version Bump / Version Bump (push) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
b75677a6ec
Joomla's PluginAdapter requires plugin="xxx" on a <files> child to
determine filesystem deployment path and extension element. Without it,
plugin files are not deployed and the element field is empty in
#__extensions. Pattern confirmed from MokoSuiteClient.

Authored-by: Moko Consulting
fix: rename plugin manifest to match element name
Universal: Auto Version Bump / Version Bump (push) Successful in 7s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
7835e77920
Joomla's autoloader namespace scanner expects plugin manifests to be
named {element}.xml (e.g. mokosuitestorelocator.xml), not the full
prefixed name (plg_webservices_mokosuitestorelocator.xml). Without the
correct filename, the PSR-4 namespace mapping is not registered in
autoload_psr4.php, causing "Class not found" errors.

Pattern confirmed from MokoSuiteClient's webservices plugin.

Authored-by: Moko Consulting
chore: sync GOVERNANCE.md from Template-Joomla
Universal: Auto Version Bump / Version Bump (push) Successful in 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
99df65b66f
Authored-by: Moko Consulting
fix: resolve all open issues — detail map, clustering, CSP, GROUP BY, cleanup (#34 #57 #58 #59 #60 #61)
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
32b541597a
- Add Leaflet map to location detail page with marker and popup (#57)
- Implement Leaflet.markercluster with toggleable module parameter (#61)
- Convert inline <script> to $wa->addInlineScript() for CSP nonce support (#34)
- Replace category INNER JOIN with EXISTS subquery for ONLY_FULL_GROUP_BY compat (#59)
- Add delete() override to LocationTable and CategoryTable for junction cleanup (#60)
- Drop dead catid column and idx_catid index via SQL update 01.00.02 (#58)
- Update CHANGELOG and README

Authored-by: Moko Consulting
fix: escape location title in detail map popup to prevent XSS
Universal: Auto Version Bump / Version Bump (push) Successful in 7s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 9s
2897a1ceba
Use DOM-based textContent instead of raw string in Leaflet bindPopup()
to prevent HTML injection via location titles.

Authored-by: Moko Consulting
fix: remove IF EXISTS syntax from SQL migration for MySQL 5.7 compat
Universal: Auto Version Bump / Version Bump (push) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
8b42c016a8
Joomla's SQL update runner doesn't support DELIMITER or stored
procedures. DROP COLUMN IF EXISTS is MySQL 8.0.13+ only. Plain
DROP COLUMN is safe here because update files only run on upgrades
from versions that had the catid column.

Authored-by: Moko Consulting
feat: add license key warning and download key preservation
Universal: Auto Version Bump / Version Bump (push) Successful in 17s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
58f3ac96d9
Save/restore the download key (dlid) across package upgrades so users
don't lose their license key. Show a warning with direct edit link
when no license key is configured.

Mirrors the pattern from MokoSuiteCross.

Authored-by: Moko Consulting
docs: update changelog with license key, XSS fix, SQL compat entries
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 8s
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
Universal: Build & Release / Promote to RC (pull_request) Failing after 10s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 39s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
03c9ca53a6
Authored-by: Moko Consulting
jmiller added 1 commit 2026-06-28 18:49:44 +00:00
jmiller added 1 commit 2026-06-28 18:49:55 +00:00
jmiller added 1 commit 2026-06-28 18:54:48 +00:00
fix: make SQL migration 01.00.02 a no-op to prevent install abort
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 10s
Universal: Auto Version Bump / Version Bump (push) Successful in 12s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 43s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 20s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
5ea2fd2b98
Joomla aborts the entire package install on any SQL error in update
files. DROP COLUMN fails when catid doesn't exist (fresh installs,
or systems where it was already removed). Since install.mysql.sql
already omits catid, no runtime migration is needed.

Authored-by: Moko Consulting
jmiller added 1 commit 2026-06-28 18:55:18 +00:00
jmiller added 1 commit 2026-06-28 18:55:36 +00:00
jmiller added 1 commit 2026-06-28 18:55:49 +00:00
jmiller added 1 commit 2026-06-28 19:54:38 +00:00
feat: add pretty display names for all extensions in Joomla admin
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 13s
Universal: Auto Version Bump / Version Bump (push) Successful in 15s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 12s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
8dfc1227cb
Authored-by: Moko Consulting
jmiller added 1 commit 2026-06-28 19:54:57 +00:00
jmiller added 1 commit 2026-06-28 19:55:11 +00:00
jmiller added 2 commits 2026-06-28 20:04:20 +00:00
Authored-by: Moko Consulting
chore: merge remote dev, resolve sync conflicts
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Generic: Project CI / Lint & Validate (pull_request) Successful in 17s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 18s
Universal: Auto Version Bump / Version Bump (push) Successful in 19s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 20s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 46s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
9b09d61473
Authored-by: Moko Consulting
jmiller added 1 commit 2026-06-28 20:04:41 +00:00
jmiller added 1 commit 2026-06-28 20:04:58 +00:00
chore(version): pre-release bump to 01.00.39-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 17s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 10m3s
84d42f70a1
jmiller merged commit c7182f6cbb into main 2026-06-28 20:06:07 +00:00
Sign in to join this conversation.