Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1216
diff -u -p -r1.1216 node.module
--- modules/node/node.module	15 Jan 2010 10:59:21 -0000	1.1216
+++ modules/node/node.module	15 Jan 2010 17:26:21 -0000
@@ -2641,6 +2641,8 @@ function node_search_validate($form, &$f
 function node_access($op, $node, $account = NULL) {
   global $user;
 
+  $rights = &drupal_static(__FUNCTION__, array());
+
   if (!$node || !in_array($op, array('view', 'update', 'delete', 'create'), TRUE)) {
     // If there was no node to check against, or the $op was not one of the
     // supported ones, we return access denied.
@@ -2651,11 +2653,24 @@ function node_access($op, $node, $accoun
     $account = $user;
   }
 
+  // $node may be either an object or a node type. Since node types cannot be
+  // an integer, use either nid or type as the static cache id.
+
+  $cid = is_object($node) ? $node->nid : $node;
+
+  // If we've already checked access for this node, user and op, return from
+  // cache.
+  if (isset($rights[$account->uid][$cid][$op])) {
+    return $rights[$account->uid][$cid][$op];
+  }
+
   if (user_access('bypass node access', $account)) {
+    $rights[$account->uid][$cid][$op] = TRUE;
     return TRUE;
   }
 
   if (!user_access('access content', $account)) {
+    $rights[$account->uid][$cid][$op] = FALSE;
     return FALSE;
   }
 
@@ -2666,45 +2681,58 @@ function node_access($op, $node, $accoun
   // node_access table.
   $access = module_invoke_all('node_access', $node, $op, $account);
   if (in_array(NODE_ACCESS_DENY, $access, TRUE)) {
+    $rights[$account->uid][$cid][$op] = FALSE;
     return FALSE;
   }
   elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) {
+    $rights[$account->uid][$cid][$op] = TRUE;
     return TRUE;
   }
 
   // Check if authors can view their own unpublished nodes.
   if ($op == 'view' && !$node->status && user_access('view own unpublished content', $account) && $account->uid == $node->uid && $account->uid != 0) {
+    $rights[$account->uid][$cid][$op] = TRUE;
     return TRUE;
   }
 
   // If the module did not override the access rights, use those set in the
   // node_access table.
   if ($op != 'create' && $node->nid) {
-    $query = db_select('node_access');
-    $query->addExpression('1');
-    $query->condition('grant_' . $op, 1, '>=');
-    $nids = db_or()->condition('nid', $node->nid);
-    if ($node->status) {
-      $nids->condition('nid', 0);
-    }
-    $query->condition($nids);
-    $query->range(0, 1);
-
-    $grants = db_or();
-    foreach (node_access_grants($op, $account) as $realm => $gids) {
-      foreach ($gids as $gid) {
-        $grants->condition(db_and()
-          ->condition('gid', $gid)
-          ->condition('realm', $realm)
-        );
-      }
-    }
-    if (count($grants) > 0) {
-      $query->condition($grants);
-    }
-    return (bool) $query
-      ->execute()
-      ->fetchField();
+    if (module_implements('node_grants')) {
+      $query = db_select('node_access');
+      $query->addExpression('1');
+      $query->condition('grant_' . $op, 1, '>=');
+      $nids = db_or()->condition('nid', $node->nid);
+      if ($node->status) {
+        $nids->condition('nid', 0);
+      }
+      $query->condition($nids);
+      $query->range(0, 1);
+
+      $grants = db_or();
+      foreach (node_access_grants($op, $account) as $realm => $gids) {
+        foreach ($gids as $gid) {
+          $grants->condition(db_and()
+            ->condition('gid', $gid)
+            ->condition('realm', $realm)
+          );
+        }
+      }
+      if (count($grants) > 0) {
+        $query->condition($grants);
+      }
+      $result =  (bool) $query
+        ->execute()
+        ->fetchField();
+      $rights[$account->uid][$cid][$op] = $result;
+      return $result;
+    }
+    elseif (is_object($node) && $op == 'view' && $node->status) {
+      // If no modules implement hook_node_grants(), the default behaviour is to
+      // allow all users to view published nodes, so reflect that here.
+      $rights[$account->uid][$cid][$op] = TRUE;
+      return TRUE;
+    }
   }
 
   return FALSE;
