You are here

public function NodeGrantDatabaseStorage::access in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/node/src/NodeGrantDatabaseStorage.php \Drupal\node\NodeGrantDatabaseStorage::access()
  2. 9 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());
  }
}