Problem/Motivation
BreadcrumbSource::alterComponent() attempts to merge the breadcrumb's cache
metadata into the component element, but the merged result is silently discarded.
CacheableMetadata::merge() returns a new cloned object rather than modifying
the receiver in place, so the original $cache variable is never updated.
The buggy code in src/Plugin/UiPatterns/Source/BreadcrumbSource.php:
$breadcrumbCache = CacheableMetadata::createFromRenderArray($renderable);
$cache = CacheableMetadata::createFromRenderArray($element);
$cache->merge($breadcrumbCache); // returns a new object — result discarded
$cache->applyTo($element); // $cache is still unmerged; breadcrumb contexts never applied
Because the merged clone is discarded, none of the breadcrumb builder's cache contexts
(e.g. url.path, route, or any custom contexts) are propagated
to the component element. The rendered breadcrumb block is therefore cached without the
correct cache contexts, and the first breadcrumb generated for a given block placement is
served for all subsequent requests that share the same insufficient cache key — in
practice, the same wrong breadcrumb appears across unrelated pages.
Steps to reproduce
- Place a UI Patterns breadcrumb block using
source_id: breadcrumb. - Implement a custom
BreadcrumbBuilderInterfacethat adds cache contexts such asurl.path. - Visit two different pages. Both pages will display the breadcrumb generated for the first page loaded, regardless of the current URL.
Proposed resolution
Chain applyTo() on the return value of merge() so the merged
metadata is actually applied to the element:
$breadcrumbCache = CacheableMetadata::createFromRenderArray($renderable);
$cache = CacheableMetadata::createFromRenderArray($element);
$cache->merge($breadcrumbCache)->applyTo($element);
Remaining tasks
Write a test confirming that cache contexts from the breadcrumb builder are present on the rendered component element.
User interface changes
None.
API changes
None.
Data model changes
None.
Comments