From 4cc4103e03512ecbf8cd0dbcbbe35a41e037cc31 Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Sat, 30 Jun 2012 11:30:24 -0700
Subject: [PATCH] =?UTF-8?q?Issue=20#1658814=20by=20G=C3=A1bor=20Hojtsy:=20?=
 =?UTF-8?q?Make=20node=5Faccess()=20language-aware.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 core/modules/node/node.api.php                |  4 +-
 core/modules/node/node.module                 | 41 +++++++++++++------
 .../node_access_test/node_access_test.module  | 11 +++++
 3 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php
index 4a067ab40df9..9719fc034011 100644
--- a/core/modules/node/node.api.php
+++ b/core/modules/node/node.api.php
@@ -596,6 +596,8 @@ function hook_node_load($nodes, $types) {
  *   - "view"
  * @param object $account
  *   The user object to perform the access check operation on.
+ * @param object $langcode
+ *   The language code to perform the access check operation on.
  *
  * @return integer
  *   - NODE_ACCESS_ALLOW: if the operation is to be allowed.
@@ -604,7 +606,7 @@ function hook_node_load($nodes, $types) {
  *
  * @ingroup node_access
  */
-function hook_node_access($node, $op, $account) {
+function hook_node_access($node, $op, $account, $langcode) {
   $type = is_string($node) ? $node : $node->type;
 
   $configured_types = node_permissions_get_configured_types();
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 70663a7c4189..319f4220734a 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -2879,13 +2879,21 @@ function node_form_system_themes_admin_form_submit($form, &$form_state) {
  * @param $account
  *   (optional) A user object representing the user for whom the operation is to
  *   be performed. Determines access for a user other than the current user.
+ * @param $langcode
+ *   (optional) Language code for the variant of the node. Different language
+ *   variants might have different permissions associated. If NULL, the
+ *   original langcode of the node is used.
  *
  * @return
  *   TRUE if the operation may be performed, FALSE otherwise.
  *
  * @see node_menu()
+ *
+ * @todo
+ *   Add langcode support to node_access schema / queries.
+ *   http://drupal.org/node/1658846
  */
-function node_access($op, $node, $account = NULL) {
+function node_access($op, $node, $account = NULL, $langcode = NULL) {
   $rights = &drupal_static(__FUNCTION__, array());
 
   if (!$node || !in_array($op, array('view', 'update', 'delete', 'create'), TRUE)) {
@@ -2903,18 +2911,25 @@ function node_access($op, $node, $account = NULL) {
 
   $cid = is_object($node) ? $node->nid : $node;
 
+  // If no language code was provided, default to the node's langcode or
+  // to an empty langcode if a node type was requested. The latter is purely
+  // for caching purposes.
+  if (empty($langcode)) {
+    $langcode = is_object($node) ? $node->langcode : '';
+  }
+
   // 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 (isset($rights[$account->uid][$cid][$langcode][$op])) {
+    return $rights[$account->uid][$cid][$langcode][$op];
   }
 
   if (user_access('bypass node access', $account)) {
-    $rights[$account->uid][$cid][$op] = TRUE;
+    $rights[$account->uid][$cid][$langcode][$op] = TRUE;
     return TRUE;
   }
   if (!user_access('access content', $account)) {
-    $rights[$account->uid][$cid][$op] = FALSE;
+    $rights[$account->uid][$cid][$langcode][$op] = FALSE;
     return FALSE;
   }
 
@@ -2923,19 +2938,19 @@ function node_access($op, $node, $account = NULL) {
   // - At least one module says to grant access.
   // If no module specified either allow or deny, we fall back to the
   // node_access table.
-  $access = module_invoke_all('node_access', $node, $op, $account);
+  $access = module_invoke_all('node_access', $node, $op, $account, $langcode);
   if (in_array(NODE_ACCESS_DENY, $access, TRUE)) {
-    $rights[$account->uid][$cid][$op] = FALSE;
+    $rights[$account->uid][$cid][$langcode][$op] = FALSE;
     return FALSE;
   }
   elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) {
-    $rights[$account->uid][$cid][$op] = TRUE;
+    $rights[$account->uid][$cid][$langcode][$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;
+  if ($op == 'view' && !$node->get('status', $langcode) && user_access('view own unpublished content', $account) && $account->uid == $node->get('uid', $langcode) && $account->uid != 0) {
+    $rights[$account->uid][$cid][$langcode][$op] = TRUE;
     return TRUE;
   }
 
@@ -2968,13 +2983,13 @@ function node_access($op, $node, $account = NULL) {
       $result =  (bool) $query
         ->execute()
         ->fetchField();
-      $rights[$account->uid][$cid][$op] = $result;
+      $rights[$account->uid][$cid][$langcode][$op] = $result;
       return $result;
     }
-    elseif (is_object($node) && $op == 'view' && $node->status) {
+    elseif (is_object($node) && $op == 'view' && $node->get('status', $langcode)) {
       // If no modules implement hook_node_grants(), the default behavior is to
       // allow all users to view published nodes, so reflect that here.
-      $rights[$account->uid][$cid][$op] = TRUE;
+      $rights[$account->uid][$cid][$langcode][$op] = TRUE;
       return TRUE;
     }
   }
diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.module b/core/modules/node/tests/modules/node_access_test/node_access_test.module
index b6c6127406dc..5d557cc2a71f 100644
--- a/core/modules/node/tests/modules/node_access_test/node_access_test.module
+++ b/core/modules/node/tests/modules/node_access_test/node_access_test.module
@@ -231,3 +231,14 @@ function _node_access_test_node_write(Node $node) {
       ->execute();
   }
 }
+
+/**
+ * Implements hook_node_access().
+ */
+function node_access_test_node_access($node, $op, $account, $langcode) {
+  if (variable_get('node_access_test_secret_catalan', 0) && $langcode == 'ca') {
+    // Make all Catalan content secret.
+    return NODE_ACCESS_DENY;
+  }
+  return NODE_ACCESS_IGNORE;
+}
-- 
GitLab