You are here

nodetype_access.module in Nodetype access 7

Same filename and directory in other branches
  1. 8 nodetype_access.module

A new, different kind of node access module made possible by Drupal 7.

This module completely bypasses the node access grants system, and instead uses hook_node_access() and hook_query_alter() to prevent users without proper permissions from viewing nodes.

File

nodetype_access.module
View source
<?php

/**
 * @file
 * A new, different kind of node access module made possible by Drupal 7.
 *
 * This module completely bypasses the node access grants system, and instead
 * uses hook_node_access() and hook_query_alter() to prevent users without
 * proper permissions from viewing nodes.
 */

/**
 * Implements hook_permission().
 *
 * Defines a 'view any $type content' permission. I guess I could've had it
 * also define a 'view own $type content' permission, but I'm lazy, and Drupal
 * defaults to letting you view your own content anyway...
 */
function nodetype_access_permission() {
  $perms = array();
  foreach (node_permissions_get_configured_types() as $type) {
    $info = node_type_get_type($type);
    $perms += array(
      nodetype_access_get_permission($type) => array(
        'title' => t('View published %type_name content', array(
          '%type_name' => $info->name,
        )),
      ),
    );
  }
  return $perms;
}

/**
 * Get permission (sanitized) for a single type
 */
function nodetype_access_get_permission($nodetype) {
  $nodetype = check_plain($nodetype);
  return "view any {$nodetype} content";
}

/**
 * Get all permissions (sanitized) keyed by nodetype
 */
function nodetype_access_get_permissions() {
  $permission_keys =& drupal_static(__FUNCTION__);
  if (!isset($permission_keys)) {
    $permission_keys = array();
    foreach (node_type_get_types() as $nodetype => $info) {
      $nodetype = check_plain($nodetype);
      $permission_keys[$nodetype] = nodetype_access_get_permission($nodetype);
    }
  }
  return $permission_keys;
}

/**
 * Implement hook_node_access().
 *
 * This will deny access to nodes accessed via node/X, or otherwise having a
 * full node_load() done on them.
 */
function nodetype_access_node_access($node, $op, $account) {
  if ($op == 'view') {
    if (user_access(nodetype_access_get_permission($node->type), $account)) {
      return NODE_ACCESS_IGNORE;
    }
    else {
      return NODE_ACCESS_DENY;
    }
  }
}

/**
 * Implement hook_query_TAG_alter().
 *
 * This takes care of nodes in listing pages, sidebar blocks, and so on. These
 * do not trigger the full set of hook_node_XXX functions, for performance
 * reasons.
 */
function nodetype_access_query_node_access_alter(QueryAlterableInterface $query) {

  // If we haven't joined on the node table yet, do so.
  $tables = $query
    ->getTables();
  $node_exists = FALSE;
  foreach ($tables as $alias => $table) {
    if ($table['table'] == 'node') {
      $node_exists = TRUE;
      break;
    }
  }

  // $alias is the alias of the node table if $node_exists
  // otherwise it is the index of the last table
  if (!$node_exists) {

    // Assume the primary table has a 'nid' column. Not a safe assumption, but
    // it stops Comment module from freaking out.
    reset($tables);
    $query
      ->join('node', 'n', 'n.nid = ' . key($tables) . '.nid');
    $alias = 'n';
  }

  // Restrict to showing only what types the user has access to view.
  $types = nodetype_access_get_accessible_types();
  if ($types) {

    // only filter if necessary
    if ($types != nodetype_access_get_all_types()) {

      // Escape the alias
      $query
        ->where(db_escape_field($alias) . '.type IN (:types)', array(
        ':types' => $types,
      ));
    }
  }
  else {

    // '1=0' evaluates to a boolean on postgresql as well as on mysql
    // Using just '0' wont work on postgresql, and using 'true' might cause issues
    // on mysql
    $query
      ->where('0=1');
  }
}

/**
 * Returns the list of node types that a user can access.
 */
function nodetype_access_get_accessible_types() {
  global $user;
  $accessible_types =& drupal_static(__FUNCTION__);
  if (!isset($accessible_types)) {

    // Those with 'bypass node access' permissions get to see everything.
    if (user_access('bypass node access')) {
      $accessible_types = array_keys(node_type_get_types());
    }
    else {
      $user_permissions = array_keys(drupal_array_merge_deep_array(user_role_permissions($user->roles)));
      $nodetype_permissions = nodetype_access_get_permissions();
      $accessible_types = array_keys(array_intersect($nodetype_permissions, $user_permissions));
    }
  }
  return $accessible_types;
}

/**
 * Returns the list of all node types.
 */
function nodetype_access_get_all_types() {
  return array_keys(node_type_get_types());
}

Functions

Namesort descending Description
nodetype_access_get_accessible_types Returns the list of node types that a user can access.
nodetype_access_get_all_types Returns the list of all node types.
nodetype_access_get_permission Get permission (sanitized) for a single type
nodetype_access_get_permissions Get all permissions (sanitized) keyed by nodetype
nodetype_access_node_access Implement hook_node_access().
nodetype_access_permission Implements hook_permission().
nodetype_access_query_node_access_alter Implement hook_query_TAG_alter().