Commit 82c6f868 authored by catch's avatar catch

Issue #681760 by agentrickard, Josh Waihi, et al: eliminate duplicates caused...

Issue #681760 by agentrickard, Josh Waihi, et al: eliminate duplicates caused by node_access() table joins.
parent 863fed6b
......@@ -3403,9 +3403,6 @@ function _node_query_node_access_alter($query, $type) {
}
}
// Prevent duplicate records.
$query->distinct();
// Find all instances of the base table being joined -- could appear
// more than once in the query, and could be aliased. Join each one to
// the node_access table.
......@@ -3434,17 +3431,9 @@ function _node_query_node_access_alter($query, $type) {
foreach ($tables as $nalias => $tableinfo) {
$table = $tableinfo['table'];
if (!($table instanceof SelectInterface) && $table == $base_table) {
// The node_access table has the access grants for any given node so JOIN
// it to the table containing the nid which can be either the node
// table or a field value table.
if ($type == 'node') {
$access_alias = $query->join('node_access', 'na', '%alias.nid = ' . $nalias . '.nid');
}
else {
$access_alias = $query->leftJoin('node_access', 'na', '%alias.nid = ' . $nalias . '.entity_id');
$base_alias = $nalias;
}
// Set the subquery.
$subquery = db_select('node_access', 'na')
->fields('na', array('nid'));
$grant_conditions = db_or();
// If any grant exists for the specified user, then user has access
......@@ -3452,29 +3441,30 @@ function _node_query_node_access_alter($query, $type) {
foreach ($grants as $realm => $gids) {
foreach ($gids as $gid) {
$grant_conditions->condition(db_and()
->condition($access_alias . '.gid', $gid)
->condition($access_alias . '.realm', $realm)
->condition('na.gid', $gid)
->condition('na.realm', $realm)
);
}
}
$count = count($grant_conditions->conditions());
if ($type == 'node') {
if ($count) {
$query->condition($grant_conditions);
// Attach conditions to the subquery for nodes.
if (count($grant_conditions->conditions())) {
$subquery->condition($grant_conditions);
}
$query->condition($access_alias . '.grant_' . $op, 1, '>=');
}
else {
if ($count) {
$entity_conditions->condition($grant_conditions);
}
$entity_conditions->condition($access_alias . '.grant_' . $op, 1, '>=');
$subquery->condition('na.grant_' . $op, 1, '>=');
$field = 'nid';
// Now handle entities.
if ($type == 'entity') {
// Set a common alias for entities.
$base_alias = $nalias;
$field = 'entity_id';
}
$subquery->where("$nalias.$field = na.nid");
$query->exists($subquery);
}
}
if ($type == 'entity' && count($entity_conditions->conditions())) {
if ($type == 'entity' && count($subquery->conditions())) {
// All the node access conditions are only for field values belonging to
// nodes.
$entity_conditions->condition("$base_alias.entity_type", 'node');
......@@ -3486,6 +3476,7 @@ function _node_query_node_access_alter($query, $type) {
// Add the compiled set of rules to the query.
$query->condition($or);
}
}
/**
......
......@@ -2401,3 +2401,89 @@ class NodeRevisionPermissionsTestCase extends DrupalWebTestCase {
$GLOBALS['user'] = $original_user;
}
}
/**
* Tests pagination with a node access module enabled.
*/
class NodeAccessPagerTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Node access pagination',
'description' => 'Test access controlled node views have the right amount of comment pages.',
'group' => 'Node',
);
}
public function setUp() {
parent::setUp('node_access_test', 'comment', 'forum');
node_access_rebuild();
$this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'node test view'));
}
/**
* Tests the comment pager for nodes with multiple grants per realm.
*/
public function testCommentPager() {
// Create a node.
$node = $this->drupalCreateNode();
// Create 60 comments.
for ($i = 0; $i < 60; $i++) {
$comment = entity_create('comment', array(
'nid' => $node->nid,
'subject' => $this->randomName(),
'comment_body' => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
));
$comment->save();
}
$this->drupalLogin($this->web_user);
// View the node page. With the default 50 comments per page there should
// be two pages (0, 1) but no third (2) page.
$this->drupalGet('node/' . $node->nid);
$this->assertText($node->title, t('Node title found.'));
$this->assertText(t('Comments'), t('Has a comments section.'));
$this->assertRaw('page=1', t('Secound page exists.'));
$this->assertNoRaw('page=2', t('No third page exists.'));
}
/**
* Tests the forum node pager for nodes with multiple grants per realm.
*/
public function testForumPager() {
// Lookup the forums vocabulary vid.
$vid = variable_get('forum_nav_vocabulary', 0);
$this->assertTrue($vid, t('Forum navigation vocabulary found.'));
// Lookup the general discussion term.
$tree = taxonomy_get_tree($vid, 0, 1);
$tid = reset($tree)->tid;
$this->assertTrue($tid, t('General discussion term found.'));
// Create 30 nodes.
for ($i = 0; $i < 30; $i++) {
$this->drupalCreateNode(array(
'nid' => NULL,
'type' => 'forum',
'taxonomy_forums' => array(
LANGUAGE_NONE => array(
array('tid' => $tid, 'vid' => $vid, 'vocabulary_machine_name' => 'forums'),
),
),
));
}
// View the general discussion forum page. With the default 25 nodes per
// page there should be two pages for 30 nodes, no more.
$this->drupalLogin($this->web_user);
$this->drupalGet('forum/' . $tid);
$this->assertRaw('page=1', t('Secound page exists.'));
$this->assertNoRaw('page=2', t('No third page exists.'));
}
}
......@@ -15,7 +15,7 @@ function node_access_test_node_grants($account, $op) {
// First grant a grant to the author for own content.
$grants['node_access_test_author'] = array($account->uid);
if ($op == 'view' && user_access('node test view', $account)) {
$grants['node_access_test'] = array(8888);
$grants['node_access_test'] = array(8888, 8889);
}
if ($op == 'view' && $account->uid == variable_get('node_test_node_access_all_uid', 0)) {
$grants['node_access_all'] = array(0);
......@@ -38,6 +38,14 @@ function node_access_test_node_access_records($node) {
'grant_delete' => 0,
'priority' => 0,
);
$grants[] = array(
'realm' => 'node_access_test',
'gid' => 8889,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => 0,
);
// For the author realm, the GID is equivalent to a UID, which
// means there are many many groups of just 1 user.
$grants[] = array(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment