function NodeGrantDatabaseStorage::access

Same name and namespace in other branches
  1. 11.x core/modules/node/src/NodeGrantDatabaseStorage.php \Drupal\node\NodeGrantDatabaseStorage::access()
  2. 10 core/modules/node/src/NodeGrantDatabaseStorage.php \Drupal\node\NodeGrantDatabaseStorage::access()
  3. 8.9.x core/modules/node/src/NodeGrantDatabaseStorage.php \Drupal\node\NodeGrantDatabaseStorage::access()

File

core/modules/node/src/NodeGrantDatabaseStorage.php, line 61

Class

NodeGrantDatabaseStorage
Defines a storage handler class that handles the node grants system.

Namespace

Drupal\node

Code

public function access(NodeInterface $node, $operation, AccountInterface $account) {
  // Grants only support these operations.
  if (!in_array($operation, [
    'view',
    'update',
    'delete',
  ])) {
    return AccessResult::neutral();
  }
  // If no module implements the hook or the node does not have an id there is
  // no point in querying the database for access grants.
  if (!$this->moduleHandler
    ->hasImplementations('node_grants') || !$node->id()) {
    // Return the equivalent of the default grant, defined by
    // self::writeDefault().
    if ($operation === 'view') {
      return AccessResult::allowedIf($node->isPublished());
    }
    else {
      return AccessResult::neutral();
    }
  }
  // Check the database for potential access grants.
  $query = $this->database
    ->select('node_access');
  $query->addExpression('1');
  // Only interested for granting in the current operation.
  $query->condition('grant_' . $operation, 1, '>=');
  // Check for grants for this node and the correct langcode.
  $nids = $query->andConditionGroup()
    ->condition('nid', $node->id())
    ->condition('langcode', $node->language()
    ->getId());
  // If the node is published, also take the default grant into account. The
  // default is saved with a node ID of 0.
  $status = $node->isPublished();
  if ($status) {
    $nids = $query->orConditionGroup()
      ->condition($nids)
      ->condition('nid', 0);
  }
  $query->condition($nids);
  $query->range(0, 1);
  $grants = $this->buildGrantsQueryCondition(node_access_grants($operation, $account));
  if (count($grants) > 0) {
    $query->condition($grants);
  }
  // Only the 'view' node grant can currently be cached; the others currently
  // don't have any cacheability metadata. Hopefully, we can add that in the
  // future, which would allow this access check result to be cacheable in all
  // cases. For now, this must remain marked as uncacheable, even when it is
  // theoretically cacheable, because we don't have the necessary metadata to
  // know it for a fact.
  $set_cacheability = function (AccessResult $access_result) use ($operation) {
    $access_result->addCacheContexts([
      'user.node_grants:' . $operation,
    ]);
    if ($operation !== 'view') {
      $access_result->setCacheMaxAge(0);
    }
    return $access_result;
  };
  if ($query->execute()
    ->fetchField()) {
    return $set_cacheability(AccessResult::allowed());
  }
  else {
    return $set_cacheability(AccessResult::neutral());
  }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.