From d1d797046ffe79faf45d0aa098774184c78dd5c9 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole Date: Wed, 5 Mar 2014 09:41:12 +0000 Subject: [PATCH] Issue #106721 by msonnabaum, lotyrin, erikwebb, catch, ezra-g, joelpittet, oleg.medvedev, jrglasgow, dawehner, bdragon: Optimize node access queries. --- .../Drupal/node/NodeGrantDatabaseStorage.php | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php b/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php index a7847d69123..9503713396b 100644 --- a/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php +++ b/core/modules/node/lib/Drupal/node/NodeGrantDatabaseStorage.php @@ -9,6 +9,7 @@ namespace Drupal\node; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Query\SelectInterface; +use Drupal\Core\Database\Query\Condition; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Session\AccountInterface; @@ -79,14 +80,7 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface { $query->condition($nids); $query->range(0, 1); - $grants = $query->orConditionGroup(); - foreach (node_access_grants($operation, $account) as $realm => $gids) { - foreach ($gids as $gid) { - $grants->condition(db_and() - ->condition('gid', $gid) - ->condition('realm', $realm)); - } - } + $grants = static::buildGrantsQueryCondition(node_access_grants($operation, $account)); if (count($grants) > 0) { $query->condition($grants); @@ -105,15 +99,8 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface { ->condition('nid', 0) ->condition('grant_view', 1, '>='); - $grants = db_or(); - foreach (node_access_grants('view', $account) as $realm => $gids) { - foreach ($gids as $gid) { - $grants->condition(db_and() - ->condition('gid', $gid) - ->condition('realm', $realm) - ); - } - } + $grants = static::buildGrantsQueryCondition(node_access_grants('view', $account)); + if (count($grants) > 0 ) { $query->condition($grants); } @@ -139,17 +126,9 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface { $subquery = $this->database->select('node_access', 'na') ->fields('na', array('nid')); - $grant_conditions = db_or(); // If any grant exists for the specified user, then user has access to the // node for the specified operation. - foreach ($grants as $realm => $gids) { - foreach ($gids as $gid) { - $grant_conditions->condition(db_and() - ->condition('na.gid', $gid) - ->condition('na.realm', $realm) - ); - } - } + $grant_conditions = static::buildGrantsQueryCondition($grants); // Attach conditions to the subquery for nodes. if (count($grant_conditions->conditions())) { @@ -264,4 +243,29 @@ class NodeGrantDatabaseStorage implements NodeGrantDatabaseStorageInterface { ->execute(); } + /** + * Creates a query condition from an array of node access grants. + * + * @param array $node_access_grants + * An array of grants, as returned by node_access_grants(). + * @return \Drupal\Core\Database\Query\Condition + * A condition object to be passed to $query->condition(). + * + * @see node_access_grants() + */ + static function buildGrantsQueryCondition(array $node_access_grants) { + $grants = new Condition("OR"); + foreach ($node_access_grants as $realm => $gids) { + if (!empty($gids)) { + $and = new Condition('AND'); + $grants->condition($and + ->condition('gid', $gids, 'IN') + ->condition('realm', $realm) + ); + } + } + + return $grants; + } + }