- 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() {
|
||||
// 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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue