2

I have threaded comments on a site where there are two roles, reviewers and administrators.

Comments are shown in a view block added to the node (in this case a webform). The view format is set to 'content' and it's using tag based caching.

  • Admins are allowed to see all comments
  • Reviewers can write comments and only seen their own, or replies to them

This is all ok and I've implemented it with hook_ENTITY_TYPE_view_alter (simplified example below).

The problem is caching - the view for one reviewer is being cached and shown when the other logs on.

Scenario:

  • Alice and Bob are reviewers
  • Alice leaves a comment on a node. Logs out.
  • Bob logs on. If the cache hasn't been cleared in the meantime, he'll see Alice's comments even though he shouldn't. (And then, were I then to clear the cache, his view would be correct, but should he logged off and Alice logs back in, she'll now see the view intended for Bob.)

Can I give each user their own cache, or failing that, not cache the view at all? (setting caching of the view block to 'none' doesn't appear to change anything, would be useful to know why in answer.)

function mymodule_comment_view_alter(
    &$build,
    Drupal\Core\Entity\EntityInterface $entity,
    \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display ) {


    // ... some logic that deals with admins (omitted)

    $comment_uid    = $entity->getOwnerId();
    $parent_comment = $entity->getParentComment();

    if ( $comment_uid === $current_user->id() ) {
        // current user's own comment? Show it
    } elseif ( isset( $parent_comment ) &&
               $parent_comment->getOwnerId() == $current_user->id() ) {
        // a comment in  reply to current user's comment? Show it
    } else {
        // otherwise, don't show it
        $build['#access'] = false;
    }

    return;
}
  • I might be oversimplifying, but wouldn't you just need to add a cache context of user? – Clive Sep 18 '18 at 19:39
  • @Clive - you're not :) but I'd never heard that term before, I'll go away and read the API now… – William Turrell Sep 18 '18 at 19:44
  • @Clive - thanks, I understand now. Sorry for not researching more thoroughly before asking. – William Turrell Sep 18 '18 at 20:32
2

As Clive said in the comments, all I needed was the following.
I won't mind if people down vote the question for being too stupid…

// was user.permissions, but that means there will only be a single
// cache shared by all reviewers, and we must cache according to authorship
$build['#cache']['contexts'] = ['user'];

Caveat: the view block cache setting also needs to be 'none'.

Drupal docs - cacheability of render arrays

  • I would've fallen in the same pit, I learned from this :) – No Sssweat Sep 19 '18 at 1:11
  • 2
    This is really a caveat. Disabling Views caching for a comment block will impact performance considerably. Normally Views handles cache contexts correctly, but Views doesn't know about the code you've added to the entity view. So you can try to add a contextual filter for the user so that Views is aware this depends on the current user, even if you don't intend to use this filter because you have your own code. – 4k4 Sep 19 '18 at 7:18

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.