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

merge-requests/26/head
Dries Buytaert 2009-01-04 19:56:51 +00:00
parent 7e60d94f69
commit 634379299f
5 changed files with 87 additions and 9 deletions

View File

@ -291,7 +291,13 @@ class SelectQuery extends Query implements QueryConditionInterface, QueryAlterab
} }
public function execute() { public function execute() {
// Modules may alter all queries or only those having a particular tag.
drupal_alter('query', $this); drupal_alter('query', $this);
if (isset($this->alterTags)) {
foreach ($this->alterTags as $tag => $value) {
drupal_alter("query_$tag", $this);
}
}
$args = $this->getArguments(); $args = $this->getArguments();

View File

@ -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) { function node_query_node_access_alter(QueryAlterableInterface $query) {
if ($query->hasTag('node_access') && !node_access_view_all_nodes()) { // Skip the extra expensive alterations if site has no node access control modules.
if (!node_access_view_all_nodes()) {
// Prevent duplicate records.
$query->distinct(); $query->distinct();
// The recognized operations are 'view', 'update', 'delete'.
if (!$op = $query->getMetaData('op')) { if (!$op = $query->getMetaData('op')) {
$op = 'view'; $op = 'view';
} }
// Skip the extra joins and conditions for node admins.
if (!user_access('bypass node access')) { 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'); $access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
$or = db_or(); $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 (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
foreach ($gids as $gid) { foreach ($gids as $gid) {
$or->condition(db_and() $or->condition(db_and()

View File

@ -4,16 +4,12 @@
/** /**
* Implementation of hook_query_alter(). * 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')) { if ($query->hasTag('database_test_alter_add_range')) {
$query->range(0, 2); $query->range(0, 2);
} }
if ($query->hasTag('database_test_alter_remove_range')) {
$query->range();
}
if ($query->hasTag('database_test_alter_add_join')) { if ($query->hasTag('database_test_alter_add_join')) {
$people_alias = $query->join('test', 'people', "test_task.pid=people.id"); $people_alias = $query->join('test', 'people', "test_task.pid=people.id");
$name_field = $query->addField('people', 'name', 'name'); $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(). * Implementation of hook_menu().
*/ */

View File

@ -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() { function testAlterRemoveRange() {
$query = db_select('test'); $query = db_select('test');

View File

@ -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. * Install the current version of the database schema, and any other setup tasks.
* *