Excerpt fields are not rendered for anonymous users

Created on 19 April 2021, almost 4 years ago
Updated 21 August 2024, 7 months ago

Problem/Motivation

When using the "Search result excerpt" field in a view mode, the field's content is not rendered for anonymous users.
RenderedItem's $build = $datasource->viewItem($item->getOriginalObject(), $view_mode) is called multiple times by the Highlight Processor. The first time it's called, it returns NULL which gets cached.

Steps to reproduce

  1. Enable the Highlight processor.
  2. Set "Highlight returned field data" to Always.
  3. Enable "Create excerpt".
  4. Add the Search result excerpt field to a view mode (e.g. Teaser).
  5. Create a View, select "Show: Rendered entity" and select the display with the excerpt field.
  6. Index the items, view the results as an anonymous user.

Proposed resolution

Add appropriate cache keys to the render array.

🐛 Bug report
Status

Needs work

Version

1.0

Component

Plugins

Created by

🇬🇧United Kingdom aimai

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States hungdo

    Re-roll the patch file for Drupal 10.2.7, search api 1.3

  • 🇫🇷France dco

    Hi,

    Patch #23 (3209441-23--cache_metadata_search_api_excerpt_field did) didn't solve for me.

    Drupal 10.3.6
    Search Api 8.x-1.35

    The excerpt is visible when logged-in but not for anonymous users

    Probably not a cache problem.

  • 🇫🇷France dco

    Solved

    2 patches are needed, this one (#23) and #12 (read below)

    https://www.drupal.org/project/search_api/issues/3284807#comment-15826249 🐛 Incorrect Search API (tag-based) cached excerpt highlighting for subsequent search with a different term but same result items Needs work

  • 🇦🇹Austria drunken monkey Vienna, Austria

    Thanks a lot for your feedback, this is very valuable information!

    I now combined these two patches into a new MR. Would be good to get some more confirmation from people that this either helps or at least doesn’t make things worse for them.

    My big problem is that I can still not reproduce this, so can’t confirm this is properly working.
    And, in any case, we definitely still need a regression test for this before it can be merged. I don’t think it should be too hard to add this as a new method to our existing \Drupal\Tests\search_api\Kernel\Views\ViewsDisplayCachingTest or \Drupal\Tests\search_api\Functional\ExcerptFieldTest? (I changed the latter to use caching for its view in the hope that this would already let the test fail, but no dice.)
    Would someone be able to work on this?

  • 🇦🇹Austria drunken monkey Vienna, Austria

    Huh, for some reason switching caching for the view to “Search API (tag-based)” breaks the existing test for the “Create excerpt even if no search keys are available” option, no idea why:

  • 🇮🇳India prashant.c Dharamshala

    Faced this issue during the implementation of search autocomplete feature ( https://www.drupal.org/project/search_api_autocomplete ).

    We are also returning the search excerpt in the autocomplete responses, so we found that the excerpt is not being returned for anonymous users. Luckily found this issue and thanks to the patch #23 .

    Applied on our site which is on Drupal 10.3.11 and seems to be working fine so far.

    Thanks

  • 🇺🇸United States raystuart Indianapolis

    Just to help with reproducing this, I needed to _not_ disable the render cache bin in order to see this locally.

    For example, in my settings.local.php file, I had the following all uncommented. If I update as shown below and I do not comment the first, then I am able to reproduce the issue locally.

    /**
     * Uncomment to disable individual cache bins.
     */
    //$settings['cache']['bins']['render'] = 'cache.backend.null';
    $settings['cache']['bins']['page'] = 'cache.backend.null';
    $settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
    

    To be safe while working on this, I probably will not disable any cache bins.

  • 🇦🇹Austria drunken monkey Vienna, Austria

    search_api_entity_view() still had a wonky render array in there, with a superfluous '#markup' key, but should be fine now.
    However, for some reason I cannot figure out the simple act of switching the search_api_test_search_excerpt view to use the search_api_tag cache plugin breaks it, resulting in an empty page (see here). I checked and I can reproduce the fail locally, even without any of the other changes in the MR – it’s really just about using the cache plugin, which shouldn’t even matter since it’s the first view of that page in the test. Not even adding an explicit cache clear to the test helps. Does anyone have any idea what’s going wrong there?

    Also, this still needs a regression test for the actual bug reported.

  • 🇺🇸United States bkosborne New Jersey, USA

    I tested this quite a bit and I can still get the incorrect search results excerpt highlighted. However, I'm using a view that's using a field-based row style (so I have an individual field added to the result row for excerpt) with the "Search API (tag-based)" cache plugin. I can still get results where the excerpt is wrong, highlighting the wrong search term.

    The problem is in getRowId. It hashes the contents of the result item, but the excerpt is not included in the hash because it's a lazy loaded property and hasn't been loaded. It should be included in this scenario.

    I think this can be fixed by detecting if the search_api_excerpt field exists in the view, and if it does, then include the snippet in the row data:

    // Include excerpt in cache ID. It's a lazy loaded property so it won't be included otherwise.
    $row_data['search_api_excerpt'] = $row->search_api_excerpt;
    

    Not really sure on the cleanest approach for doing this detection. I think we need to loop through all the fields in the view and check their plugin and real field matches "search_api_excerpt", and if so, include it in the row data like above.

Production build 0.71.5 2024