Commit 63437929 authored by Dries's avatar Dries

- Patch #320591 by Moshe, Crell et al: tag specific alter hook for database queries.

parent 7e60d94f
......@@ -291,7 +291,13 @@ public function getArguments() {
}
public function execute() {
// Modules may alter all queries or only those having a particular tag.
drupal_alter('query', $this);
if (isset($this->alterTags)) {
foreach ($this->alterTags as $tag => $value) {
drupal_alter("query_$tag", $this);
}
}
$args = $this->getArguments();
......
......@@ -2324,17 +2324,23 @@ function node_db_rewrite_sql($query, $primary_table, $primary_field) {
}
/**
* Implementation of hook_query_alter().
* Implementation of hook_query_TAG_alter().
*/
function node_query_alter(QueryAlterableInterface $query) {
if ($query->hasTag('node_access') && !node_access_view_all_nodes()) {
function node_query_node_access_alter(QueryAlterableInterface $query) {
// Skip the extra expensive alterations if site has no node access control modules.
if (!node_access_view_all_nodes()) {
// Prevent duplicate records.
$query->distinct();
// The recognized operations are 'view', 'update', 'delete'.
if (!$op = $query->getMetaData('op')) {
$op = 'view';
}
// Skip the extra joins and conditions for node admins.
if (!user_access('bypass node access')) {
// The node_access table has the access grants for any given node.
$access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
$or = db_or();
// If any grant exists for the specified user, then user has access to the node for the specified operation.
foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
foreach ($gids as $gid) {
$or->condition(db_and()
......
......@@ -4,16 +4,12 @@
/**
* Implementation of hook_query_alter().
*/
function database_test_query_alter(SelectQuery $query) {
function database_test_query_alter(QueryAlterableInterface $query) {
if ($query->hasTag('database_test_alter_add_range')) {
$query->range(0, 2);
}
if ($query->hasTag('database_test_alter_remove_range')) {
$query->range();
}
if ($query->hasTag('database_test_alter_add_join')) {
$people_alias = $query->join('test', 'people', "test_task.pid=people.id");
$name_field = $query->addField('people', 'name', 'name');
......@@ -36,6 +32,14 @@ function database_test_query_alter(SelectQuery $query) {
}
}
/**
* Implementation of hook_query_TAG_alter(). Called by DatabaseTestCase::testAlterRemoveRange.
*/
function database_test_query_database_test_alter_remove_range_alter(QueryAlterableInterface $query) {
$query->range();
}
/**
* Implementation of hook_menu().
*/
......
......@@ -1695,7 +1695,7 @@ class DatabaseAlter2TestCase extends DatabaseTestCase {
}
/**
* Test that we can remove a range() value from a query.
* Test that we can remove a range() value from a query. This also tests hook_query_TAG_alter().
*/
function testAlterRemoveRange() {
$query = db_select('test');
......
......@@ -1374,6 +1374,68 @@ function hook_schema_alter(&$schema) {
);
}
/**
* Perform alterations to a structured query.
*
* Structured (aka dynamic) queries that have tags associated may be altered by any module
* before the query is executed.
*
* @see hook_query_TAG_alter()
* @see node_query_node_access_alter()
*
* @param $query
* A Query object describing the composite parts of a SQL query.
* @return
* None.
*/
function hook_query_alter(QueryAlterableInterface $query) {
}
/**
* Perform alterations to a structured query for a given tag.
*
* @see hook_query_alter()
* @see node_query_node_access_alter()
*
* @param $query
* An Query object describing the composite parts of a SQL query.
* @return
* None.
*/
function hook_query_TAG_alter(QueryAlterableInterface $query) {
// Skip the extra expensive alterations if site has no node access control modules.
if (!node_access_view_all_nodes()) {
// Prevent duplicates records.
$query->distinct();
// The recognized operations are 'view', 'update', 'delete'.
if (!$op = $query->getMetaData('op')) {
$op = 'view';
}
// Skip the extra joins and conditions for node admins.
if (!user_access('bypass node access')) {
// The node_access table has the access grants for any given node.
$access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
$or = db_or();
// If any grant exists for the specified user, then user has access to the node for the specified operation.
foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
foreach ($gids as $gid) {
$or->condition(db_and()
->condition("{$access_alias}.gid", $gid)
->condition("{$access_alias}.realm", $realm)
);
}
}
if (count($or->conditions())) {
$query->condition($or);
}
$query->condition("{$access_alias}.grant_$op", 1, '>=');
}
}
}
/**
* Install the current version of the database schema, and any other setup tasks.
*
......
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