- Patch #320591 by Moshe, Crell et al: tag specific alter hook for database queries.
parent
7e60d94f69
commit
634379299f
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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().
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue