Index: apachesolr.module
===================================================================
--- apachesolr.module	(revision 23287)
+++ apachesolr.module	(working copy)
@@ -718,7 +718,6 @@
   $limits = variable_get('apachesolr_facet_query_limits', array());
 
   $limit = drupal_map_assoc(array(50, 40, 30, 20, 15, 10, 5, 3));
-
   $form['apachesolr_facet_query_initial_limit'] = array(
     '#type' => 'select',
     '#title' => t('Initial filter links'),
@@ -726,6 +725,7 @@
     '#description' => t('The initial number of filter links to show in this block.'),
     '#default_value' => isset($initial[$module][$delta]) ? $initial[$module][$delta] : variable_get('apachesolr_facet_query_initial_limit_default', 10),
   );
+
   $limit = drupal_map_assoc(array(100, 75, 50, 40, 30, 20, 15, 10, 5, 3));
   $form['apachesolr_facet_query_limit'] = array(
     '#type' => 'select',
@@ -735,6 +735,14 @@
     '#default_value' => isset($limits[$module][$delta]) ? $limits[$module][$delta] : variable_get('apachesolr_facet_query_limit_default', 20),
   );
 
+  $reflect_hierarchy = variable_get('apachesolr_facet_reflect_hierarchy', array());
+  $form['apachesolr_facet_reflect_hierarchy'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Links reflect hierarchy'),
+    '#description' => t('Facet will be sorted hierarchically if it bases on a hierarchical taxonomy vocabulary.'),
+    '#default_value' => !empty($reflect_hierarchy[$module][$delta]),
+  );
+
   return $form;
 }
 
@@ -752,6 +760,9 @@
   $initial = variable_get('apachesolr_facet_query_initial_limits', array());
   $initial[$module][$delta] = (int)$edit['apachesolr_facet_query_initial_limit'];
   variable_set('apachesolr_facet_query_initial_limits', $initial);
+  $reflect_hierarchy = variable_get('apachesolr_facet_reflect_hierarchy', array());
+  $reflect_hierarchy[$module][$delta] = $edit['apachesolr_facet_reflect_hierarchy'];
+  variable_set('apachesolr_facet_reflect_hierarchy', $reflect_hierarchy);
 }
 
 /**
@@ -969,6 +980,9 @@
     'apachesolr_facet_item' => array(
       'arguments' => array('name' => NULL, 'count' => NULL, 'path' => NULL, 'querystring' => '', 'active' => FALSE, 'unclick_link' => NULL, 'num_found' => NULL),
     ),
+    'apachesolr_facet_item_indent' => array(
+      'arguments' => array('indent' => 0),
+    ),
     'apachesolr_unclick_link' => array(
       'arguments' => array('url' => NULL, 'querystring' => ''),
     ),
@@ -984,16 +998,24 @@
   );
 }
 
-function theme_apachesolr_facet_item($name, $count, $path, $querystring = '', $active = FALSE, $unclick_link = NULL, $num_found = NULL) {
+function theme_apachesolr_facet_item($name, $count, $path, $querystring = '', $active = FALSE, $unclick_link = NULL, $num_found = NULL, $indent = 0) {
   $attributes = array();
   if ($active) {
     $attributes['class'] = 'active';
   }
+  $link = '';
   if ($unclick_link) {
-    return $unclick_link . ' '. check_plain($name);
+    $link = $unclick_link . ' '. check_plain($name);
   }
   else {
-    return apachesolr_l($name ." ($count)",  $path, array('attributes' => $attributes, 'query' => $querystring));
+    $link = apachesolr_l($name ." ($count)",  $path, array('attributes' => $attributes, 'query' => $querystring));
+  }
+  return theme('apachesolr_facet_item_indent', $indent).$link;
+}
+
+function theme_apachesolr_facet_item_indent($indent = 0) {
+  if ($indent > 0) {
+    return str_repeat('&nbsp;', $indent).'∟';
   }
 }
 
Index: apachesolr_search.module
===================================================================
--- apachesolr_search.module	(revision 23274)
+++ apachesolr_search.module	(working copy)
@@ -358,7 +358,6 @@
           return;
         }
         $query = apachesolr_current_query();
-
         $facets = apachesolr_get_enabled_facets('apachesolr_search');
         if (empty($facets[$delta]) && ($delta != 'currentsearch')) {
           return;
@@ -372,46 +371,75 @@
         if ((strpos($delta, 'im_vid_') === 0) && module_exists('taxonomy')) {
 
           if (is_object($response->facet_counts->facet_fields->$delta)) {
-            $contains_active = FALSE;
-            $terms = array();
+            $vid = substr($delta, 7);
+            if (is_numeric($vid)) {
+              $vocab = taxonomy_vocabulary_load($vid);
+              $terms = array();
 
-            foreach ($response->facet_counts->facet_fields->$delta as $tid => $count) {
-              $unclick_link = '';
-              unset($active);
-              $term = taxonomy_get_term($tid);
-              $new_query = clone $query;
-              if ($active = $query->has_field('tid', $tid)) {
-                $contains_active = TRUE;
-                $new_query->remove_field('tid', $term->tid);
-                $path = 'search/' . arg(1) . '/' . $new_query->get_query_basic();
-                $querystring = $new_query->get_url_querystring();
-                $unclick_link = theme('apachesolr_unclick_link', $path, $querystring);
-              }
-              else {
-                $new_query->add_field('tid', $term->tid);
-                $path = 'search/' . arg(1) . '/' . $new_query->get_query_basic();
-                $querystring = $new_query->get_url_querystring();
-              }
-              $countsort = $count == 0 ? '' : 1 / $count;
-              // if numdocs == 1 and !active, don't add.
-              if ($response->numFound == 1 && !$active) {
-                // skip
+              $reflect_hierarchy = variable_get('apachesolr_facet_reflect_hierarchy', array());
+              $reflect_hierarchy = $reflect_hierarchy['apachesolr_search'][$delta];
+
+              foreach ($response->facet_counts->facet_fields->$delta as $tid => $count) {
+                $unclick_link = '';
+                unset($active);
+
+                $parents = array();
+                if ($reflect_hierarchy) {
+                  $parents = taxonomy_get_parents_all($tid);
+                  if (!empty($parents[1]) && !$query->has_field('tid', $parents[1]->tid)) {
+                    continue;
+                  }
+                }
+                else {
+                  $parents[] = taxonomy_get_term($tid);
+                }
+
+                $new_query = clone $query;
+
+                if ($active = $query->has_field('tid', $tid)) {
+                  $new_query->remove_field('tid', $tid);
+                  if ($reflect_hierarchy) {
+                    $childs = taxonomy_get_tree($vid, $tid);
+                    foreach ($childs as $child) {
+                      $new_query->remove_field('tid', $child->tid);
+                    }
+                  }
+                  $path = 'search/' . arg(1) . '/' . $new_query->get_query_basic();
+                  $querystring = $new_query->get_url_querystring();
+                  $unclick_link = theme('apachesolr_unclick_link', $path, $querystring);
+                }
+                else {
+                  $new_query->add_field('tid', $tid);
+                  $path = 'search/' . arg(1) . '/' . $new_query->get_query_basic();
+                  $querystring = $new_query->get_url_querystring();
+                }
+                // if numdocs == 1 and !active, don't add.
+                if ($response->numFound == 1 && !$active) {
+                  // skip
+                }
+                else {
+                  $sort_key = '';
+                  $term = NULL;
+                  foreach (array_reverse($parents) as $term) {
+                    $count = $response->facet_counts->facet_fields->$delta->{$term->tid};
+                    $countsort = $count == 0 ? '' : 1 / $count;
+                    $countsort = $active ? $countsort : 1 + $countsort;
+                    $sort_key .= $countsort.$term->name;
+                  }
+                  $terms[$term->vid][$sort_key] = theme('apachesolr_facet_item', $term->name, $count, $path, $querystring, $active, $unclick_link, $response->numFound, count($parents) - 1);
+                }
               }
-              else {
-                $terms[$term->vid][$active ? $countsort . $term->name : 1 + $countsort . $term->name] = theme('apachesolr_facet_item', $term->name, $count, $path, $querystring, $active, $unclick_link, $response->numFound);
+
+              if (is_array($terms) && isset($terms[$vid]) && is_array($terms[$vid])) {
+                ksort($terms[$vid]);
+                $limit = isset($initial_limits['apachesolr_search'][$delta]) ? $initial_limits['apachesolr_search'][$delta] : $limit_default;
+                return array(
+                  'subject' => t('Filter by @name', array('@name' => $vocab->name)),
+                  'content' => theme('apachesolr_facet_list', $terms[$vid], $limit),
+                );
               }
             }
           }
-          $vid = substr($delta, 7);
-          $vocab = taxonomy_vocabulary_load($vid);
-          if (is_numeric($vid) && is_array($terms) && isset($terms[$vid]) && is_array($terms[$vid])) {
-            ksort($terms[$vid]);
-            $limit = isset($initial_limits['apachesolr_search'][$delta]) ? $initial_limits['apachesolr_search'][$delta] : $limit_default;
-            return array(
-              'subject' => t('Filter by @name', array('@name' => $vocab->name)),
-              'content' => theme('apachesolr_facet_list', $terms[$vid], $limit),
-            );
-          }
           return;
         }
 
