Index: node_access_example.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/examples/node_access_example/node_access_example.module,v
retrieving revision 1.6
diff -u -r1.6 node_access_example.module
--- node_access_example/node_access_example.module	28 Jun 2010 20:42:08 -0000	1.6
+++ node_access_example/node_access_example.module	27 Dec 2010 11:20:12 -0000
@@ -3,43 +3,66 @@
 
 /**
  * @file
- * This is an example illustrating how to restrict access to nodes based on
- * the node access system. It implements an additional "private" marker for
- * each node. The idea is that only the user (or specially permissioned users)
- * can access a "private" node.
+ * Module file illustrating API-based node access.
+ */
+
+/**
+ * @defgroup node_access_example Example: Node Access
+ * @ingroup examples
+ * @{
+ * Demonstrates node access.
+ *
+ * This is an example demonstrating how to grant or deny access to nodes using
+ * the Drupal 7 core API node access system.
+ *
+ * This module will add a 'private' flag for each node, which the node's author
+ * can manage. Nodes marked private can only be viewed, edited, or deleted by
+ * the author. However, not everything is as private as it seems on the internet
+ * and so we need to implement some ways to allow other users to manage this
+ * 'private' content.
+ *
+ * We will use the node grant system to specify which users are allowed to view,
+ * edit, or delete 'private' content. We will also allow a user named 'foobar'
+ * to have edit privileges on private content as well.
+ *
+ * In addition, we will provide a page which will show some minimal instructions
+ * and statistics on private nodes on the site.
+ *
+ * We use NodeAPI hooks to put a single marker on a node, called 'private'. The
+ * marker is implemented by a database table which has one row per node simply
+ * indicating that the node is private. If the "private" marker is set, other
+ * users are denied access.
+ *
+ * Standard permissions are defined which allow users with
+ * 'access any private content' or 'edit any private content' to override the
+ * 'private' node access restrictions.
+ *
+ * A separate access realm grants privileges to each node's author, so that
+ * they can always view, edit, and delete their own private nodes.
+ *
+ * The only page provided by this module gives a rundown of how many nodes are
+ * marked private, and how many of those are accessible to the current user.
+ * This demonstrates the use of the 'node_access' tag in node queries,
+ * preventing disclosure of information which should not be shown to users
+ * who don't have the proper permissions.
+ *
+ * Most relevant functions:
+ * - node_access_example_permission()
+ * - node_access_example_node_access()
+ * - node_access_example_node_access_records()
+ * - node_access_example_node_grants()
  *
- * The node access system has three layers.
+ * Drupal's node access system has three layers.
  * - Overall override permissions. User 1 and any user with 'bypass node access'
  *   permission are automatically granted access.
  * - hook_node_access() gives each module the opportunity to approve or deny
  *   access. Any module that returns NODE_ACCESS_DENY from hook_node_access()
  *   will result in denial of access. If no module denies access and one or
- *   more modules allow access, then access is granted.
+ *   more modules allow access, then access is granted. hook_node_access() is
+ *   new for Drupal 7.
  * - If no resolution has yet been reached, then the node_access table is used
- *   along with hook_node_grants().
- *
- * In order to demonstrate hook_node_access() (see
- * node_example_module_node_access()) to deny delete access to users with an
- * even-numbered uid.
- *
- * In addition, the traditional node rights system is employed to specify
- * which users are allowed to view, edit, or delete "private" content.
- *
- * This puts a single marker on a node: 'private'. The marker is implemented
- * by a custom table which has one row per node simply indicating that the node
- * is private. If the "private" marker is set, other users are denied access.
- *
- * Additional standard permissions are defined which allow users with
- * 'access any private content' or 'edit any private content' to override
- * the node access restrictions.
- *
- * Additionally, the node author can always view, edit, and delete the node.
- * A separate access realm grants privileges to each node's author.
- *
- * There are two basic building blocks in the node access system.
- * - hook_node_access_records() provides a list of "grants" for each node.
- * - hook_node_grants() provides determines which of those grants
- *   is available for a given user account.
+ *   along with hook_node_grants(). Drupal updates the node_access table when
+ *   nodes are saved, by calling hook_node_access_records().
  *
  * Note that current best practice is probably to interoperate with the
  * @link http://drupal.org/project/acl ACL module @endlink rather than directly
@@ -48,16 +71,11 @@
  * It's also critical to understand when working with node access rights that
  * normally one would only use one module granting node access. That's the
  * reason that ACL module has come to the fore, as it becomes the central
- * clearing house for granting access. The problem with node acces is that
- * it is a granting system, not a restricting system. As a result, the first
- * module that grants access wins, even though some other node access module
- * might have wanted not to grant access. So there's enormous (potential)
- * ambiguity if one tries to use more than one node access module.
- *
- * The only page provided by this module gives a rundown of how many nodes
- * are marked private, and how many of those are accessible to the current
- * user. This demonstrates the use of the 'node_access' tag in node queries,
- * preventing disclosure of information which should not be shown to a user.
+ * clearing house for granting access. The problem with node acces is that it is
+ * a granting system, not a restricting system. As a result, the first module
+ * that grants access wins, even though some other node access module might have
+ * wanted not to grant access. So there's enormous (potential) ambiguity if one
+ * tries to use more than one node access module.
  *
  * See: @link node_access Node Access Rights @endlink and
  * @link http://drupal.org/node/270000 Handbook page on Node Access module @endlink
@@ -65,7 +83,10 @@
 
 
 /**
- * Implements hook_menu() to provide a description.
+ * Implements hook_menu().
+ *
+ * This path provides a page, with some instructions for the user, and some
+ * statistics about node access changes implemented by this module.
  */
 function node_access_example_menu() {
   $items['examples/node_access'] = array(
@@ -77,8 +98,8 @@
 }
 
 /**
- * Information for the user about what nodes are marked private on the system
- * and which of those the user has access to.
+ * Information page for the user about what nodes are marked private on the
+ * system and which of those the user has access to.
  *
  * The queries showing what is accessible to the current user demonstrate the
  * use of the 'node_access' tag to make sure that we don't show inappropriate
@@ -139,13 +160,17 @@
 /**
  * Implements hook_permission().
  *
- * Users with 'access any private content' have global access to content marked
- * private by other users. 'edit any private content' allows global edit
- * privileges, basically overriding the node access system.
+ * We create two permissions, which we can use as a base for our grant/deny
+ * decision:
+ *
+ * - 'access any private content' allows global access to content marked
+ *   private by other users.
+ * - 'edit any private content' allows global edit privileges, basically
+ *   overriding the node access system.
  *
  * Note that the 'edit any * content' and 'delete any * content' permissions
- * will allow edit or delete permissions to the holder, regardless of what
- * this module does.
+ * will allow edit or delete permissions to the holder, regardless the limits
+ * imposed by this module.
  */
 function node_access_example_permission() {
   return array(
@@ -163,8 +188,11 @@
 /**
  * Implements hook_node_access().
  *
- *  Allows view and edit access to private nodes where the account requesting
- *  access has the username 'foobar'.
+ * Allows view and edit access to private nodes, when the account requesting
+ * access has the username 'foobar'.
+ *
+ * hook_node_access() is new for Drupal 7. This example module uses it to
+ * demonstrate allowing certain privileges to an arbitrary user.
  */
 function node_access_example_node_access($node, $op, $account) {
   // If $node is a string, the node has not yet been created. We don't care
@@ -182,23 +210,37 @@
 /**
  * Implements hook_node_grants().
  *
- * Tell the node access system what grant IDs the account belongs to for each
- * realm.
+ * 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().
+ *
+ * Here we are determining if the user belongs to any of two main categories of
+ * realms:
+ * - The node_access_example_author realm grants the user access to content they
+ *   created. The user's grant ID is their UID.
+ * - The node_access_example_view and node_access_example_edit realms grant
+ *   override access to users with specific traditional permissions, so they can
+ *   edit others' content. Both of these realms have just one grant id, 1.
+ *   The user is either a member or not based on the permissions
+ *   'access any private content' and 'edit any private content.'
  *
- * Here we are providing two realms:
- * - The node_access_example_author realm grants access to a user for their
- *   own content (nodes that they created). The user's grant ID is their UID.
- * - The node_access_example realm grants override access to users with specific
- *   traditional permissions so that they can edit others content. This has just
- *   one grant id, 1: the user is either a member or not based on the
- *   permissions 'access any private content' and 'edit any private content'.
+ * @see node_access_example_permission()
+ * @see node_access_example_node_access_records()
  */
 function node_access_example_node_grants($account, $op) {
   // First grant a grant to the author for own content.
   $grants['node_access_example_author'] = array($account->uid);
 
-  // Then, if "access any private content" is allowed to the account,
-  // grant view, update, or delete as necessary.
+  // Then, if "access any private content" is allowed to the account, grant
+  // view, update, or delete access as necessary.
   if ($op == 'view' && user_access('access any private content', $account)) {
     $grants['node_access_example_view'] = array(1);
   }
@@ -213,11 +255,38 @@
 /**
  * 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. Since this
- * example module only offers 1 grant ID, we will only ever be
- * returning one record.
+ * 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 three
+ * realms:
+ *
+ * The first and second are realms are 'node_access_example_view' and
+ * 'node_access_example_edit,' which have a single grant ID, 1. The user is
+ * either a member of these realms or not, depending upon the operation and the
+ * access permission set.
+ *
+ * The third 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
@@ -241,8 +310,8 @@
       'priority' => 0,
     );
 
-    // For the example_author realm, the GID is equivalent to a UID, which
-    // means there are many many groups of just 1 user.
+    // For the node_access_example_author realm, the grant ID (gid) is
+    // equivalent to the node author's user ID (UID).
     $grants[] = array(
       'realm' => 'node_access_example_author',
       'gid' => $node->uid,
@@ -253,13 +322,14 @@
     );
     return $grants;
   }
+  // Return nothing if the node has not been marked private.
 }
 
 /**
  * Implements 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
+ * checkbox is checked, only the node author and users with
  * 'access any private content' privileges may see it.
  */
 function node_access_example_form_alter(&$form, $form_state) {
@@ -283,8 +353,10 @@
 
 /**
  * Implements hook_node_load().
+ *
+ * Gather and add the private setting for the nodes Drupal is loading.
+ * @see nodeapi_example.module
  */
-
 function node_access_example_node_load($nodes, $types) {
   $result = db_query('SELECT nid, private FROM {node_access_example} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)));
   foreach ($result as $record) {
@@ -296,8 +368,8 @@
  * Implements hook_node_delete().
  *
  * Delete the node_access_example record when the node is deleted.
+ * @see nodeapi_example.module
  */
-
 function node_access_example_node_delete($node) {
   db_delete('node_access_example')->condition('nid', $node->nid)->execute();
 }
@@ -306,6 +378,7 @@
  * Implements hook_node_insert().
  *
  * Insert a new access record when a node is created.
+ * @see nodeapi_example.module
  */
 function node_access_example_node_insert($node) {
   if (isset($node->private)) {
@@ -315,10 +388,11 @@
 }
 
 /**
- * Implements hook_nodeapi_update().
+ * Implements hook_node_update().
  *
- * If the record in the node_access_example table already exists, we must
- * update it. If it doesn't exist, we create it.
+ * If the record in the node_access_example table already exists, we must update
+ * it. If it doesn't exist, we create it.
+ * @see nodeapi_example.module
  */
 function node_access_example_node_update($node) {
   // Find out if there is already a node_access_example record.
@@ -341,3 +415,7 @@
     drupal_set_message(t('Inserted new node_access nid=@nid, private=@private', array('@nid' => $node->nid, '@private' => $node->private)));
   }
 }
+
+/**
+ * @} End of "defgroup node_access_example".
+ */

