summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/node/node.module12
-rw-r--r--modules/simpletest/tests/database_test.module14
-rw-r--r--modules/simpletest/tests/database_test.test2
-rw-r--r--modules/system/system.api.php62
4 files changed, 81 insertions, 9 deletions
diff --git a/modules/node/node.module b/modules/node/node.module
index f2e616f6a..deca20ea3 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -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()
diff --git a/modules/simpletest/tests/database_test.module b/modules/simpletest/tests/database_test.module
index 555f976b3..25631e0c7 100644
--- a/modules/simpletest/tests/database_test.module
+++ b/modules/simpletest/tests/database_test.module
@@ -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().
*/
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index 37c6fac5f..9cbec229a 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -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');
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index 3ac517fd4..e6d3b3038 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -1375,6 +1375,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.
*
* The hook will be called the first time a module is installed, and the