You are here

public function EntityAccessControlHandler::fieldAccess in Drupal 8

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php \Drupal\Core\Entity\EntityAccessControlHandler::fieldAccess()
  2. 10 core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php \Drupal\Core\Entity\EntityAccessControlHandler::fieldAccess()

Checks access to an operation on a given entity field.

This method does not determine whether access is granted to the entity itself, only the specific field. Callers are responsible for ensuring that entity access is also respected, for example by using \Drupal\Core\Entity\EntityAccessControlHandlerInterface::access().

Parameters

string $operation: The operation access should be checked for. Usually one of "view" or "edit".

\Drupal\Core\Field\FieldDefinitionInterface $field_definition: The field definition.

\Drupal\Core\Session\AccountInterface $account: (optional) The user session for which to check access, or NULL to check access for the current user. Defaults to NULL.

\Drupal\Core\Field\FieldItemListInterface $items: (optional) The field values for which to check access, or NULL if access is checked for the field definition, without any specific value available. Defaults to NULL.

bool $return_as_object: (optional) Defaults to FALSE.

Return value

bool|\Drupal\Core\Access\AccessResultInterface The access result. Returns a boolean if $return_as_object is FALSE (this is the default) and otherwise an AccessResultInterface object. When a boolean is returned, the result of AccessInterface::isAllowed() is returned, i.e. TRUE means access is explicitly allowed, FALSE means access is either explicitly forbidden or "no opinion".

Overrides EntityAccessControlHandlerInterface::fieldAccess

See also

\Drupal\Core\Entity\EntityAccessControlHandlerInterface::access()

File

core/lib/Drupal/Core/Entity/EntityAccessControlHandler.php, line 312

Class

EntityAccessControlHandler
Defines a default implementation for entity access control handler.

Namespace

Drupal\Core\Entity

Code

public function fieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account = NULL, FieldItemListInterface $items = NULL, $return_as_object = FALSE) {
  $account = $this
    ->prepareUser($account);

  // Get the default access restriction that lives within this field.
  $default = $items ? $items
    ->defaultAccess($operation, $account) : AccessResult::allowed();

  // Explicitly disallow changing the entity ID and entity UUID.
  $entity = $items ? $items
    ->getEntity() : NULL;
  if ($operation === 'edit' && $entity) {
    if ($field_definition
      ->getName() === $this->entityType
      ->getKey('id')) {

      // String IDs can be set when creating the entity.
      if (!($entity
        ->isNew() && $field_definition
        ->getType() === 'string')) {
        return $return_as_object ? AccessResult::forbidden('The entity ID cannot be changed.')
          ->addCacheableDependency($entity) : FALSE;
      }
    }
    elseif ($field_definition
      ->getName() === $this->entityType
      ->getKey('uuid')) {

      // UUIDs can be set when creating an entity.
      if (!$entity
        ->isNew()) {
        return $return_as_object ? AccessResult::forbidden('The entity UUID cannot be changed.')
          ->addCacheableDependency($entity) : FALSE;
      }
    }
  }

  // Get the default access restriction as specified by the access control
  // handler.
  $entity_default = $this
    ->checkFieldAccess($operation, $field_definition, $account, $items);

  // Combine default access, denying access wins.
  $default = $default
    ->andIf($entity_default);

  // Invoke hook and collect grants/denies for field access from other
  // modules. Our default access flag is masked under the ':default' key.
  $grants = [
    ':default' => $default,
  ];
  $hook_implementations = $this
    ->moduleHandler()
    ->getImplementations('entity_field_access');
  foreach ($hook_implementations as $module) {
    $grants = array_merge($grants, [
      $module => $this
        ->moduleHandler()
        ->invoke($module, 'entity_field_access', [
        $operation,
        $field_definition,
        $account,
        $items,
      ]),
    ]);
  }

  // Also allow modules to alter the returned grants/denies.
  $context = [
    'operation' => $operation,
    'field_definition' => $field_definition,
    'items' => $items,
    'account' => $account,
  ];
  $this
    ->moduleHandler()
    ->alter('entity_field_access', $grants, $context);
  $result = $this
    ->processAccessHookResults($grants);
  return $return_as_object ? $result : $result
    ->isAllowed();
}