? .svn
? translations/.svn
Index: module_grants.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/module_grants/module_grants.module,v
retrieving revision 1.8
diff -u -p -r1.8 module_grants.module
--- module_grants.module	20 Apr 2009 00:22:53 -0000	1.8
+++ module_grants.module	4 May 2009 18:24:52 -0000
@@ -45,6 +45,13 @@ function module_grants_menu() {
     'access arguments' => array('access content summary'),
     'type' => MENU_LOCAL_TASK,
   );
+  $items['admin/settings/module_grants'] = array(
+    'title' => 'Module grants',
+    'description' =>  'Configure how multiple node access modules interact.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('module_grants_admin_settings'),
+    'access arguments' => array('administer site configuration'),
+  );
   return $items;
 }
 
@@ -63,6 +70,20 @@ function _show_viewable_nodes() {
 }
 
 /**
+ * Menu callback for admin settings.
+ */
+function module_grants_admin_settings() {
+  $form['module_grants_explicit'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enforce explicit AND between multiple node access modules'),
+    '#default_value' => variable_get('module_grants_explicit', 0),
+    '#description' => t('Check this box if you want to consider the node access settings for a particular node for <em>only those node access modules</em> that have a node access row for that node.  For example, if you have a node that is limited by node access module X but not module Y, with this box checked access would be granted even though module Y doesn\'t explicitly allow access.  With this box unchecked, access would be denied.  Whether or not this box is checked, the default behavior will apply when you have a node limited by both modules X and Y -- access will be granted only if both allow it.'),
+  );
+
+  return system_settings_form($form);
+}
+
+/**
  * Implementation of hook_menu_alter().
  *
  * Modify menu items defined in other modules (in particular the node module).
@@ -188,8 +209,14 @@ function module_grants_node_access($op, 
   }
 
   // If the module neither allows nor denies access, then find grants
-  // amongst modules that implement hook_node_grants()
-  $all_grants = grants_by_module($op, $account);
+  // amongst modules that implement hook_node_grants(), taking into
+  // account the module_grants_explicit setting.
+  if (variable_get('module_grants_explicit', 0)) {
+    $all_grants = grants_by_module($op, $account, $node->nid);
+  }
+  else {
+    $all_grants = grants_by_module($op, $account);
+  }
 
   $base_sql = "SELECT COUNT(*) FROM {node_access} WHERE (nid=0 OR nid=%d) AND ((gid=0 AND realm='all')";
 
@@ -219,16 +246,28 @@ function module_grants_node_access($op, 
  *   The operation, i.e 'view', 'update' or 'delete'
  * @param $account
  *   User account object
+ * @param $nid
+ *   Optional. If a nid is passed in, only modules with at least one node_access
+ *   row for the given nid are included.
  * @return
  *   Array of module grants SQL
  */
-function grants_by_module($op, $account) {
+function grants_by_module($op, $account, $nid = NULL) {
   $hook = 'node_grants';
   $all_grants = array();
   foreach (module_implements($hook) as $module) {
     $module_grants = module_invoke($module, $hook, $account, $op);
     if (!empty($module_grants)) {
       $module_gids = array();
+      // If a nid has been passed in, don't collect the grants for this module
+      // unless it has at least one row in the node_access table for this nid.
+      if ($nid) {
+        $result = db_result(db_query("SELECT COUNT(*) FROM {node_access} WHERE nid = %d AND realm IN ('%s')", $nid, implode("','", array_keys($module_grants))));
+        if ($result == 0) {
+          // This module doesn't have a node_access row for this node, so continue to the next module.
+          continue;
+        }
+      }
       foreach ($module_grants as $realm => $gids) {
         foreach ($gids as $gid) {
           $module_gids[] = "(gid=$gid AND realm='$realm')";
