{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiaktlgvlfuqll27zt3tradmybzegwxccimk4zow3s2gjfwhdmznme",
    "uri": "at://did:plc:ql5nzcyoitey44ceaysoz6ez/app.bsky.feed.post/3mijbfa54dhs2"
  },
  "description": "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.\n\nBut 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.\n\nAnyway to change Drupal’s behavior, I need to delve into both into entity access. Unfortunately I cannot solve...",
  "path": "/app.bsky.feed.post/3mijbfa54dhs2",
  "publishedAt": "2026-04-02T12:37:46.000Z",
  "site": "at://did:plc:ql5nzcyoitey44ceaysoz6ez",
  "tags": [
    "drupal"
  ],
  "textContent": "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.\n\nBut 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.\n\nAnyway 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.\n\nOne thing to remember that is really important is to remember caching. And Drupal makes this simple.\n\n\n      /*** 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();}}}}\n\nAnd 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.\n\nThis is not live yet, but when I have more free time I will push and deploy it.",
  "title": "Improving external comment privacy without relying on unpubished comments",
  "updatedAt": "2026-04-02T13:26:08.000Z"
}