CommentAccessControlHandler.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. return AccessResult::allowedIf($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished() && $account->hasPermission('edit own comments'))->cachePerPermissions()->cachePerUser()->addCacheableDependency($entity);
  40. default:
  41. // No opinion.
  42. return AccessResult::neutral()->cachePerPermissions();
  43. }
  44. }
  45. /**
  46. * {@inheritdoc}
  47. */
  48. protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
  49. return AccessResult::allowedIfHasPermission($account, 'post comments');
  50. }
  51. /**
  52. * {@inheritdoc}
  53. */
  54. protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
  55. if ($operation == 'edit') {
  56. // Only users with the "administer comments" permission can edit
  57. // administrative fields.
  58. $administrative_fields = [
  59. 'uid',
  60. 'status',
  61. 'created',
  62. 'date',
  63. ];
  64. if (in_array($field_definition->getName(), $administrative_fields, TRUE)) {
  65. return AccessResult::allowedIfHasPermission($account, 'administer comments');
  66. }
  67. // No user can change read-only fields.
  68. $read_only_fields = [
  69. 'hostname',
  70. 'changed',
  71. 'cid',
  72. 'thread',
  73. ];
  74. // These fields can be edited during comment creation.
  75. $create_only_fields = [
  76. 'comment_type',
  77. 'uuid',
  78. 'entity_id',
  79. 'entity_type',
  80. 'field_name',
  81. 'pid',
  82. ];
  83. if ($items && ($entity = $items->getEntity()) && $entity->isNew() && in_array($field_definition->getName(), $create_only_fields, TRUE)) {
  84. // We are creating a new comment, user can edit create only fields.
  85. return AccessResult::allowedIfHasPermission($account, 'post comments')->addCacheableDependency($entity);
  86. }
  87. // We are editing an existing comment - create only fields are now read
  88. // only.
  89. $read_only_fields = array_merge($read_only_fields, $create_only_fields);
  90. if (in_array($field_definition->getName(), $read_only_fields, TRUE)) {
  91. return AccessResult::forbidden();
  92. }
  93. // If the field is configured to accept anonymous contact details - admins
  94. // can edit name, homepage and mail. Anonymous users can also fill in the
  95. // fields on comment creation.
  96. if (in_array($field_definition->getName(), ['name', 'mail', 'homepage'], TRUE)) {
  97. if (!$items) {
  98. // We cannot make a decision about access to edit these fields if we
  99. // don't have any items and therefore cannot determine the Comment
  100. // entity. In this case we err on the side of caution and prevent edit
  101. // access.
  102. return AccessResult::forbidden();
  103. }
  104. $is_name = $field_definition->getName() === 'name';
  105. /** @var \Drupal\comment\CommentInterface $entity */
  106. $entity = $items->getEntity();
  107. $commented_entity = $entity->getCommentedEntity();
  108. $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous');
  109. $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments');
  110. $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && ($anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT || $is_name) && $account->hasPermission('post comments'))
  111. ->cachePerPermissions()
  112. ->addCacheableDependency($entity)
  113. ->addCacheableDependency($field_definition->getConfig($commented_entity->bundle()))
  114. ->addCacheableDependency($commented_entity);
  115. return $admin_access->orIf($anonymous_access);
  116. }
  117. }
  118. if ($operation == 'view') {
  119. // Nobody has access to the hostname.
  120. if ($field_definition->getName() == 'hostname') {
  121. return AccessResult::forbidden();
  122. }
  123. // The mail field is hidden from non-admins.
  124. if ($field_definition->getName() == 'mail') {
  125. return AccessResult::allowedIfHasPermission($account, 'administer comments');
  126. }
  127. }
  128. return parent::checkFieldAccess($operation, $field_definition, $account, $items);
  129. }
  130. }