Improving external comment privacy without relying on unpubished comments

mradcliffe April 2, 2026
Source

Since my blog is public, I had not really considered how I would respond or handle quiet or followers-only replies to my posts. So far I leave these comments as “unpublished”. In my comment administrative view, I have an extra column that checks whether an internal field has been marked private, which happens when I process incoming activities.

But this means that I cannot reply to those posts without exposing them to greater world (i.e. anonymous users). And this makes me feel bad.

Anyway to change Drupal’s behavior, I need to delve into both into entity access. Unfortunately I cannot solve this alone with hook_comment_access because the comments field type does not use that hook when it builds comments attached to a node (or other entity). Easiest way to do that is with template_preprocess_field__comment. I think I can do this also by hooking into entity build/view builder. I took the time to do this using object-oriented hooks instead, which is great because I was able to auto-wire the current_user service into my class.

One thing to remember that is really important is to remember caching. And Drupal makes this simple.

  /*** Implements hook_comment_access().*/#[Hook('comment_access')]public function entityAccess(CommentInterface $entity, string $operation, AccountInterface $account): AccessResultInterface {if ($entity->isPublished() &&$account->isAnonymous() &&$entity->hasField('field_external_id') &&$entity->hasField('field_private')) {return AccessResult::forbiddenIf($entity->get('field_private')->first()->get('value')->getCastedValue())->addCacheContexts(['user.roles:anonymous'])->addCacheableDependency($entity);}return AccessResult::neutral();}/*** Implements hook_preprocess_HOOK() for field templates.*/#[Hook('preprocess_field__comment')]public function preprocessField(&$variables): void {// The comments field does not use entity access hooks to restrict access.// It does use query tags, but the easiest way to alter it is at render.foreach ($variables['comments'] as $key => $build) {if (is_numeric($key)) {if ($build['#comment'] instanceof CommentInterface &&$this->account->isAnonymous() &&$build['#comment']->isPublished() &&$build['#comment']->hasField('field_external_id') &&$build['#comment']->hasField('field_private')) {$variables['comments'][$key]['#cache']['contexts'][] = 'user.roles:anonymous';$variables['comments'][$key]['#access'] = !$build['#comment']->get('field_private')->first()->get('value')->getCastedValue();}}}}

And so with this, I should feel comfortable publishing comments that came in addressed in followers-only or quiet mode. Privately addressing is something I do not support at all still.

This is not live yet, but when I have more free time I will push and deploy it.

Discussion in the ATmosphere

Loading comments...