You are here

node_access_example.module in Examples for Developers 6

Same filename and directory in other branches
  1. 7 node_access_example/node_access_example.module

This is an example illustrating how to restrict access to nodes based on some criterion associated with the user.

This example module will simply set a single flag on a node: 'private'. If the flag is set, only users with the 'view private content' flag can see the node, and all users with 'edit private content' can edit (but not delete) the node.

Additionally we will ensure that the node author can always view, edit, and delete the node by providing an additional access realm that grants privileges to the node's author.

Database definition:


  CREATE TABLE node_access_example (
    nid int(10) unsigned NOT NULL default '0' PRIMARY KEY,
    private int,
    KEY `node_example_nid` (nid)
  )

File

node_access_example/node_access_example.module
View source
<?php

/**
 * @file
 *
 * This is an example illustrating how to restrict access to nodes based
 * on some criterion associated with the user.
 *
 * This example module will simply set a single flag on a node:
 * 'private'. If the flag is set, only users with the 'view private
 * content' flag can see the node, and all users with 'edit private
 * content' can edit (but not delete) the node.
 *
 * Additionally we will ensure that the node author can always view,
 * edit, and delete the node by providing an additional access realm that
 * grants privileges to the node's author.
 *
 * Database definition:
 * @code
 *   CREATE TABLE node_access_example (
 *     nid int(10) unsigned NOT NULL default '0' PRIMARY KEY,
 *     private int,
 *     KEY `node_example_nid` (nid)
 *   )
 * @endcode
 */

/**
 * @defgroup node_access_example Example: Node Access
 * @ingroup examples
 * @{
 * Examples of node access restriction. (drupal 6)
 *
 * This is an example illustrating how to restrict access to nodes based
 * on some criterion associated with the user.
 *
 * This example module will simply set a single flag on a node:
 * 'private'. If the flag is set, only users with the 'view private
 * content' flag can see the node, and all users with 'edit private
 * content' can edit (but not delete) the node.
 *
 * Additionally we will ensure that the node author can always view,
 * edit, and delete the node by providing an additional access realm that
 * grants privileges to the node's author.
 *
 * Database definition:
 * @code
 *   CREATE TABLE node_access_example (
 *     nid int(10) unsigned NOT NULL default '0' PRIMARY KEY,
 *     private int,
 *     KEY `node_example_nid` (nid)
 *   )
 * @endcode
 *
 * This example is part of the Examples for Developers Project which you can download
 * and experiment with here: http://drupal.org/project/examples
 */

/**
 * Implementation of hook_perm().
 *
 * In this example, we will use a simple permission to determine whether a user
 * has access to "private" content. This permission is defined here.
 */
function node_access_example_perm() {
  return array(
    'access private content',
    'edit private content',
  );
}

/**
 * Here we define a constant for our node access grant ID, for the example realm.
 * This ID could be any integer, but here we choose 23,
 * because it is this author's favorite number.
 */
define('NODE_ACCESS_EXAMPLE_GRANT_ALL', 23);

/**
 * Implements hook_node_grants().
 *
 * Tell the node access system what grant IDs the user belongs to for
 * each realm, based on the operation being performed.
 *
 * When the user tries to perform an operation on the node, Drupal calls
 * hook_node_grants() to determine grant ID and realm for the user.
 * Drupal looks up the grant ID and realm for the node, and compares them
 * to the grant ID and realm provided here. If grant ID and realm match
 * for both user and node, then the operation is allowed.
 *
 * Grant ID and realm are both determined per node, by your module in
 * hook_node_access_records().
 *
 * In our example, we've created three access realms: One for authorship,
 * and two that track with the permission system.
 *
 * We always add node_access_example_author to the list of grants, with a
 * grant ID equal to their user ID. We do this because in our model,
 * authorship always gives you permission to edit or delete your nodes,
 * even if they're marked private.
 *
 * Then we compare the user's permissions to the operation to determine
 * whether the user falls into the other two realms:
 * node_access_example_view, and/or node_access_example_edit. If the user
 * has the 'access any private content' permission we defined in
 * hook_permission(), they're declared as belonging to the
 * node_access_example_realm. Similarly, if they have the 'edit any
 * private content' permission, we add the node_access_example_edit realm
 * to the list of grants they have.
 *
 * @see node_access_example_perm()
 * @see node_access_example_node_access_records()
 */
function node_access_example_node_grants($account, $op) {
  if ($op == 'view' && user_access('access private content', $account)) {
    $grants['node_access_example'] = array(
      NODE_ACCESS_EXAMPLE_GRANT_ALL,
    );
  }
  if (($op == 'update' || $op == 'delete') && user_access('edit private content', $account)) {
    $grants['node_access_example'] = array(
      NODE_ACCESS_EXAMPLE_GRANT_ALL,
    );
  }
  $grants['node_access_example_author'] = array(
    $account->uid,
  );
  return $grants;
}

/**
 * Implements hook_node_access_records().
 *
 * All node access modules must implement this hook. If the module is
 * interested in the privacy of the node passed in, return a list of node
 * access values for each grant ID we offer.
 *
 * In this example, for each node which is marked private, we define two
 * realms:
 *
 * The first realm is 'node_access_example' which have a single grant ID.
 * The user is either a member of these realms or not, depending upon the
 * operation and the access permission set.
 *
 * The second is 'node_access_example_author.' It gives the node author
 * special privileges. 'node_access_example_author' has one grant ID for
 * every UID, and each user is automatically a member of the group where
 * GID == UID. This has the effect of giving each user their own grant ID
 * for nodes they authored, within this realm.
 *
 * Drupal calls this hook when a node is saved, or when access
 * permissions change in order to rebuild the node access database
 * table(s).
 *
 * The array you return will define the realm and the grant ID for the
 * given node. This is stored in the {node_access} table for subsequent
 * comparison against the user's realm and grant IDs, which you'll supply
 * in hook_node_grants().
 *
 * Realm names and grant IDs are arbitrary. Official drupal naming
 * conventions do not cover access realms, but since all realms are
 * stored in the same database table, it's probably a good idea to use
 * descriptive names which follow the module name, such as
 * 'mymodule_realmname'.
 *
 * @see node_access_example_node_grants()
 */
function node_access_example_node_access_records($node) {

  // We only care about the node if it's been marked private. If not, it is
  // treated just like any other node and we completely ignore it.
  if (!empty($node->private)) {
    $grants = array();
    $grants[] = array(
      'realm' => 'node_access_example',
      'gid' => NODE_ACCESS_EXAMPLE_GRANT_ALL,
      'grant_view' => TRUE,
      'grant_update' => FALSE,
      'grant_delete' => FALSE,
      'priority' => 0,
    );

    // For the example_author array, the GID is equivalent to a UID, which
    // means there are many many groups of just 1 user.
    $grants[] = array(
      'realm' => 'node_access_example_author',
      'gid' => $node->uid,
      'grant_view' => TRUE,
      'grant_update' => TRUE,
      'grant_delete' => TRUE,
      'priority' => 0,
    );
    return $grants;
  }
}

/**
 * Implementation of hook_form_alter()
 *
 * This module adds a simple checkbox to the node form labeled
 * private. If the checkbox is labelled, only the node author and
 * users with 'access private content' privileges may see it.
 */
function node_access_example_form_alter(&$form, $form_state) {
  if ($form['#id'] == 'node-form') {
    $form['private'] = array(
      '#type' => 'checkbox',
      '#title' => t('Private'),
      '#description' => t('Check here if this content should be set private and only shown to privileged users.'),
      '#default_value' => isset($form['#node']->private) ? $form['#node']->private : FALSE,
    );
  }
}

/**
 * Implementation of hook_nodeapi().
 *
 * The module must track the access status of the node.
 */
function node_access_example_nodeapi(&$node, $op, $arg = 0) {
  switch ($op) {
    case 'load':
      $node->private = db_result(db_query('SELECT private FROM {node_access_example} WHERE nid = %d', $node->nid));
      break;
    case 'insert':
      db_query('INSERT INTO {node_access_example} (nid, private) VALUES (%d, %d)', $node->nid, $node->private);
      break;
    case 'update':
      db_query('UPDATE {node_access_example} SET private = %d WHERE nid = %d', $node->private, $node->nid);
      break;
    case 'delete':
      db_query('DELETE FROM {node_access_example} WHERE nid = %d', $node->nid);
      break;
  }
}

/**
 * @} End of "defgroup node_access_example".
 */

Functions

Constants

Namesort descending Description
NODE_ACCESS_EXAMPLE_GRANT_ALL Here we define a constant for our node access grant ID, for the example realm. This ID could be any integer, but here we choose 23, because it is this author's favorite number.