Index: apachesolr_search.module
===================================================================
--- apachesolr_search.module	(revision 19897)
+++ apachesolr_search.module	(revision 19898)
@@ -1,5 +1,5 @@
 <?php
-// $Id: apachesolr_search.module,v 1.1.2.6.2.131 2009/12/27 16:47:37 pwolanin Exp $
+// $Id: apachesolr_search.module,v 1.1.2.6.2.156 2010/08/11 21:43:16 pwolanin Exp $
 
 /**
  * @file
@@ -19,7 +19,7 @@
       $remaining = 0;
       $total = 0;
       // Collect the stats
-      $status = module_invoke('apachesolr_search', 'search', 'status');
+      $status = apachesolr_index_status('apachesolr_search');
       $remaining += $status['remaining'];
       $total += $status['total'];
 
@@ -141,42 +141,48 @@
  * Re-implementation of search_view().
  */
 function apachesolr_search_view($type = NULL) {
-  // Search form submits with POST but redirects to GET.
+  if (empty($type)) {
+    // Note: search/X can not be a default tab because it would take on the
+    // path of its parent (search). It would prevent remembering keywords when
+    // switching tabs. This is why we drupal_goto to it from the parent instead.
+    drupal_goto('search/apachesolr_search');
+  }
+  $keys = trim(search_get_keys());
+  // Construct the search form.  If the user submits POST data, this will
+  // redirect to a GET request before the search actually runs.
+  if (isset($_POST['form_id']) && $_POST['form_id'] == 'search_form') {
+    $form = drupal_get_form('search_form', NULL, $keys, $type);
+  }
+  // We did not redirect, so run the search if needed.
   $results = '';
-  if (!isset($_POST['form_id'])) {
-    if (empty($type)) {
-      // Note: search/X can not be a default tab because it would take on the
-      // path of its parent (search). It would prevent remembering keywords when
-      // switching tabs. This is why we drupal_goto to it from the parent instead.
-      drupal_goto('search/apachesolr_search');
+  $filters = '';
+  if (isset($_GET['filters'])) {
+    $filters = trim($_GET['filters']);
+  }
+  // Only perform search if there is non-whitespace search term or filters:
+  if ($keys || $filters) {
+    // Log the search keys:
+    $log = $keys;
+    if ($filters) {
+      $log .= 'filters='. $filters;
     }
-    $keys = trim(search_get_keys());
-    $filters = '';
-    if ($type == 'apachesolr_search' && isset($_GET['filters'])) {
-      $filters = trim($_GET['filters']);
-    }
-    // Only perform search if there is non-whitespace search term or filters:
-    if ($keys || $filters) {
-      // Log the search keys:
-      $log = $keys;
-      if ($filters) {
-        $log .= 'filters='. $filters;
-      }
-      watchdog('search', '%keys (@type).', array('%keys' => $log, '@type' => t('Search')), WATCHDOG_NOTICE, l(t('results'), 'search/'. $type .'/'. $keys));
+    watchdog('search', '%keys (@type).', array('%keys' => $log, '@type' => t('Search')), WATCHDOG_NOTICE, l(t('results'), 'search/'. $type .'/'. $keys));
 
-      // Collect the search results:
-      $results = search_data($keys, $type);
+    // Collect the search results:
+    $results = search_data($keys, $type);
 
-      if ($results) {
-        $results = theme('box', t('Search results'), $results);
-      }
-      else {
-        $results = theme('box', t('Your search yielded no results'), variable_get('apachesolr_search_noresults', apachesolr_search_noresults()));
-      }
+    if ($results) {
+      $results = theme('box', t('Search results'), $results);
     }
+    else {
+      $results = theme('box', t('Your search yielded no results'), variable_get('apachesolr_search_noresults', apachesolr_search_noresults()));
+    }
   }
-  // Construct the search form.
-  return drupal_get_form('search_form', NULL, $keys, $type) . $results;
+  if (empty($form)) {
+    // The form may be altered based on the query that was run.
+    $form = drupal_get_form('search_form', NULL, $keys, $type);
+  }
+  return $form . $results;
 }
 
 function apachesolr_search_noresults() {
@@ -191,19 +197,26 @@
 /**
  * Execute a search results based on keyword, filter, and sort strings.
  *
+ * @param $keys
+ * @param $filterstring
+ * @param $solrsort
+ * @param $base_path
+ *   For constructing filter and sort links. Leave empty unless the links need to point somewhere
+ *   other than the base path of the current request.
+ * @param integer $page
+ *   For pagination.
+ * @param $caller
+ * @return Apache_Solr_Response $response
  * @throws Exception
  */
-function apachesolr_search_execute($keys, $filters, $solrsort, $base_path = '', $page = 0, $caller = 'apachesolr_search') {
-
+function apachesolr_search_execute($keys, $filterstring, $solrsort, $base_path = '', $page = 0, $caller = 'apachesolr_search') {
   $params = array();
   // This is the object that knows about the query coming from the user.
-  $query = apachesolr_drupal_query($keys, $filters, $solrsort, $base_path);
+  $query = apachesolr_drupal_query($keys, $filterstring, $solrsort, $base_path);
   if (empty($query)) {
     throw new Exception(t('Could not construct a Solr query in function apachesolr_search_search()'));
   }
 
-  // This is the object that does the communication with the solr server.
-  $solr = apachesolr_get_solr();
   $params += apachesolr_search_basic_params($query);
   if ($keys) {
     $params += apachesolr_search_highlighting_params($query);
@@ -213,46 +226,19 @@
     // No highlighting, use the teaser as a snippet.
     $params['fl'] .= ',teaser';
   }
+  if (module_exists('upload')) {
+    $params['fl'] .= ',is_upload_count';
+  }
   apachesolr_search_add_facet_params($params, $query);
-  apachesolr_search_add_boost_params($params, $query, $solr);
+  apachesolr_search_add_boost_params($params, $query, apachesolr_get_solr());
 
-  // Allow modules to alter the query prior to statically caching it.
-  // This can e.g. be used to add available sorts.
-  foreach (module_implements('apachesolr_prepare_query') as $module) {
-    $function_name = $module . '_apachesolr_prepare_query';
-    $function_name($query, $params, $caller);
-  }
-
-  // Cache the built query. Since all the built queries go through
-  // this process, all the hook_invocations will happen later
-  $current_query = apachesolr_current_query($query);
-
-  // This hook allows modules to modify the query and params objects.
-  apachesolr_modify_query($query, $params, $caller);
-  $params['start'] = $page * $params['rows'];
-
-  if (!$query) {
-    return array();
-  }
-
-  if (('' == $keys) && isset($params['fq'])) {
-    // Move the fq params to the q.alt for better performance.
-    $params['q.alt'] = implode(' ', $params['fq']);
-    unset($params['fq']);
-  }
-
-  // We must run htmlspecialchars() here since converted entities are in the index.
-  // and thus bare entities &, > or < won't match.
-  $response = $solr->search(htmlspecialchars($query->get_query_basic(), ENT_NOQUOTES, 'UTF-8'), $params['start'], $params['rows'], $params);
-  // The response is cached so that it is accessible to the blocks and anything
-  // else that needs it beyond the initial search.
-  apachesolr_static_response_cache($response);
+  list($final_query, $response) = apachesolr_do_query($caller, $query, $params, $page);
   apachesolr_has_searched(TRUE);
   // Add search terms and filters onto the breadcrumb.
-  // We use $current_query to avoid exposing, for example, nodeaccess
+  // We use the original $query to avoid exposing, for example, nodeaccess
   // filters in the breadcrumb.
-  drupal_set_breadcrumb(array_merge(menu_get_active_breadcrumb(), $current_query->get_breadcrumb()));
-  return apachesolr_process_response($response, $query, $params);
+  drupal_set_breadcrumb(array_merge(menu_get_active_breadcrumb(), $query->get_breadcrumb()));
+  return apachesolr_process_response($response, $final_query, $params);
 }
 
 function apachesolr_search_basic_params($query) {
@@ -302,7 +288,7 @@
       // When modules are disabled their facet settings may remain.
       continue;
     }
-    foreach($module_facets as $delta => $facet_field) {
+    foreach ($module_facets as $delta => $facet_field) {
       // TODO: generalize handling of date and range facets.
       if ($module == 'apachesolr_search' && ($facet_field == 'created' || $facet_field == 'changed')) {
         list($start, $end, $gap) = apachesolr_search_date_range($query, $facet_field);
@@ -404,7 +390,7 @@
 function apachesolr_process_response($response, $query, $params) {
   $results = array();
   // We default to getting snippets from the body.
-  $hl_fl = is_null($params['hl.fl']) ? 'body' : $params['hl.fl'];
+  $hl_fl = isset($params['hl.fl']) ? $params['hl.fl'] : 'body';
   $total = $response->response->numFound;
   apachesolr_pager_init($total, $params['rows']);
   if ($total > 0) {
@@ -431,6 +417,15 @@
       drupal_alter('apachesolr_search_result', $doc);
       // Copy code from comment_nodeapi().
       $extra[] = format_plural($doc->comment_count, '1 comment', '@count comments');
+      // Copy code from upload_nodeapi()
+      if (isset($doc->is_upload_count)) {
+        $extra[] = format_plural($doc->is_upload_count, '1 attachment', '@count attachments');
+      }
+      $fields = array();
+      foreach ($doc->getFieldNames() as $field_name) {
+        $fields[$field_name] = $doc->$field_name;
+      }
+
       $results[] = array(
         'link' => url($doc->path, array('absolute' => TRUE)),
         'type' => apachesolr_search_get_type($doc->type),
@@ -443,6 +438,7 @@
         'extra' => $extra,
         'score' => $doc->score,
         'snippet' => $snippet,
+        'fields' => $fields,
       );
     }
 
@@ -474,7 +470,9 @@
   // gap to use.  This callback assumes $delta is 'changed' or 'created'.
   if (!isset($start_iso)) {
     $start_iso = apachesolr_date_iso(db_result(db_query("SELECT MIN($facet_field) FROM {node} WHERE status = 1")));
-    $end_iso = apachesolr_date_iso(db_result(db_query("SELECT MAX($facet_field) FROM {node} WHERE status = 1")));
+    // Subtract one second, so that this range's $end_iso is not equal to the
+    // next range's $start_iso.
+    $end_iso = apachesolr_date_iso(db_result(db_query("SELECT MAX($facet_field) FROM {node} WHERE status = 1")) - 1);
     $gap = apachesolr_date_determine_gap($start_iso, $end_iso);
   }
   // Return a query range from the beginning of a gap period to the beginning
@@ -541,7 +539,7 @@
       // $delta can only be 32 chars, and the CCK field name may be this
       // long also, so we cannot add anything to it.
       $facets[$field['field_name']] = array(
-        'info' => t('Apache Solr Search: Filter by @field', array('@field' => $field['label'])),
+        'info' => t('Apache Solr Search: Filter by @field', array('@field' => $field['widget']['label'])),
         'facet_field' => apachesolr_index_key($field),
       );
     }
@@ -562,7 +560,7 @@
       $blocks = array();
       foreach ($enabled_facets as $delta => $facet_field) {
         if (isset($facets[$delta])) {
-          $blocks[$delta] = $facets[$delta] + array('cache' => BLOCK_CACHE_PER_PAGE,);
+          $blocks[$delta] = $facets[$delta] + array('cache' => BLOCK_CACHE_PER_PAGE);
         }
       }
       $blocks['currentsearch'] = array(
@@ -585,12 +583,8 @@
           return;
         }
 
-        // Get information needed by the taxonomy blocks about limits.
-        $initial_limits = variable_get('apachesolr_facet_query_initial_limits', array());
-        $limit_default = variable_get('apachesolr_facet_query_initial_limit_default', 10);
-
         // Handle taxonomy vocabulary facets
-        if ((strpos($delta, 'im_vid_') === 0)) {
+        if (strpos($delta, 'im_vid_') === 0) {
           return apachesolr_search_taxonomy_facet_block($response, $query, $delta);
         }
 
@@ -601,7 +595,7 @@
             return apachesolr_facet_block($response, $query, 'apachesolr_search', $delta, $delta, t('Filter by book'), 'apachesolr_search_get_book');
           case 'language':
             return apachesolr_facet_block($response, $query, 'apachesolr_search', $delta, $delta, t('Filter by language'), 'apachesolr_search_language_name');
-           case 'uid':
+          case 'uid':
             return apachesolr_facet_block($response, $query, 'apachesolr_search', $delta, $delta, t('Filter by author'), 'apachesolr_search_get_username');
           case 'type':
             return apachesolr_facet_block($response, $query, 'apachesolr_search', $delta, $delta, t('Filter by type'), 'apachesolr_search_get_type');
@@ -611,14 +605,14 @@
             return apachesolr_date_facet_block($response, $query, 'apachesolr_search', $delta, $delta, t('Filter by post date'));
 
           default:
-           if ($fields = apachesolr_cck_fields()) {
-            foreach ($fields as $name => $field) {
-              if ($field['field_name'] == $delta) {
-                $index_key = apachesolr_index_key($field);
-                return apachesolr_facet_block($response, $query, 'apachesolr_search', $delta, $index_key, t('Filter by @field', array('@field' => $field['label'])));
+            if ($fields = apachesolr_cck_fields()) {
+              foreach ($fields as $name => $field) {
+                if ($field['field_name'] == $delta) {
+                  $index_key = apachesolr_index_key($field);
+                  return apachesolr_facet_block($response, $query, 'apachesolr_search', $delta, $index_key, t('Filter by @field', array('@field' => $field['label'])));
+                }
               }
             }
-          }
         }
         break;
       }
@@ -704,6 +698,7 @@
           }
         }
       }
+
       // Check for the case like starting on a taxonomy/term/$tid page
       // where parents are not marked as active.
       // @todo: can we make this more efficient?
@@ -729,7 +724,8 @@
     $items = apachesolr_search_nested_facet_items($query, $facets, $response->response->numFound);
     // Process all terms into an item list
     if ($items && ($response->response->numFound > 1 || $contains_active)) {
-      $limit = isset($initial_limits['apachesolr_search'][$delta]) ? $initial_limits['apachesolr_search'][$delta] : $limit_default;
+      $initial_limits = variable_get('apachesolr_facet_query_initial_limits', array());
+      $limit = isset($initial_limits['apachesolr_search'][$delta]) ? $initial_limits['apachesolr_search'][$delta] : variable_get('apachesolr_facet_query_initial_limit_default', 10);
       return array(
         'subject' => t('Filter by @name', array('@name' => $vocab->name)),
         'content' => theme('apachesolr_facet_list', $items, $limit),
@@ -739,34 +735,6 @@
 }
 
 /**
- * Callback function for the 'Filter by book' facet block.
- */
-function apachesolr_search_get_book($facet, &$options) {
-  if (is_numeric($facet)) {
-    return db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $facet));
-  }
-  else {
-    $options['html'] = TRUE;
-    return theme('placeholder', t('Not in any book'));
-  }
-}
-
-function apachesolr_search_language_name($lang) {
-  static $list = NULL;
-
-  if (!isset($list)) {
-    if (function_exists('locale_language_list')) {
-      $list = locale_language_list();
-    }
-    $list['und'] = t('Language neutral');
-    // TODO - remove this line - only present for rc4 update.
-    $list['zxx'] = $list['und'];
-  }
-  return ($lang && isset($list[$lang])) ? $list[$lang] : $lang;
-}
-
-
-/**
  * Recursive function that returns a nested array of facet values for use with
  * theme_item_list().
  *
@@ -784,16 +752,17 @@
 function apachesolr_search_nested_facet_items($query, $facets, $num_found, $sort = TRUE) {
 
   $items = array();
-  foreach($facets as $field) {
+  foreach ($facets as $field) {
     $facet_text = theme('apachesolr_breadcrumb_' . $field['#name'], $field['#value'], $field['#exclude']);
     if (!$facet_text) {
       $facet_text = $field['#value'];
     }
+
+    $active = !empty($field['#active']);
+
     $link = array();
     $new_query = clone $query;
-    if (!empty($field['#active'])) {
-      // '*' sorts before all numbers.
-      $sortpre = '*';
+    if ($active) {
       foreach (apachesolr_search_collect_children($field) as $child) {
         $new_query->remove_filter($child['#name'], $child['#value']);
       }
@@ -801,11 +770,19 @@
       $link['data'] = theme('apachesolr_unclick_link', $facet_text, $new_query->get_path(), $options);
     }
     else {
-      $sortpre = 1000000 - $field['#count'];
       $new_query->add_filter($field['#name'], $field['#value']);
       $options = array('query' => $new_query->get_url_queryvalues());
       $link['data'] = theme('apachesolr_facet_link', $facet_text, $new_query->get_path(), $options, $field['#count'], FALSE, $num_found);
     }
+
+    if ($active) {
+      // '*' sorts before all numbers.
+      $sortpre = '*';
+    }
+    else {
+      $sortpre = 1000000 - $field['#count'];
+    }
+
     // We don't display children unless the parent is clicked.
     if (!empty($field['#children']) && $field['#active'] == TRUE) {
       $link['children'] = apachesolr_search_nested_facet_items($query, $field['#children'], $num_found, $sort);
@@ -817,13 +794,38 @@
     $items[$sortpre . '*' . $facet_text . $field['#name'] . $field['#value']] = $link;
   }
 
-  if ($sort) {
+  if ($sort && $items) {
     ksort($items);
   }
   return array_values($items);
 }
 
 /**
+ * Callback function for the 'Filter by book' facet block.
+ */
+function apachesolr_search_get_book($facet, &$options) {
+  if (is_numeric($facet)) {
+    return db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $facet));
+  }
+  else {
+    $options['html'] = TRUE;
+    return theme('placeholder', t('Not in any book'));
+  }
+}
+
+function apachesolr_search_language_name($lang) {
+  static $list = NULL;
+
+  if (!isset($list)) {
+    if (function_exists('locale_language_list')) {
+      $list = locale_language_list();
+    }
+    $list['und'] = t('Language neutral');
+  }
+  return ($lang && isset($list[$lang])) ? $list[$lang] : $lang;
+}
+
+/**
  * Callback function for the 'Filter by name' facet block.
  */
 function apachesolr_search_get_username($facet) {
@@ -839,7 +841,8 @@
 function apachesolr_search_get_type($facet) {
   $type = node_get_types('name', $facet);
   // A disabled or missing node type returns FALSE.
-  return ($type === FALSE) ? $facet : $type;
+  $name = ($type === FALSE) ? $facet : $type;
+  return apachesolr_tt("nodetype:type:$facet:name", $name);
 }
 
 /**
@@ -879,8 +882,21 @@
 
 /**
  * Process a block search form submission.
+ *
+ * @see search_box_form_submit()
  */
 function apachesolr_search_search_box_form_submit($form, &$form_state) {
+  // The search form relies on control of the redirect destination for its
+  // functionality, so we override any static destination set in the request,
+  // for example by drupal_access_denied() or drupal_not_found()
+  // (see http://drupal.org/node/292565).
+  if (isset($_REQUEST['destination'])) {
+    unset($_REQUEST['destination']);
+  }
+  if (isset($_REQUEST['edit']['destination'])) {
+    unset($_REQUEST['edit']['destination']);
+  }
+
   $form_id = $form['form_id']['#value'];
   $keys = $form_state['values'][$form_id];
   // Handle Apache webserver clean URL quirks.
@@ -912,11 +928,14 @@
     $form['basic']['apachesolr_search']['#tree'] = TRUE;
     $form['basic']['apachesolr_search']['queryvalues'] = array(
       '#type' => 'hidden',
-      '#default_value' => serialize($queryvalues),
+      // We use JSON encoding instead of PHP serialize, since otherwise we be
+      // at risk of user input being injected into the hidden string and
+      // unserialized.
+      '#default_value' => json_encode($queryvalues),
     );
     $form['basic']['apachesolr_search']['get'] = array(
       '#type' => 'hidden',
-      '#default_value' => serialize(array_diff_key($_GET, array('q' => 1, 'page' => 1, 'filters' => 1, 'solrsort' => 1, 'retain-filters' => 1))),
+      '#default_value' => json_encode(array_diff_key($_GET, array('q' => 1, 'page' => 1, 'filters' => 1, 'solrsort' => 1, 'retain-filters' => 1))),
     );
     if ($queryvalues || isset($form_state['post']['apachesolr_search']['retain-filters'])) {
       $form['basic']['apachesolr_search']['retain-filters'] = array(
@@ -927,28 +946,29 @@
     }
 
     if (variable_get('apachesolr_search_spellcheck', FALSE) && $apachesolr_has_searched && ($response = apachesolr_static_response_cache())) {
-      //Get spellchecker suggestions into an array.
-      $suggestions = get_object_vars($response->spellcheck->suggestions);
+      // Get spellchecker suggestions into an array.
+      if (isset($response->spellcheck->suggestions) && $response->spellcheck->suggestions) {
+        $suggestions = get_object_vars($response->spellcheck->suggestions);
+        if ($suggestions) {
+          // Get the original query and replace words.
+          $query = apachesolr_current_query();
 
-      if ($suggestions) {
-        //Get the original query and replace words.
-        $query = apachesolr_current_query();
+          foreach ($suggestions as $word => $value) {
+            $replacements[$word] = $value->suggestion[0];
+          }
+          $new_keywords = strtr($query->get_query_basic(), $replacements);
 
-        foreach($suggestions as $word => $value) {
-          $replacements[$word] = $value->suggestion[0];
+          // Show only if suggestion is different than current query.
+          if ($query->get_query_basic() != $new_keywords) {
+            $form['basic']['suggestion'] = array(
+              '#prefix' => '<div class="spelling-suggestions">',
+              '#suffix' => '</div>',
+              '#type' => 'item',
+              '#title' => t('Did you mean'),
+              '#value' => l($new_keywords, $query->get_path($new_keywords)),
+            );
+          }
         }
-        $new_keywords = strtr($query->get_query_basic(), $replacements);
-
-        // Show only if suggestion is different than current query.
-        if ($query->get_query_basic() != $new_keywords) {
-          $form['basic']['suggestion'] = array(
-            '#prefix' => '<div class="spelling-suggestions">',
-            '#suffix' => '</div>',
-            '#type' => 'item',
-            '#title' => t('Did you mean'),
-            '#value' => l($new_keywords, $query->get_path($new_keywords)),
-          );
-        }
       }
     }
   }
@@ -966,8 +986,8 @@
   if (variable_get('clean_url', '0')) {
     $keys = str_replace('+', '%2B', $keys);
   }
-  $get = unserialize($fv['apachesolr_search']['get']);
-  $queryvalues = unserialize($fv['apachesolr_search']['queryvalues']);
+  $get = json_decode($fv['apachesolr_search']['get'], TRUE);
+  $queryvalues = json_decode($fv['apachesolr_search']['queryvalues'], TRUE);
   if (!empty($fv['apachesolr_search']['retain-filters']) && $queryvalues) {
     $get = $queryvalues + $get;
     $get['retain-filters'] = '1';
@@ -1096,6 +1116,9 @@
   return apachesolr_search_language_name($lang);
 }
 
+/**
+ * Proxy theme function for 'created' and 'changed' date fields.
+ */
 function theme_apachesolr_breadcrumb_date_range($range) {
   if (preg_match('@[\[\{](\S+) TO (\S+)[\]\}]@', $range, $match)) {
     return apachesolr_date_format_range($match[1], $match[2]);
@@ -1139,7 +1162,8 @@
  * Return the human readable text for a content type.
  */
 function theme_apachesolr_breadcrumb_type($type) {
-  return node_get_types('name', $type);
+  $name = node_get_types('name', $type);
+  return apachesolr_tt("nodetype:type:$type:name", $name);
 }
 
 /**
@@ -1173,12 +1197,12 @@
 }
 
 
-function apacehsolr_get_parent_terms($tids) {
+function apachesolr_get_parent_terms($tids) {
   // Find the starting tid terms and then all their parents.
   $parent_terms = array();
   $new_tids = $tids;
   do {
-    $result = db_query(db_rewrite_sql("SELECT t.tid, t.parent FROM {term_hierarchy} t WHERE t.tid IN (". db_placeholders($new_tids) .")",'t', 'tid'), $new_tids);
+    $result = db_query(db_rewrite_sql("SELECT t.tid, t.parent FROM {term_hierarchy} t WHERE t.tid IN (". db_placeholders($new_tids) .")", 't', 'tid'), $new_tids);
     $new_tids = array();
     while ($term = db_fetch_object($result)) {
       $parent_terms[$term->tid] = $term;
@@ -1201,6 +1225,7 @@
 function apachesolr_search_currentsearch_block($response, $query) {
   $fields = $query->get_filters();
   $links = array();
+  $facets = array();
 
   // If current search has keys, offer current search without them
   if ($keys = $query->get_query_basic()) {
@@ -1209,7 +1234,8 @@
   // Find all taxonomy terms to be treated in a hierarchy.
   if (module_exists('taxonomy')) {
     $reflect_hierarchy = apachesolr_search_get_hierarchical_vocabularies();
-    foreach($fields as $index => $field) {
+    $facets = array();
+    foreach ($fields as $index => $field) {
       if ($field['#name'] && 'tid' == $field['#name']) {
         $term = taxonomy_get_term($field['#value']);
         if ($reflect_hierarchy[$term->vid]) {
@@ -1221,7 +1247,7 @@
     }
     if ($facets) {
       // Get all term hierarchy information.
-      $all_terms = apacehsolr_get_parent_terms(array_keys($facets));
+      $all_terms = apachesolr_get_parent_terms(array_keys($facets));
       foreach ($all_terms as $tid => $term) {
         if (!isset($facets[$tid])) {
           // This is a parent that is missing from the query.  E.g. we started
@@ -1246,7 +1272,7 @@
   }
 
   // We don't directly render any items with a parent.
-  foreach($fields as $index => $field) {
+  foreach ($fields as $index => $field) {
     $fields[$index]['#active'] = TRUE;
     if (!empty($fields[$index]['#parent']) || !$field['#name']) {
       // We will render it via its parent.
