Closed (fixed)
Project:
Domain Path
Version:
3.x-dev
Component:
Code
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
23 Feb 2026 at 10:23 UTC
Updated:
12 Mar 2026 at 12:15 UTC
Jump to comment: Most recent
Url objects can now specify the domain as an option, see #3574800: Allow Url objects to specify the Domain as an option
However, the domain path alias is only applied when the URL is generated on the active domain
Apply domain path alias processing on outbound URLs with a domain option
The domain path alias is applied to URLs with a Domain option
To be determined
To be determined
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 #4
mably commentedProblem
When code sets
$url->setOption('domain', 'example_com')directly (without going throughDomainSourcePathProcessor), domain path aliases are not applied. Core'sPathProcessorAlias(priority 300) aliases the path for the active domain, and nobody re-aliases it for the target domain.This is because
domain_pathcurrently resolves aliases only viahook_domain_source_alter, which is fired byDomainSourcePathProcessor(priority 90) — but that processor skips processing when$options['domain']is already set.Solution
New outbound path processor
DomainPathOutboundProcessorat priority 85 (afterDomainSourcePathProcessorat 90, beforeDomainPathProcessorat 80):$options['domain']getAliasByPathAndDomain()The processor is safe for double-processing: when
hook_domain_source_alterhas already replaced the path (domain_source flow), the reverse-resolve typically fails (returns the path unchanged), and the target-domain lookup also returns the same path. Net result: path stays unchanged.Priority chain
PathProcessorAliasDomainSourcePathProcessorhook_domain_source_alterDomainPathOutboundProcessorDomainPathProcessorChanges
src/HttpKernel/DomainPathOutboundProcessor.phpdomain_path.services.yml— registered the new service at priority 85tests/src/Functional/DomainPathDomainOptionTest.php— 3 test methods covering alias resolution, fallback without alias, and non-canonical route exclusionDepends on
#3574800 (domain module:
DomainPathProcessorwith thedomainURL option)Comment #5
idebr commentedPerhaps the following priority chain is preferable?
310 DomainSourcePathProcessor -> sets
$options['domain']if not set before305 DomainPathOutboundProcessor
-> calls
DomainPathAliasManager::getPathByAliasAndDomain()only if$options['domain']is set-> sets
$options['alias'] = TRUEto prevent duplicate processing by PathProcessorAlias since it includes a fallback to the core path alias: https://git.drupalcode.org/project/drupal/-/blob/main/core/modules/path_...hook_domain_source_alteris no longer neededComment #6
idebr commentedDomainPathOutboundProcessor::resolveDomain()is a good example of how allowing both strings and Domain objects in a variable leads to messy code :)Comment #7
mably commentedCurrent architecture (this MR)
AliasPathProcessorDomainPathAliasManager)DomainSourcePathProcessorhook_domain_source_alter, setsoptions['domain']DomainPathOutboundProcessorDomainPathProcessorbase_urlto target domainThe problem: core's
AliasPathProcessor(priority 300) runs first and aliases the path for the active domain. Then our processor at 85 has to undo that (reverse-resolve withgetPathByAlias) and redo it for the target domain. This reverse-then-forward dance works but is wasteful.@idebr proposed architecture
DomainSourcePathProcessoroptions['domain']DomainPathOutboundProcessoroptions['domain']is set, aliases path for target domain, setsoptions['alias'] = TRUEAliasPathProcessor$options['alias']— if TRUE, skips. Otherwise aliases normallyDomainPathProcessorbase_urlto target domainKey insight: by running before core's
AliasPathProcessor(priority 305 > 300), you alias the path for the target domain first. Then you set$options['alias'] = TRUE, which is core's built-in mechanism to tellAliasPathProcessor"aliasing is already done, skip it" (AliasPathProcessor.php line 45). No reverse-resolve needed.Also:
hook_domain_source_alterwould no longer be needed becauseDomainPathOutboundProcessorhandles the aliasing directly —DomainPathFormHooks::domainSourceAlter()was only used to swap the alias for the target domain, which this processor now does.Trade-offs
This approach is cleaner because:
$options['alias']skip mechanismhook_domain_source_alterimplementationConsiderations:
DomainSourcePathProcessormoving from 90 to 310 is a bigger change in the domain module — it needs to work correctly running before core aliasing instead of afterhook_domain_source_alterto modify the alias would breakDomainSourcePathProcessorat 310 would be the internal path (e.g./node/1) rather than an alias, which might actually be simplerI'll rework the implementation to follow this approach — seems like a solid improvement.
Comment #8
mably commented@idebr could you validate this issue please? https://www.drupal.org/project/domain/issues/3575227
Comment #9
idebr commentedI suggest naming the service DomainPathAliasProcessor: the core service is somewhat misnamed missing the 'Alias' part, and Outbound is an implementation detail that easily becomes outdated if the implementation changes
Comment #10
mably commentedService renamed.
Comment #11
mably commentedLooks Domain Path 2.x will now require Domain 3.x.
Don't know what to think about that.
Comment #12
idebr commented#11 An option is to tag 2.0.0 first to allow projects to update, and merge this issue in 2.1.x that requires drupal/domain:^3.0?
Core path alias processing can be skipped entirely if the
$option['domain']is set, since getPathByAliasAndDomain includes a fallback to Core path alias processing, see https://git.drupalcode.org/project/domain_path/-/blob/2.x/src/DomainPath...Comment #13
mably commentedI'll go directly to 3.x to match domain module versioning.
Implemented your suggestion that should definitely improve performance.
Comment #14
mably commentedShould be ready for merge.
Is it ok for you @idebr?
Comment #15
idebr commentedLooks good to me 👍
Comment #17
mably commentedComment #19
mably commentedLooks like our latest changes have introduced some regressions.
Investigating.
Comment #20
mably commented@idebr ok, found the culprit, $options['language'] is not populated anymore after moving DomainSourcePathProcessor at priority 310.
The domain_source field can be translated, so it's currently totally broken.
How could we fix that?
May be we can get the current language by ourselves if not provided in
$options['language'].What do you think?
Comment #21
idebr commentedI think this was fixed in a follow-up in Domain? #3575489: DomainSourcePathProcessor uses wrong translation when $options['language'] is not set (priority 310)