Issue #3618104: Bubble the generated URL cacheability out of the domain source token (3.x backport)

Backport of !433 (merged) to 3.x. Fixes #3618104.

DomainSourceToken::getTokens() ended each replacement with $bubbleable_metadata->merge($generated_url);. BubbleableMetadata::merge() builds $result = parent::merge($other) and returns a new object, leaving the one it was called on untouched, so the return value being discarded meant the merge never happened. Everything the generated URL carried was thrown away.

Concretely the absolute URL's url.site cache context never bubbled, so a rendered page containing a domain source token could be cached without varying by host and served across domains.

The fix uses the in-place call, matching core's own token hooks (SystemTokensHooks uses this shape three times, for url, url-brief and login-url):

$bubbleable_metadata->addCacheableDependency($generated_url);

This is not a behaviour reduction versus the intended merge(): BubbleableMetadata overrides addCacheableDependency() to call addAttachments() as well when the argument implements AttachmentsInterface, and GeneratedUrl extends BubbleableMetadata, so cache contexts, cache tags, max-age and attachments all transfer.

Note that satisfying the static analysis by using the return value ($bubbleable_metadata = $bubbleable_metadata->merge(...)) would leave the bug in place, because the caller holds the object being modified.

The kernel test from the 4.x merge request is deliberately not included here. On core 11.3 and earlier a kernel container cannot resolve domain_source.route_provider, which is declared as parent: router.route_provider, so generating an outbound URL through the domain source path processor dies with ArgumentCountError: Too few arguments to function Drupal\Core\Routing\RouteProvider::__construct(), 0 passed and at least 6 expected. Verified by A/B: the same test on the same branch passes on a Drupal 11.4.4 root and fails on a full Drupal 11.3.16 root. Since this branch also runs a previous major (Drupal 10) job that is not allow_failure, the test would go red for a reason unrelated to this change. 4.x requires ^11.4 || ^12, so it always runs where the test works.

The token remains covered end to end on this branch by the functional DomainSourceTokenTest.

Edited by Frank Mably

Merge request reports

Loading
Loading