Problem
domain_config_ui resolves the domain used for configuration form read and write from DomainNegotiationContext (the negotiated, active domain). That same domain also drives routing, language negotiation and path-prefix handling. So a contrib module that wants to let an administrator edit another domain's configuration from a single host cannot simply change the active domain: doing so breaks the current URL (404) on sites using language prefixes or path-prefix domain mode.
Proposal
Introduce a small DomainConfigEditContext service that holds an optional "config-editing domain", restricted to a set of configuration names. DomainConfigFactory and DomainConfigUIManager resolve the editing domain through this context in preference to the negotiated domain, falling back to negotiation when nothing is set. The enable/disable toggler uses the manager's active domain so registration follows the editing domain.
- Name-scoped: only the configuration names a form actually edits are retargeted; everything else keeps using the negotiated domain.
- Backward compatible: with no editing domain set, behaviour is identical to today.
- Negotiation, language and path-prefix handling are never touched, so the current URL keeps working.
Benefit
This is the seam needed by the proposed Domain Configuration Switcher submodule in Domain Extras (domain_extras #3592820), which reintroduces the 2.x "configure any domain from a single host" workflow. With this context the switcher retargets only a form's configuration to the selected domain and leaves the request's real domain in place, so it works on language-prefixed and path-prefix-mode sites.
A merge request will follow.
Issue fork domain-3592832
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mably commentedComment #4
mably commentedFollow-up for the 4.x deprecation cycle: rename
DomainConfigUIManager::getActiveDomainId(), whose contract broadened in this issue from "the negotiated domain" to "the effective config-editing domain" (the editing selection when set, otherwise the negotiated domain).Do it as a proper deprecation, not a rename in place: add the new method (e.g.
getActiveEditingDomainId()), keepgetActiveDomainId()as a @deprecated delegating alias with @trigger_error + a change record and a @group legacy test, and remove it in 4.0.0. The factory's protected getActiveDomainId() / hasActiveDomainId() can just be renamed in 4.x (no ceremony).Naming note: avoid
getEditingDomainId()— it would over-claim, since the method falls back to the negotiated domain when no editing domain is set. Pick a name conveying the effective/active editing target.Comment #5
mably commentedUpdate: implemented in this MR rather than deferred.
getActiveDomainId()is now @deprecated but keeps its original behavior (returns the negotiated domain, unchanged), and the editing-aware resolution lives in the newgetActiveEditingDomainId(). The edit context also gainedgetNegotiatedDomainId(), which the deprecated method delegates to (so no service is injected just to feed dead-end code, and there is no static \Drupal call). All internal callers were repointed to the new method, with a @group legacy test covering the deprecation.Remaining 4.0.0 task: remove the deprecated
getActiveDomainId()(interface + manager) and its @group legacy test.Comment #7
mably commented