diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php index 3be5a2f..4966744 100644 --- a/core/lib/Drupal/Core/Database/Query/Select.php +++ b/core/lib/Drupal/Core/Database/Query/Select.php @@ -44,7 +44,7 @@ class Select extends Query implements SelectInterface { * 'type' => $join_type (one of INNER, LEFT OUTER, RIGHT OUTER), * 'table' => $table, * 'alias' => $alias_of_the_table, - * 'condition' => $condition_clause_on_which_to_join, + * 'condition' => $join_condition (string or Condition object), * 'arguments' => $array_of_arguments_for_placeholders_in_the condition. * 'all_fields' => TRUE to SELECT $alias.*, FALSE or NULL otherwise. * ) @@ -52,6 +52,10 @@ class Select extends Query implements SelectInterface { * If $table is a string, it is taken as the name of a table. If it is * a Select query object, it is taken as a subquery. * + * If $join_condition is a Condition object, any arguments should be + * incorporated into the object; a separate array of arguments does not + * need to be provided. + * * @var array */ protected $tables = array(); @@ -201,6 +205,10 @@ public function arguments() { if ($table['table'] instanceof SelectInterface) { $args += $table['table']->arguments(); } + // If the join condition is an object, grab its arguments recursively. + if (!empty($table['condition']) && $table['condition'] instanceof ConditionInterface) { + $args += $table['condition']->arguments(); + } } foreach ($this->expressions as $expression) { @@ -230,6 +238,10 @@ public function compile(Connection $connection, PlaceholderInterface $queryPlace if ($table['table'] instanceof SelectInterface) { $table['table']->compile($connection, $queryPlaceholder); } + // Make sure join conditions are also compiled. + if (!empty($table['condition']) && $table['condition'] instanceof ConditionInterface) { + $table['condition']->compile($connection, $queryPlaceholder); + } } // If there are any dependent queries to UNION, compile it recursively. @@ -253,6 +265,11 @@ public function compiled() { return FALSE; } } + if (!empty($table['condition']) && $table['condition'] instanceof ConditionInterface) { + if (!$table['condition']->compiled()) { + return FALSE; + } + } } foreach ($this->union as $union) { @@ -827,7 +844,7 @@ public function __toString() { $query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']); if (!empty($table['condition'])) { - $query .= ' ON ' . $table['condition']; + $query .= ' ON ' . (string) $table['condition']; } } diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 91d27e8..4bd7862 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1044,7 +1044,7 @@ function node_query_node_access_alter(AlterableInterface $query) { return; } - $tables = $query->getTables(); + $tables = &$query->getTables(); $base_table = $query->getMetaData('base_table'); // If the base table is not given, default to node if present. if (!$base_table) { diff --git a/core/modules/node/src/NodeGrantDatabaseStorage.php b/core/modules/node/src/NodeGrantDatabaseStorage.php index 6b6f280..6df3c91 100644 --- a/core/modules/node/src/NodeGrantDatabaseStorage.php +++ b/core/modules/node/src/NodeGrantDatabaseStorage.php @@ -190,7 +190,24 @@ public function alterQuery($query, array $tables, $op, AccountInterface $account // Now handle entities. $subquery->where("$nalias.$field = na.nid"); - $query->exists($subquery); + if (empty($tableinfo['join type'])) { + $query->exists($subquery); + } + else { + // If it's a join, add the node access check to the join condition. + $join_cond = $query + ->andConditionGroup() + ->exists($subquery); + // Add the existing join conditions into the Condition object. + if ($tables[$nalias]['condition'] instanceof ConditionInterface) { + $join_cond->condition($tables[$nalias]['condition']); + } + else { + $join_cond->where($tables[$nalias]['condition'], $tables[$nalias]['arguments']); + $tables[$nalias]['arguments'] = array(); + } + $tables[$nalias]['condition'] = $join_cond; + } } } } diff --git a/core/modules/node/src/NodeGrantDatabaseStorageInterface.php b/core/modules/node/src/NodeGrantDatabaseStorageInterface.php index c59f941..3cf8b7c 100644 --- a/core/modules/node/src/NodeGrantDatabaseStorageInterface.php +++ b/core/modules/node/src/NodeGrantDatabaseStorageInterface.php @@ -50,7 +50,7 @@ public function checkAll(AccountInterface $account); * @return int * Status of the access check. */ - public function alterQuery($query, array $tables, $op, AccountInterface $account, $base_table); + public function alterQuery($query, array &$tables, $op, AccountInterface $account, $base_table); /** * Writes a list of grants to the database, deleting previously saved ones. 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 e195ea8..1338eac 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 @@ -78,7 +78,7 @@ function node_access_test_node_grants($account, $op) { function node_access_test_node_access_records(NodeInterface $node) { $grants = array(); // For NodeAccessBaseTableTestCase, only set records for private nodes. - if (!\Drupal::state()->get('node_access_test.private') || $node->private->value) { + if (!\Drupal::state()->get('node_access_test.private') || (isset($node->private) && $node->private->value)) { // Groups 8888 and 8889 for the node_access_test realm both receive a view // grant for all controlled nodes. See node_access_test_node_grants(). $grants[] = array(