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

Command icon 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

mably created an issue. See original summary.

mably’s picture

Status: Active » Needs review
mably’s picture

Follow-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()), keep getActiveDomainId() 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.

mably’s picture

Update: 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 new getActiveEditingDomainId(). The edit context also gained getNegotiatedDomainId(), 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.

  • mably committed fa36d6d4 on 3.x
    feat: #3592832 domain_config_ui: decouple the config-editing domain from...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.