Module can pollute the render cache when used with a field item that has cache ids set

Created on 24 May 2023, over 1 year ago
Updated 24 October 2023, about 1 year ago

Problem/Motivation

When used with a field formatter where each field item has a cache key set (such as on an entity reference field with the rendered entity formatter) the suffix is appended to this item which can put incorrect markup into the render cache for the field item value.

Reporting as a new issue - even though I suspect https://www.drupal.org/project/field_delimiter/issues/3321484 is a result of this issue - there is not enough details in that issue to be sure this is a duplicate.

Steps to reproduce

Using this module with standard install profile

  • On article default display - configure the tags field to use Rendered entity, use default view mode and add a delimiter
  • On article teaser display - configure the tags field to use Rendered entity, use default view mode and add a different delimiter than above
  • Add an article with more that 1 tag.
  • View the article in the full view mode
  • View the article in the teaser view mode

Observe that the field is rendered on the teaser view mode with the settings from the default view mode.

This is because the field item will have cache keys set - e.g

["entity_view", "taxonomy_term", "1", "default"]

And the preprocess function is adding #suffix to that render array - so if it is the first time being rendered it will include the suffix as part of the rendered HTML for that entity (the referenced taxonomy term).

This is not correct behaviour. When rendered elsewhere, this information which should be related only to field / view mode of the host entity is now part of the render cache for the entity being referenced.

Likewise, if the taxonomy term has been first rendered elsewhere using the same view mode but outside the context of a field with a delimiter, it will cache the correct markup, but when the node / field with the delimiter set is rendered it is using the cached markup and will not render the prefix added by this module.

Proposed resolution

I initially thought of adding a representation of the delimiter as the final part of the cache key - but this would reduce the cacheability of rendered entities - and require work to ensure we are using something that can safely be used as keys (e.g the delimiter can contain HTML so I wasn't immediately sure of supported characters for cache keys).

So perhaps a simpler alternative is to use a nested render array instead of a suffix. Given the delimiter is already sanitized it could so something like:

$content_with_suffix = [
  $item['content'],
  ['#markup' => $safe_delimiter],
];
$item['content'] = $content_with_suffix;

This would keep the cache benefits of using the rendered entity cache and allow the module to insert the delimiter in the same position.

Remaining tasks

  1. Agree on approach
  2. Patch
  3. Review
  4. Commit

User interface changes

n/a

API changes

n/a

Data model changes

Proposed approach would change modify the field item content render array to be a nested array contain the original render array and the suffix.

🐛 Bug report
Status

RTBC

Version

2.0

Component

Code

Created by

🇳🇿New Zealand ericgsmith

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @ericgsmith
  • 🇳🇿New Zealand ericgsmith

    Attached is a patch and test with the approach of using a nested render array.

    There are no automated tests setup on this module so these need to be run offline.

  • Status changed to Needs review over 1 year ago
  • Status changed to RTBC over 1 year ago
  • 🇳🇿New Zealand RoSk0 Wellington

    I've followed the steps to reproduce and:
    configured Tags field on the Default display mode to be Rendered entity, Rendered as Default and Delimited by: -|-
    configured Tags field on the Teaser display mode to be Rendered entity, Rendered as Default and Delimited by: ,,
    cleared the caches with drush cr, just in case
    visited /node/1, which is just created article with 3 tags
    and observed - in addition to my -|- delimiter I can see a comma
    exactly same output is visible on the home page, which is teaser view mode

    After applying the patch and clearing the caches default display haven't changed, teaser did however - no it shows three commas!

    So it looks like the patch does fix cache pollution, but the problem of extra comma is still present. Will see if I can find where is that coming from.

    Patch and test looks good.

  • 🇳🇿New Zealand RoSk0 Wellington

    No issues here - that additional comma is hard coded for the tags field in the Olivero theme.

  • This patch is just what we needed. Hope this gets committed soon. Thanks.

  • The patch also applies to 2.0.x

Production build 0.71.5 2024