CommentAccessControlHandler.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. namespace Drupal\comment;
  3. use Drupal\Core\Access\AccessResult;
  4. use Drupal\Core\Entity\EntityAccessControlHandler;
  5. use Drupal\Core\Entity\EntityInterface;
  6. use Drupal\Core\Field\FieldDefinitionInterface;
  7. use Drupal\Core\Field\FieldItemListInterface;
  8. use Drupal\Core\Session\AccountInterface;
  9. /**
  10. * Defines the access control handler for the comment entity type.
  11. *
  12. * @see \Drupal\comment\Entity\Comment
  13. */
  14. class CommentAccessControlHandler extends EntityAccessControlHandler {
  15. /**
  16. * {@inheritdoc}
  17. */
  18. protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
  19. /** @var \Drupal\comment\CommentInterface|\Drupal\user\EntityOwnerInterface $entity */
  20. $comment_admin = $account->hasPermission('administer comments');
  21. if ($operation == 'approve') {
  22. return AccessResult::allowedIf($comment_admin && !$entity->isPublished())
  23. ->cachePerPermissions()
  24. ->addCacheableDependency($entity);
  25. }
  26. if ($comment_admin) {
  27. $access = AccessResult::allowed()->cachePerPermissions();
  28. return ($operation != 'view') ? $access : $access->andIf($entity->getCommentedEntity()->access($operation, $account, TRUE));
  29. }
  30. switch ($operation) {
  31. case 'view':
  32. $access_result = AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished())->cachePerPermissions()->addCacheableDependency($entity)
  33. ->andIf($entity->getCommentedEntity()->access($operation, $account, TRUE));
  34. if (!$access_result->isAllowed()) {
  35. $access_result->setReason("The 'access comments' permission is required and the comment must be published.");
  36. }
  37. return $access_result;
  38. case 'update':
  39. $access_result = AccessResult::allowedIf($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished() && $account->hasPermission('edit own comments'))
  40. ->cachePerPermissions()->cachePerUser()->addCacheableDependency($entity);
  41. if (!$access_result->isAllowed()) {
  42. $access_result->setReason("The 'edit own comments' permission is required, the user must be the comment author, and the comment must be published.");
  43. }
  44. return $access_result;
  45. default:
  46. // No opinion.
  47. return AccessResult::neutral()->cachePerPermissions();
  48. }
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
  54. return AccessResult::allowedIfHasPermission($account, 'post comments');
  55. }
  56. /**
  57. * {@inheritdoc}
  58. */
  59. protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
  60. if ($operation == 'edit') {
  61. // Only users with the "administer comments" permission can edit
  62. // administrative fields.
  63. $administrative_fields = [
  64. 'uid',
  65. 'status',
  66. 'created',
  67. 'date',
  68. ];
  69. if (in_array($field_definition->getName(), $administrative_fields, TRUE)) {
  70. return AccessResult::allowedIfHasPermission($account, 'administer comments');
  71. }
  72. // No user can change read-only fields.
  73. $read_only_fields = [
  74. 'hostname',
  75. 'changed',
  76. 'cid',
  77. 'thread',
  78. ];
  79. // These fields can be edited during comment creation.
  80. $create_only_fields = [
  81. 'comment_type',
  82. 'uuid',
  83. 'entity_id',
  84. 'entity_type',
  85. 'field_name',
  86. 'pid',
  87. ];
  88. if ($items && ($entity = $items->getEntity()) && $entity->isNew() && in_array($field_definition->getName(), $create_only_fields, TRUE)) {
  89. // We are creating a new comment, user can edit create only fields.
  90. return AccessResult::allowedIfHasPermission($account, 'post comments')->addCacheableDependency($entity);
  91. }
  92. // We are editing an existing comment - create only fields are now read
  93. // only.
  94. $read_only_fields = array_merge($read_only_fields, $create_only_fields);
  95. if (in_array($field_definition->getName(), $read_only_fields, TRUE)) {
  96. return AccessResult::forbidden();
  97. }
  98. // If the field is configured to accept anonymous contact details - admins
  99. // can edit name, homepage and mail. Anonymous users can also fill in the
  100. // fields on comment creation.
  101. if (in_array($field_definition->getName(), ['name', 'mail', 'homepage'], TRUE)) {
  102. if (!$items) {
  103. // We cannot make a decision about access to edit these fields if we
  104. // don't have any items and therefore cannot determine the Comment
  105. // entity. In this case we err on the side of caution and prevent edit
  106. // access.
  107. return AccessResult::forbidden();
  108. }
  109. $is_name = $field_definition->getName() === 'name';
  110. /** @var \Drupal\comment\CommentInterface $entity */
  111. $entity = $items->getEntity();
  112. $commented_entity = $entity->getCommentedEntity();
  113. $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous');
  114. $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments');
  115. $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && ($anonymous_contact != CommentInterface::ANONYMOUS_MAYNOT_CONTACT || $is_name) && $account->hasPermission('post comments'))
  116. ->cachePerPermissions()
  117. ->addCacheableDependency($entity)
  118. ->addCacheableDependency($field_definition->getConfig($commented_entity->bundle()))
  119. ->addCacheableDependency($commented_entity);
  120. return $admin_access->orIf($anonymous_access);
  121. }
  122. }
  123. if ($operation == 'view') {
  124. // Nobody has access to the hostname.
  125. if ($field_definition->getName() == 'hostname') {
  126. return AccessResult::forbidden();
  127. }
  128. // The mail field is hidden from non-admins.
  129. if ($field_definition->getName() == 'mail') {
  130. return AccessResult::allowedIfHasPermission($account, 'administer comments');
  131. }
  132. }
  133. return parent::checkFieldAccess($operation, $field_definition, $account, $items);
  134. }
  135. }