_node_query_node_access_alter

  1. drupal
    1. 7
Versions
7 _node_query_node_access_alter($query, $base_table, $type)

Helper for node access functions.

Parameters

$query The query to add conditions to.

$base_table The table holding node ids.

$type Either 'node' or 'entity' depending on what sort of query it is. See node_query_node_access_alter() and node_query_entity_field_access_alter() for more.

Related topics

Code

drupal/modules/node/node.module, line 3144

<?php
function _node_query_node_access_alter($query, $base_table, $type) {
  global $user;

  // Read meta-data from query, if provided.
  if (!$account = $query->getMetaData('account')) {
    $account = $user;
  }
  if (!$op = $query->getMetaData('op')) {
    $op = 'view';
  }

  // If $account can bypass node access, or there are no node access modules,
  // or the operation is 'view' and the $acount has a global view grant (i.e.,
  // a view grant for node ID 0), we don't need to alter the query.
  if (user_access('bypass node access', $account)) {
    return;
  }
  if (!count(module_implements('node_grants'))) {
    return;
  }
  if ($op == 'view' && node_access_view_all_nodes($account)) {
    return;
  }

  // Prevent duplicate records.
  $query->distinct();

  // Find all instances of the {node} table being joined -- could appear
  // more than once in the query, and could be aliased. Join each one to
  // the node_access table.

  $tables = $query->getTables();
  $grants = node_access_grants($op, $account);
  if ($type == 'entity') {
    // The original query looked something like:
    // @code
    //  SELECT nid FROM sometable s
    //  INNER JOIN node_access na ON na.nid = s.nid
    //  WHERE ($node_access_conditions)
    // @endcode
    //
    // Our query will look like:
    // @code
    //  SELECT entity_type, entity_id
    //  FROM field_data_something s
    //  LEFT JOIN node_access na ON s.entity_id = na.nid
    //  WHERE (entity_type = 'node' AND $node_access_conditions) OR (entity_type <> 'node')
    // @endcode
    //
    // So instead of directly adding to the query object, we need to collect
    // in a separate db_and() object and then at the end add it to the query.
    $entity_conditions = db_and();
  }
  foreach ($tables as $nalias => $tableinfo) {
    $table = $tableinfo['table'];
    if (!($table instanceof SelectQueryInterface) && $table == $base_table) {

      // The node_access table has the access grants for any given node so JOIN
      // it to the table containing the nid which can be either the node
      // table or a field value table.
      if ($type == 'node') {
        $access_alias = $query->join('node_access', 'na', '%alias.nid = ' . $nalias . '.nid');
      }
      else {
        $access_alias = $query->leftJoin('node_access', 'na', '%alias.nid = ' . $nalias . '.entity_id');
        $base_alias = $nalias;
      }

      $grant_conditions = db_or();
      // If any grant exists for the specified user, then user has access
      // to the node for the specified operation.
      foreach ($grants as $realm => $gids) {
        foreach ($gids as $gid) {
          $grant_conditions->condition(db_and()
            ->condition($access_alias . '.gid', $gid)
            ->condition($access_alias . '.realm', $realm)
          );
        }
      }

      $count = count($grant_conditions->conditions());
      if ($type == 'node') {
        if ($count) {
          $query->condition($grant_conditions);
        }
        $query->condition($access_alias . '.grant_' . $op, 1, '>=');
      }
      else {
        if ($count) {
          $entity_conditions->condition($grant_conditions);
        }
        $entity_conditions->condition($access_alias . '.grant_' . $op, 1, '>=');
      }
    }
  }

  if ($type == 'entity' && count($entity_conditions->conditions())) {
    // All the node access conditions are only for field values belonging to
    // nodes.
    $entity_conditions->condition("$base_alias.entity_type", 'node');
    $or = db_or();
    $or->condition($entity_conditions);
    // If the field value belongs to a non-node entity type then this function
    // does not do anything with it.
    $or->condition("$base_alias.entity_type", 'node', '<>');
    // Add the compiled set of rules to the query.
    $query->condition($or);
  }
}
?>