commit 82d7301bd79adf7d93425bbd4a3989867b9259e1
Author: Damien Tournoud <damien@commerceguys.com>
Date:   Thu Oct 27 14:39:55 2011 +0200

    Fix for issue #1222324: run the query alteration process manually to workaround core's limitations.

diff --git a/handlers/views_handler_relationship.inc b/handlers/views_handler_relationship.inc
index bcab8b9..2344536 100644
--- a/handlers/views_handler_relationship.inc
+++ b/handlers/views_handler_relationship.inc
@@ -137,7 +137,7 @@ class views_handler_relationship extends views_handler {
     // Add access tags if the base table provide it.
     if (empty($this->query->options['disable_sql_rewrite']) && isset($table_data['table']['base']['access query tag'])) {
       $access_tag = $table_data['table']['base']['access query tag'];
-      $this->query->add_tag($access_tag);
+      $this->query->add_tag($access_tag, $alias);
     }
   }
 
diff --git a/includes/view.inc b/includes/view.inc
index 41ed056..54cd2b4 100644
--- a/includes/view.inc
+++ b/includes/view.inc
@@ -801,6 +801,15 @@ class view extends views_db_object {
       }
     }
 
+    // Add the access control tag to the query.
+    if (empty($this->query->options['disable_sql_rewrite'])) {
+      $base_table_data = views_fetch_data($this->base_table);
+      if (isset($base_table_data['table']['base']['access query tag'])) {
+        $access_tag = $base_table_data['table']['base']['access query tag'];
+        $this->query->add_tag($access_tag);
+      }
+    }
+
     // Build all the relationships first thing.
     $this->_build('relationship');
 
diff --git a/plugins/views_plugin_query_default.inc b/plugins/views_plugin_query_default.inc
index 23f0eb1..b579665 100644
--- a/plugins/views_plugin_query_default.inc
+++ b/plugins/views_plugin_query_default.inc
@@ -1009,8 +1009,11 @@ class views_plugin_query_default extends views_plugin_query {
    *
    * @see SelectQuery::addTag
    */
-  function add_tag($tag) {
-    $this->tags[] = $tag;
+  function add_tag($tag, $base_table = NULL) {
+    $this->tags[] = array(
+      'tag' => $tag,
+      'base_table' => $base_table,
+    );
   }
 
   /**
@@ -1186,11 +1189,6 @@ class views_plugin_query_default extends views_plugin_query {
       ->addTag('views')
       ->addTag('views_' . $this->view->name);
 
-    // Add the tags added to the view itself.
-    foreach ($this->tags as $tag) {
-      $query->addTag($tag);
-    }
-
     if (!empty($distinct)) {
       $query->distinct();
     }
@@ -1295,6 +1293,43 @@ class views_plugin_query_default extends views_plugin_query {
 
     $view->build_info['query'] = $this->query();
     $view->build_info['count_query'] = $this->query(TRUE);
+
+    // Alter the queries.
+    foreach ($this->tags as $tag) {
+      $this->executeAlterHooks($view->build_info['query'], $tag['tag'], $tag['base_table']);
+      $this->executeAlterHooks($view->build_info['count_query'], $tag['tag'], $tag['base_table']);
+    }
+  }
+
+  /**
+   * Manually alter a SelectQuery.
+   *
+   * Core doesn't allow defining a different base table for every tag,
+   * making it impossible to property perform access control across
+   * relationships. We run every tag one by one, mimicking the alter process
+   * performed in SelectQuery::preExecute().
+   */
+  protected function executeAlterHooks(SelectQueryInterface $query, $tag, $base_table = NULL) {
+    // Save the old tags and metadata.
+    // For some reason, those are public.
+    $old_tags = $query->alterTags;
+    $old_metadata = $query->alterMetaData;
+
+    $query->alterTags = array($tag => TRUE);
+    if (isset($base_table)) {
+      // Use an explicit base table.
+      $query->alterMetaData['base_table'] = $base_table;
+    }
+    else {
+      // Else, use the first table of the query.
+      $tables = $query->getTables();
+      $query->alterMetaData['base_table'] = key($tables);
+    }
+    drupal_alter(array('query', 'query_' . $tag), $query);
+
+    // Restore the tags and metadata.
+    $query->alterTags = $old_tags;
+    $query->alterMetaData = $old_metadata;
   }
 
   /**
@@ -1312,15 +1347,6 @@ class views_plugin_query_default extends views_plugin_query {
     $query->addMetaData('view', $view);
     $count_query->addMetaData('view', $view);
 
-    if (empty($this->options['disable_sql_rewrite'])) {
-      $base_table_data = views_fetch_data($this->base_table);
-      if (isset($base_table_data['table']['base']['access query tag'])) {
-        $access_tag = $base_table_data['table']['base']['access query tag'];
-        $query->addTag($access_tag);
-        $count_query->addTag($access_tag);
-      }
-    }
-
     $items = array();
     if ($query) {
       $additional_arguments = module_invoke_all('views_query_substitutions', $view);
