Skip to content

Add $config->ClassName array overlay for module config settings #329

Open
adrianbj wants to merge 2 commits into
processwire:devfrom
adrianbj:feat/config-class-overlay
Open

Add $config->ClassName array overlay for module config settings #329
adrianbj wants to merge 2 commits into
processwire:devfrom
adrianbj:feat/config-class-overlay

Conversation

@adrianbj
Copy link
Copy Markdown
Contributor

Summary

This PR generalises a pattern several existing modules (notably TracyDebugger) already implement locally: overriding module config values from site/config.php via a $config->ClassName array. After this change, the override works for any configurable module without per-module code.

A common use case is reading secrets from $_ENV (.env files via phpdotenv etc.) and feeding them into module config without storing them in the database or in version-controlled files:

// site/config.php
$config->WireMailMailgun = [                                                                                                                                                      
    'apiKey' => $_ENV['MAILGUN_API_KEY'],
    'domain' => $_ENV['MAILGUN_DOMAIN'],                                                                                                                                          
];                                                                                                                                                                                
 
$config->TracyDebugger = [                                                                                                                                                        
    'outputMode' => $_ENV['APP_ENV'] === 'prod' ? 'production' : 'development',                                                                                                 
];

Behavior

Modules::getConfig($class, $property = '') now overlays values from $wire->config->ClassName on top of the stored DB config before returning.

  • Shallow merge of top-level keys (matches the TracyDebugger pattern)
  • getConfig('Foo') returns array_merge($dbData, (array) $config->Foo)
  • getConfig('Foo', 'apiKey') returns the overlay value when present, else DB value
  • DB rows are never mutated by the overlay
  • Internal configData[$id] cache continues to store raw DB data; overlay is applied at read time after cache lookup
  • Non-array $config->ClassName (string, object, missing) → overlay silently ignored
  • Empty array $config->ClassName → no-op

Because ModulesConfigs::setModuleConfigData() already routes through getConfig() when no $data argument is provided, module instance properties applied at init time automatically pick up the overlay too — no separate change needed for that path.

Admin UI indicator

To avoid confusion when an override is active, getModuleConfigInputfields() now decorates the module config form:

  • Fields whose names match a key in $config->ClassName get a notes line appended ("Currently overridden by ...") so admins know edits won't take effect at runtime.
  • A single InputfieldMarkup summary is prepended to the form listing the overridden keys.
  • Override values are never rendered (secret-safe). Inputs stay editable so the stored DB value remains useful as a fallback when the override is removed.

Backward compatibility

Purely additive. Modules that don't have $config->ClassName set behave identically. Modules that already implement their own internal overlay (TracyDebugger) continue to work —
the merge is idempotent for them.

Files changed

  • wire/core/Modules/ModulesConfigs.phpgetConfig() implementation, PHPDoc, and admin UI indicator in getModuleConfigInputfields()
  • wire/core/Modules/Modules.php — PHPDoc on the wrapper

adrianbj added 2 commits May 17, 2026 15:03
When $wire->config->ClassName is set to an array in site/config.php, its
top-level keys are now overlaid on top of the stored DB config returned
from Modules::getConfig(). This generalises the per-module pattern
pioneered by TracyDebugger so any configurable module can have its
settings overridden (e.g. from $_ENV) without per-module code.

- Shallow merge; non-array overlays are ignored
- DB rows are never mutated by the overlay
- Internal configData cache continues to hold raw DB data; overlay is
  applied at read time after cache lookup
- Module instance properties pick up the overlay automatically because
  setModuleConfigData() already routes through getConfig()
When rendering a module's config form, fields whose names match a key
in $wire->config->ClassName get a "Currently overridden by ..." note
appended below the input, and a single summary InputfieldMarkup is
prepended to the form listing all overridden keys.

- Override values are intentionally NOT shown (they often hold secrets);
  only the key names are surfaced.
- Inputs remain editable so admins can still update the stored DB value
  as a fallback for when the override is removed.
- Indicator runs after the numVisible/flagsNoUserConfig calculation so
  the prepended markup doesn't skew that count.
@adrianbj adrianbj changed the base branch from master to dev May 17, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant