EntityAccessControlHandler.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <?php
  2. namespace Drupal\entity;
  3. use Drupal\Core\Access\AccessResult;
  4. use Drupal\Core\Entity\EntityAccessControlHandler as CoreEntityAccessControlHandler;
  5. use Drupal\Core\Entity\EntityInterface;
  6. use Drupal\Core\Entity\EntityPublishedInterface;
  7. use Drupal\Core\Entity\EntityTypeInterface;
  8. use Drupal\Core\Session\AccountInterface;
  9. use Drupal\user\EntityOwnerInterface;
  10. /**
  11. * Controls access based on the generic entity permissions.
  12. *
  13. * @see \Drupal\entity\UncacheableEntityPermissionProvider
  14. */
  15. class EntityAccessControlHandler extends CoreEntityAccessControlHandler {
  16. /**
  17. * {@inheritdoc}
  18. */
  19. public function __construct(EntityTypeInterface $entity_type) {
  20. parent::__construct($entity_type);
  21. if (!$entity_type->hasHandlerClass('permission_provider') || !is_a($entity_type->getHandlerClass('permission_provider'), EntityPermissionProvider::class, TRUE)) {
  22. throw new \Exception("This entity access control handler requires the entity permissions provider: {EntityPermissionProvider::class}");
  23. }
  24. }
  25. /**
  26. * {@inheritdoc}
  27. */
  28. protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
  29. $account = $this->prepareUser($account);
  30. /** @var \Drupal\Core\Access\AccessResult $result */
  31. $result = parent::checkAccess($entity, $operation, $account);
  32. if ($result->isNeutral()) {
  33. if ($entity instanceof EntityOwnerInterface) {
  34. $result = $this->checkEntityOwnerPermissions($entity, $operation, $account);
  35. }
  36. else {
  37. $result = $this->checkEntityPermissions($entity, $operation, $account);
  38. }
  39. }
  40. // Ensure that access is evaluated again when the entity changes.
  41. return $result->addCacheableDependency($entity);
  42. }
  43. /**
  44. * Checks the entity operation and bundle permissions.
  45. *
  46. * @param \Drupal\Core\Entity\EntityInterface $entity
  47. * The entity for which to check access.
  48. * @param string $operation
  49. * The entity operation. Usually one of 'view', 'view label', 'update' or
  50. * 'delete'.
  51. * @param \Drupal\Core\Session\AccountInterface $account
  52. * The user for which to check access.
  53. *
  54. * @return \Drupal\Core\Access\AccessResultInterface
  55. * The access result.
  56. */
  57. protected function checkEntityPermissions(EntityInterface $entity, $operation, AccountInterface $account) {
  58. if ($operation === 'view') {
  59. $permissions = [
  60. "view {$entity->getEntityTypeId()}"
  61. ];
  62. }
  63. else {
  64. $permissions = [
  65. "$operation {$entity->getEntityTypeId()}",
  66. "$operation {$entity->bundle()} {$entity->getEntityTypeId()}",
  67. ];
  68. }
  69. return AccessResult::allowedIfHasPermissions($account, $permissions, 'OR');
  70. }
  71. /**
  72. * Checks the entity operation and bundle permissions, with owners.
  73. *
  74. * @param \Drupal\Core\Entity\EntityInterface $entity
  75. * The entity for which to check access.
  76. * @param string $operation
  77. * The entity operation. Usually one of 'view', 'view label', 'update' or
  78. * 'delete'.
  79. * @param \Drupal\Core\Session\AccountInterface $account
  80. * The user for which to check access.
  81. *
  82. * @return \Drupal\Core\Access\AccessResultInterface
  83. * The access result.
  84. */
  85. protected function checkEntityOwnerPermissions(EntityInterface $entity, $operation, AccountInterface $account) {
  86. if ($operation === 'view') {
  87. if ($entity instanceof EntityPublishedInterface && !$entity->isPublished()) {
  88. if (($account->id() == $entity->getOwnerId())) {
  89. $permissions = [
  90. "view own unpublished {$entity->getEntityTypeId()}",
  91. ];
  92. return AccessResult::allowedIfHasPermissions($account, $permissions)->cachePerUser();
  93. }
  94. return AccessResult::neutral()->cachePerUser();
  95. }
  96. else {
  97. return AccessResult::allowedIfHasPermissions($account, [
  98. "view {$entity->getEntityTypeId()}",
  99. ]);
  100. }
  101. }
  102. else {
  103. if (($account->id() == $entity->getOwnerId())) {
  104. $result = AccessResult::allowedIfHasPermissions($account, [
  105. "$operation own {$entity->getEntityTypeId()}",
  106. "$operation any {$entity->getEntityTypeId()}",
  107. "$operation own {$entity->bundle()} {$entity->getEntityTypeId()}",
  108. "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}",
  109. ], 'OR');
  110. }
  111. else {
  112. $result = AccessResult::allowedIfHasPermissions($account, [
  113. "$operation any {$entity->getEntityTypeId()}",
  114. "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}",
  115. ], 'OR');
  116. }
  117. return $result;
  118. }
  119. }
  120. /**
  121. * {@inheritdoc}
  122. */
  123. protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
  124. $result = parent::checkCreateAccess($account, $context, $entity_bundle);
  125. if ($result->isNeutral()) {
  126. $permissions = [
  127. 'administer ' . $this->entityTypeId,
  128. 'create ' . $this->entityTypeId,
  129. ];
  130. if ($entity_bundle) {
  131. $permissions[] = 'create ' . $entity_bundle . ' ' . $this->entityTypeId;
  132. }
  133. $result = AccessResult::allowedIfHasPermissions($account, $permissions, 'OR');
  134. }
  135. return $result;
  136. }
  137. }