Index: modules/hs_taxonomy_views.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/modules/hs_taxonomy_views.module,v
retrieving revision 1.25
diff -u -p -r1.25 hs_taxonomy_views.module
--- modules/hs_taxonomy_views.module	26 Aug 2010 11:16:19 -0000	1.25
+++ modules/hs_taxonomy_views.module	23 Nov 2010 14:35:23 -0000
@@ -180,6 +180,9 @@ function hs_taxonomy_views_handlers() {
       'hs_taxonomy_views_handler_filter_term_node_tid' => array(
         'parent' => 'views_handler_filter_term_node_tid',
       ),
+      'hs_taxonomy_views_handler_filter_term_node_tid_depth' => array(
+        'parent' => 'hs_taxonomy_views_handler_filter_term_node_tid',
+      ),
     )
   );
 }
@@ -187,7 +190,7 @@ function hs_taxonomy_views_handlers() {
 /**
  * Implementation of hook_views_data_alter().
  */
-function hs_taxonomy_views_data_alter(&$data) {
+function hs_taxonomy_views_views_data_alter(&$data) {
   // Term view type, tid field.
   $data['term_data']['tid'] = array(
    'title' => t('Term ID'),
@@ -238,6 +241,21 @@ function hs_taxonomy_views_data_alter(&$
       'skip base'       => 'term_data',
     ),
   );
+
+  // Node view type, tid with depth field.
+  $data['node']['term_node_tid_depth'] = array(
+    'group' => t('Taxonomy'),
+    'title' => t('Term ID (with depth)'),
+    'help' => t('The depth filter is more complex, so provides fewer options.'),
+    'real field' => 'vid',
+    'argument' => array(
+      'handler' => 'views_handler_argument_term_node_tid_depth',
+      'accept depth modifier' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'hs_taxonomy_views_handler_filter_term_node_tid_depth',
+    ),
+  );
 }
 
 
@@ -560,8 +578,10 @@ function hs_taxonomy_views_hierarchical_
       if (isset($view->display[$display_id]->display_options['filters']) && count($view->display[$display_id]->display_options['filters'])) {
         foreach ($view->display[$display_id]->display_options['filters'] as $filter) {
           if (isset($filter['type']) && $filter['type'] == 'hierarchical_select'
-              && isset($filter['table']) && $filter['table'] == 'term_node'
+            && ((isset($filter['table']) && $filter['table'] == 'term_node'
               && isset($filter['field']) && $filter['field'] == 'tid')
+             || (isset($filter['table']) && $filter['table'] == 'node'
+              && isset($filter['field']) && $filter['field'] == 'term_node_tid_depth')))
           {
             $vocabulary = taxonomy_vocabulary_load($filter['vid']);
             $filter_label = (!empty($filter['expose']['label'])) ? $filter['expose']['label'] : t('Taxonomy: Term');
Index: modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc
===================================================================
RCS file: modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc
diff -N modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc	23 Nov 2010 14:35:23 -0000
@@ -0,0 +1,91 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * This file defines a new filter handler for using Hierarchical Select in
+ * exposed Taxonomy term with depth filters.
+ */
+
+class hs_taxonomy_views_handler_filter_term_node_tid_depth extends hs_taxonomy_views_handler_filter_term_node_tid {
+  function operator_options() {
+    return array(
+      'or' => t('Is one of'),
+    );
+  }
+
+  function option_definition() {
+    $options = parent::option_definition();
+
+    $options['depth'] = array('default' => 0);
+
+    return $options;
+  }
+
+  function extra_options_form(&$form, &$form_state) {
+    parent::extra_options_form($form, $form_state);
+
+    $form['depth'] = array(
+      '#type' => 'weight',
+      '#title' => t('Depth'),
+      '#default_value' => $this->options['depth'],
+      '#description' => t('The depth will match nodes tagged with terms in the hierarchy. For example, if you have the term "fruit" and a child term "apple", with a depth of 1 (or higher) then filtering for the term "fruit" will get nodes that are tagged with "apple" as well as "fruit". If negative, the reverse is true; searching for "apple" will also pick up nodes tagged with "fruit" if depth is -1 (or lower).'),
+    );
+  }
+
+  function query() {
+    // If no filter values are present, then do nothing.
+    if (count($this->value) == 0) {
+      return;
+    }
+    else if (count($this->value) == 1) {
+      $placeholder = " = %d";
+    }
+    else {
+      $placeholder = " IN (" . implode(', ', array_fill(0, sizeof($this->value), '%d')) . ")";
+    }
+
+    // The normal use of ensure_my_table() here breaks Views.
+    // So instead we trick the filter into using the alias of the base table.
+    // See http://drupal.org/node/271833
+    // If a relationship is set, we must use the alias it provides.
+    if (!empty($this->relationship)) {
+      $this->table_alias = $this->relationship;
+    }
+    // If no relationship, then use the alias of the base table.
+    else if (isset($this->query->table_queue[$this->query->base_table]['alias'])) {
+      $this->table_alias = $this->query->table_queue[$this->query->base_table]['alias'];
+    }
+    // This should never happen, but if it does, we fail quietly.
+    else {
+      return;
+    }
+
+    // Now build the subqueries.
+    $subquery = "\n  SELECT tn.vid FROM {term_node} tn\n";
+    $where = "  WHERE tn.tid $placeholder\n";
+    $args = $this->value;
+    $last = "tn";
+
+    if ($this->options['depth'] > 0) {
+      $subquery .= "    LEFT JOIN {term_hierarchy} th ON th.tid = tn.tid\n";
+      $last = "th";
+      foreach (range(1, abs($this->options['depth'])) as $count) {
+        $subquery .= "    LEFT JOIN {term_hierarchy} th$count ON $last.parent = th$count.tid\n";
+        $where .= "    OR th$count.tid $placeholder\n";
+        $args = array_merge($args, $this->value);
+        $last = "th$count";
+      }
+    }
+    else if ($this->options['depth'] < 0) {
+      foreach (range(1, abs($this->options['depth'])) as $count) {
+        $subquery .= "    LEFT JOIN {term_hierarchy} th$count ON $last.tid = th$count.parent\n";
+        $where .= "    OR th$count.tid $placeholder\n";
+        $args = array_merge($args, $this->value);
+        $last = "th$count";
+      }
+    }
+
+    $this->query->add_where(0, "$this->table_alias.$this->real_field IN ($subquery$where  )", $args);
+  }
+}
