5

I have

Content types:

  • front_banner
  • news

Entity Queues:

  • front_banner -> only ever contains one front_banner node
  • news -> contains multiple news nodes

Views:

  • front_banner -> displays rendered nodes (default)
  • news -> displays rendered nodes (teaser)

The front banner content type has a field in it that determines whether the text colour should be light or dark when display (sets a class in the twig template, works fine). The news content type also makes use of the front_banner's overlay style field like so:

function mymodule_preprocess_node(array &$vars) {
  if ($vars['node']->bundle() == 'news'){

    // Set the overlay class (dark/light).
    $entity_subqueue = \Drupal::entityManager()->getStorage('entity_subqueue')->load('front_banner');
    $items = $entity_subqueue->get('items')->getValue();
    $front_node = node_load($items[0]['target_id']);
    $vars['overlay_class'] = $front_node->get('field_overlay_style')->getString();
  }
}

All of this works perfectly well, my problem occurs when I alter the front_banner node or entityqueue: the cache is obviously not set to refresh for news items when that occurs.

1. Which render cache do I need to rebuild?

Is it the view cache? or the node's render cache? or both?

2. How can I do it?

I have tried creating my own cache tag and flushing it like so:

function mymodule_entity_presave(EntityInterface $entity) {
  $tags = ['entity_type:' . $entity->getEntityTypeId() . '.' . $entity->bundle()];
  Cache::invalidateTags($tags);
}

function mymodule_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
  if ($build['#node']->bundle() == 'news'){
    //dpm($build);
    $tags=['entity_type:node.front_page_banner', 'entity_subqueue:front_banner'];
    $build['#node']->addCacheTags($tags);
  }
}

(entity_subqueue:front_banner tag is provided by the entityqueue module)

I cannot get the news node page itself to change the overlay style, nor can I get the view that displays news nodes to change the overlay style when the front_banner node is saved.


[Edit 1:] I looked into Views Custom Cache Tags - this does allow me to state which tags I want to affect the views cache - I tried putting the two relevant tags in my view to no effect. Perhaps this means it's the node cache that is giving me grief?

  • You can give a try to Views Custom Cache Tags module. The module allows to add custom tags to views which can be invalidated programatically during hook_node_presave() as per mentioned on project page. – Yogesh Nov 8 '16 at 4:55
  • Thanks for the tip, I should have included that attempt in my question, edited. – Darvanen Nov 8 '16 at 5:24
  • You can disable the content type cache ie news content type cache programatically as well you can disable views cache of news from views UI – Shreya Shetty Nov 10 '16 at 5:38
  • You are using a different (set of) tags in invalidateTags then you attached to your view. Guess that's your mistake. – Clemens Tolboom Nov 10 '16 at 16:44
  • I can assure you that 'entity_type:' . $entity->getEntityTypeId() . '.' . $entity->bundle() renders down to entity_type:node.front_page_banner, and that entity_subqueue:front_banner is provided by the entityqueue module. Can you elaborate if I'm missing something else? – Darvanen Nov 10 '16 at 22:05
4
+200

Every view that lists nodes is tagged with node_list and will be invalidated when a node is added, changed or deleted, so you don't need to worry about adding your nodes to the view.

But you do need to add the entity_subqueue tag to your view's cache tags, and you need to add the entity_subqueue tag and banner content type to your news content type's build array. I haven't tested the way you're adding it, but I know you can add cache tags to a node in hook_entity_view:

  function mymodule_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {

      if ($entity->bundle() == 'news') {

        $tags = ['entity_type:node.front_page_banner', 'entity_subqueue:front_banner'];
        $build['#cache']['tags'] = array_merge($build['#cache']['tags'], $tags);

      }
    }

I know this is similar to what you were doing, but need to add it to the build array, not the node object.

Then you need to add the entity queue to the build array of your view

function mymodule_views_pre_view(ViewExecutable $view, $display_id, array &$args) {

  if ($view->id() == 'news' || $view->id() == 'front_banner') {
    $view->element['#cache']['tags'][] = 'entity_subqueue:front_banner';
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.