From 7fa938321482e920b5ebb45c4757cf6bee24ac4b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 11:48:00 +0000 Subject: [PATCH] Audit references/module.md (#3): add cross-links, fill 4 gaps, J6.1 verify Closes the module.md checklist in #3. Cross-references to shared refs (cross-cutting principle from #2): - Manifest XML section: cross-link intro pointing to manifest.md for universal elements; example keeps module-specific bits (client=, ). - New Language Files section: MOD_* prefix specifics + cross-link to language-files.md. - Service Provider section: cross-link intro pointing to service-provider.md for the universal wrapping pattern; example keeps module-specific factory triple (ModuleDispatcherFactory, HelperFactory, Module). - New Install Script (Optional) section: pointer to install-script.md with note that modules rarely need one. Content gaps closed (flagged by audit): - Web Asset Manager registration from the dispatcher: new subsection showing useStyle/useScript against joomla.asset.json-resolved URIs and where to register Text::script() keys, with cross-reference to gotchas.md for the URI-resolution and truthy-key rules. - Caching: new section explaining default per-instance keying, the two cases that need user attention (URL-dependent + session-state- dependent output), and the absence of a public dispatcher-level cache-key hook. Joomla 6.1 verification (continuous discipline from issue #11): - Dispatcher section cites AbstractModuleDispatcher on 6.1-dev for constructor + getLayoutData signatures. - Service Provider section cites mod_articles_news provider on 6.1-dev for the factory triple. - New Joomla 6.1 capabilities section covers PR #46772 (Versions for Modules / #__ucm_history) and PR #46622 (#__extensions.custom_data column). Both additive, no existing-code changes required. Table of Contents rebuilt to expose all new sections and flag which content lives in the shared references. CHANGELOG [Unreleased] gets new sections for the additions and verifications. --- CHANGELOG.md | 13 +++++ skills/joomla/references/module.md | 94 ++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 987e0c7..59be2db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,19 @@ All notable changes to the Joomla skill are documented here. The format follows - `references/plugin.md` — Removed the now-dead `use Joomla\Event\DispatcherInterface;` import from the plugin class example (it was only there to satisfy the old constructor's typed parameter). - `references/service-provider.md` — Plugin row in the "what each extension type registers" table updated: plugins don't use any `Service\Provider\*` factory shorthand; the provider just `new`s the class with `$config`. Added the J6.0 → J6.1+ deprecation note pointing at `references/plugin.md` for the full story. +### Added (issue #3 — `references/module.md` audit) +- `references/module.md` — Table of Contents rebuilt to flag the universal-content references (`manifest.md`, `language-files.md`, `service-provider.md`, `install-script.md`) on each affected line, and to expose the new sections. +- `references/module.md` — Cross-link intros on the Manifest XML and Service Provider sections, deferring universal content to the shared references and keeping module-specific concretizations (`client="site"`/`administrator"`, ``; `ModuleDispatcherFactory` + `HelperFactory` + `Module` factory triple). +- `references/module.md` — New **Language Files** section with `MOD_*` prefix specifics, the no-`folder=""` `` quirk, and a pointer to [`language-files.md`](references/language-files.md) for the full conventions. +- `references/module.md` — New **Web Asset Manager registration from the dispatcher** subsection inside Dispatcher, showing how to use `useStyle`/`useScript` against `joomla.asset.json`-resolved URIs and where to register `Text::script()` keys. Cross-references `gotchas.md` for URI-auto-resolution and the truthy-key trap. +- `references/module.md` — New **Caching** section explaining default per-instance keying, the two cases that need user attention (URL-dependent output, session-state-dependent output), and the absence of a public dispatcher-level cache-key hook. +- `references/module.md` — New **Install Script (Optional)** section noting that modules rarely need a `` and pointing to [`install-script.md`](references/install-script.md) for the shared lifecycle pattern. +- `references/module.md` — New **Joomla 6.1 capabilities** section covering [PR #46772 (Versions for Modules / `#__ucm_history`)](https://github.com/joomla/joomla-cms/pull/46772) and [PR #46622 (`#__extensions.custom_data` JSON column)](https://github.com/joomla/joomla-cms/pull/46622). Neither requires existing module code to change; both are additive. + +### Verified +- `references/module.md` Dispatcher section now cites [`AbstractModuleDispatcher` on `joomla-cms` `6.1-dev`](https://github.com/joomla/joomla-cms/blob/6.1-dev/libraries/src/Dispatcher/AbstractModuleDispatcher.php) for the constructor and `getLayoutData()` signatures. +- `references/module.md` Service Provider section now cites [`mod_articles_news/services/provider.php` on `joomla-cms` `6.1-dev`](https://github.com/joomla/joomla-cms/blob/6.1-dev/modules/mod_articles_news/services/provider.php) for the factory triple. Both confirm the existing patterns are current as of 6.1. + ### Fixed - Removed brand-specific references (CWM / Proclaim / EventBooking) from `SKILL.md` and `references/module.md`. The skill is generic Joomla guidance and shouldn't lean on specific third-party extension code or naming conventions as canonical examples. Replaced with vendor-neutral placeholders (``, `Acme`, generic `bookings`/`items`) and a generic note about projects shipping admin + site modules in one source tree. The `Joomla-Bible-Study/claude-skill-joomla` GitHub URL stays — that's the skill's own home, not borrowed code. diff --git a/skills/joomla/references/module.md b/skills/joomla/references/module.md index f7ae7d8..daeccba 100644 --- a/skills/joomla/references/module.md +++ b/skills/joomla/references/module.md @@ -2,11 +2,16 @@ ## Table of Contents 1. [Directory Structure](#directory-structure) -2. [Manifest XML](#manifest-xml) -3. [Service Provider](#service-provider) -4. [Dispatcher](#dispatcher) -5. [Helper Class](#helper-class) -6. [Template (Layout)](#template) +2. [Manifest XML](#manifest-xml) — universal elements in [`manifest.md`](manifest.md) +3. [Language Files](#language-files) — full conventions in [`language-files.md`](language-files.md) +4. [Service Provider](#service-provider) — universal pattern in [`service-provider.md`](service-provider.md) +5. [Dispatcher](#dispatcher) (incl. Web Asset Manager registration) +6. [Helper Class](#helper-class) +7. [Template (Layout)](#template-layout) +8. [Caching](#caching) +9. [Install Script (Optional)](#install-script-optional) — full walkthrough in [`install-script.md`](install-script.md) +10. [Admin Module](#admin-module) +11. [Joomla 6.1 capabilities](#joomla-61-capabilities) --- @@ -35,6 +40,8 @@ mod_example/ ## Manifest XML +For the **universal** elements that appear in every extension type's manifest (`` root attributes, the metadata block, ``, ``, ``, ``, `` / ``) see [`references/manifest.md`](manifest.md). The example below is module-specific: it adds the `client="site"` (or `"administrator"`) attribute and the `` block where module params are declared. + ```xml @@ -96,10 +103,25 @@ Key points: --- +## Language Files + +Modules use the `MOD__*` key prefix and ship two `.ini` files: a runtime file for layout strings (`en-GB.mod_example.ini`) and a `.sys.ini` for the install / Module Manager listing (`en-GB.mod_example.sys.ini`). + +The full conventions — file-naming, plurals, `_FIELD__LABEL` / `_DESC` form-field pattern, `Text::script()` JS registration, the dispatcher as the right place to register module JS strings — are **shared across all extension types** and live in [`references/language-files.md`](language-files.md). Module-specific reminders: + +- The manifest's `` block has no `folder=""` attribute (modules ship a single `language/` subtree). +- Field labels in the `` block (e.g., `MOD_EXAMPLE_COUNT` at line 69) only resolve once the runtime `.ini` is loaded by the Module Manager. Set `MOD_EXAMPLE_XML_DESCRIPTION` to a key in the `.sys.ini` so the Modules listing is translatable. + +--- + ## Service Provider +The wrapping pattern (`ServiceProviderInterface` + anonymous class + `register()` + `Container::registerServiceProvider()`) is shared across components, modules, and plugins. The universal pattern, what each extension type registers, and the common DI pitfalls live in [`references/service-provider.md`](service-provider.md). What's specific to modules is **which factories get registered** — `ModuleDispatcherFactory`, `HelperFactory`, and the generic `Module` provider — and the namespace prefixes the first two take. + **File:** `services/provider.php` +(Verified against [`mod_articles_news/services/provider.php` on `joomla-cms` `6.1-dev`](https://github.com/joomla/joomla-cms/blob/6.1-dev/modules/mod_articles_news/services/provider.php) — same factory set, same namespace-prefix shape.) + ```php getApplication()->getDocument()->getWebAssetManager(); + $wa->useStyle('mod_example.style'); + $wa->useScript('mod_example.script'); + + // Register a JS-loadable language string from the dispatcher + \Joomla\CMS\Language\Text::script('MOD_EXAMPLE_LOADING'); + + $data['items'] = $this->getHelperFactory() + ->getHelper('ExampleHelper') + ->getItems($data['params'], $this->getApplication()); + + return $data; +} +``` + +The asset names (`mod_example.style`, `mod_example.script`) come from the module's `media/joomla.asset.json`; Joomla auto-resolves the URI to `media/mod_example/css/style.css` and `media/mod_example/js/script.js`. See `references/gotchas.md` § "WAM URI Auto-Resolution" for the path-resolution rules and the `media/vendor/...` exception for non-standard asset paths. + +`Text::script()` registration must happen here, before the template loads — otherwise `Joomla.Text._('MOD_EXAMPLE_LOADING')` returns the raw key. See `references/gotchas.md` for the truthy-key trap. + --- ## Helper Class @@ -263,6 +315,27 @@ if (empty($items)) { --- +## Caching + +Joomla caches module output between requests when the **module instance** has caching enabled (admin → Modules → your module → `Advanced` → `Caching` = `Use global` or `Yes`). The cache is keyed per module instance plus a per-module **cache id** that the dispatcher's flow doesn't override unless you ask it to. + +For most modules the default keying is fine: same params + same user + same page = same cached output. Two cases you have to handle yourself: + +- **Output that depends on the URL beyond `Itemid`** (e.g., the current article's id): pass a custom modifier through the `cache_id` channel, or set `cache_lifetime` to `0` if the output truly can't be cached safely. +- **Output that depends on session state** (per-user data, recently-viewed lists): set the manifest's `` so the user can disable caching, and document that Use global / Yes will produce stale data for them. + +There is no current public hook to customize the cache key from the dispatcher; for instance-level cache control, declare the relevant fields in `` and let admins flip the switch. + +--- + +## Install Script (Optional) + +Modules **rarely** need a `` — most ship without one. Add a script only when you need an environment check beyond what Joomla enforces, an asset-directory pre-creation, or any cleanup on uninstall that Joomla won't do automatically (e.g., custom rows your module wrote at runtime). + +When you do need one, the lifecycle hooks (`preflight`, `install`, `update`, `postflight`, `uninstall`) and the class-naming convention (`Mod_InstallerScript`) are **shared with components and plugins**. The full pattern, hook signatures, and example skeletons live in [`references/install-script.md`](install-script.md). + +--- + ## Admin Module For admin-side modules, the structure is identical but: @@ -276,3 +349,14 @@ For admin-side modules, the structure is identical but: - Placed in `administrator/modules/` when installed In practice, larger Joomla projects often ship modules under both `modules/admin/` and `modules/site/` in the same source tree, so the build can package admin and site variants from one repo. + +--- + +## Joomla 6.1 capabilities + +Two module-relevant additions shipped in Joomla 6.1 ([release milestone](https://github.com/joomla/joomla-cms/milestone/148?closed=1), released 2026-04-14): + +- **Versions for Modules** ([PR #46772](https://github.com/joomla/joomla-cms/pull/46772)) — modules now participate in the UCM versioning history (`#__ucm_history`), so admins can see and revert past module-instance configurations the same way they can for articles and categories. Nothing in your module's code needs to change; the capability is plumbed at the core Modules administrator level. Worth knowing because user expectations shift: "where's the version history for this module" is now a reasonable question. +- **`#__extensions.custom_data`** ([PR #46622](https://github.com/joomla/joomla-cms/pull/46622)) — components, menus, modules, and template styles all gained a `custom_data` JSON column on `#__extensions`. Use it for arbitrary per-extension metadata that doesn't belong in `params` (which is user-facing) — e.g., post-install bookkeeping, telemetry opt-ins, or feature flags scoped to a single installed instance. Read/write via `Factory::getContainer()->get('DatabaseDriver')` against the `#__extensions` row keyed by your module's `extension_id`. + +Neither feature changes the patterns in this reference; both are additive. A future revision can add a worked example for `custom_data` if a clear use case emerges.