Index: drupalorg_search/drupalorg_search.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drupalorg/drupalorg_search/drupalorg_search.module,v
retrieving revision 1.13
diff -u -r1.13 drupalorg_search.module
--- drupalorg_search/drupalorg_search.module	5 Feb 2010 18:18:16 -0000	1.13
+++ drupalorg_search/drupalorg_search.module	9 Apr 2010 22:53:59 -0000
@@ -84,13 +84,22 @@
  * Exclude the meta_type filter from faceting.
  */
 function drupalorg_search_apachesolr_modify_query(&$query, &$params) {
+  $tids = array();
+  $tid_query = apachesolr_drupal_query();
   // TODO: some pending improvements to Apachesolr may simplify this.
   foreach ($query->get_filters() as $filter) {
     if ($filter['#name'] == 'ss_meta_type') {
       $query->remove_filter($filter['#name'], $filter['#value']);
       $query->add_filter('{!tag=meta_type}' . $filter['#name'], $filter['#value']);
     }
+    if ($filter['#name'] == 'tid') {
+      $query->remove_filter($filter['#name'], $filter['#value']);
+      $tid_query->add_filter($filter['#name'], $filter['#value']);
+    }
   }
+
+  $query->add_subquery($tid_query, 'OR');
+
   if (isset($params['facet.field'])) {
     foreach ($params['facet.field'] as &$field) {
       if ($field == 'ss_meta_type') {
@@ -112,6 +121,11 @@
       'cache' => BLOCK_NO_CACHE,
     );
 
+    $blocks['meta_type_facets'] = array(
+      'info' => t('Drupalorg Search: Meta-Type Specific Facets'),
+      'cache' => BLOCK_NO_CACHE,
+    );
+
     // Add the facet blocks.
     $enabled_facets = apachesolr_get_enabled_facets('drupalorg_search');
     $facets = drupalorg_search_apachesolr_facets();
@@ -174,6 +188,140 @@
       }
     }
   }
+  else if ($op == 'view' && $delta == 'meta_type_facets' && arg(0) == 'search') {
+    $content = '';
+    $filter = NULL;
+    // if we've run a search, pull the ss_meta_type out of the search
+    if (apachesolr_has_searched() && ($response = apachesolr_static_response_cache()) && ($query = apachesolr_current_query())) {
+      $filters = $query->get_filters('ss_meta_type');
+      $filter = $filters[0]['#value'];
+    }
+    $content .= drupal_get_form('drupalorg_search_base_meta_facet_form', $filter);
+
+    // if $filter isn't present, it is - at best - a POST page, and otherwise
+    // a page that doesn't require the refinement box
+    if ($filter) {
+      return array(
+        'subject' => t('Refine your search'),
+        'content' => $content,
+      );
+    }
+  }
+}
+
+function drupalorg_search_base_meta_facet_form($form_state, $meta_type = NULL) {
+  $form = array();
+  // if we don't have a meta type (displayed query page), then
+  // pull it from the post (form submission)
+  $meta_type = !is_null($meta_type) ? $meta_type : (isset($form_state['post']['meta_type']) ? $form_state['post']['meta_type'] : '');
+
+  // pull filters from a meta-type-specific filter function
+  $func = 'drupalorg_search_' . $meta_type . '_meta_facet_form';
+  if (function_exists($func)) {
+    $form['meta_type'] = array(
+      '#type' => 'hidden',
+      '#value' => $meta_type,
+    );
+
+    $form['filters'] = $func();
+    $form['filters']['#tree'] = TRUE;
+
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Submit'),
+    );
+  }
+
+  return $form;
+}
+
+/**
+ * Take the submitted parameters, filter our anything else in that set of options
+ * that wasn't selected, and add in everything that was selected.
+ * Handles filter box form submissions for all meta-type facets.
+ */
+function drupalorg_search_base_meta_facet_form_submit(&$form, &$form_state) {
+  // Add a filter to the query for each checked box
+  $new_query = isset($_GET['filters']) ? $_GET['filters'] : '';
+
+  // we can't necessarily strip all tids, so strip only those
+  // related to our filter box
+  $filters = $form_state['values']['filters'];
+  $query_params = array();
+  foreach ($filters as $filter_options) {
+    foreach ($filter_options as $filter_key => $filter_value) {
+      $new_query = str_replace($filter_key, '', $new_query);
+      // if we want to filter on the value, add the value in
+      if ($filter_value !== 0) {
+        $query_params[] = $filter_value;
+      }
+    }
+  }
+  $new_query = trim($new_query) . ' ' . implode(' ', $query_params);
+
+  // Run the new query
+  $form_state['redirect'] = array('search/' . arg(1) . '/' . arg(2), 'filters=' . $new_query);
+}
+
+/**
+ * Generate the filter box for themes
+ */
+function drupalorg_search_theme_meta_facet_form() {
+  return drupalorg_search_project_meta_facet_form(DRUPALORG_THEME_TID);
+}
+
+/**
+ * Generate the filter box for modules
+ */
+function drupalorg_search_module_meta_facet_form() {
+  return drupalorg_search_project_meta_facet_form(DRUPALORG_MODULE_TID);
+}
+
+/**
+ * Generic function for generating checkbox lists for vocabularies related to the
+ * top-level project taxonomy terms
+ */
+function drupalorg_search_project_meta_facet_form($tid) {
+  $filters  = isset($_GET['filters']) ? $_GET['filters'] : '';
+  // pull relevant variables.
+  // TODO: there MUST be a better way to do this.
+  $result   = db_query("SELECT REPLACE(name, 'drupalorg_project_tid_', '' ) AS related_vid, value AS project_tid FROM {variable} WHERE name LIKE 'drupalorg_project_tid_%'");
+  while ($project = db_fetch_object($result)) {
+    // unserialize the related top-level taxonomy term from projects
+    $project->project_tid = unserialize($project->project_tid);
+
+    // if the vocabulary is related to the top-level term we're viewing
+    // build the filter options
+    if ($project->project_tid == $tid) {
+      $vocabulary = taxonomy_vocabulary_load($project->related_vid);
+      $tree       = taxonomy_get_tree($vocabulary->vid);
+      $options    = array();
+      $default    = '';
+
+      // build the option list per taxonomy term
+      if ($tree) {
+        foreach ($tree as $term) {
+          if (!in_array($term->tid, $exclude)) {
+            $options['tid:' . $term->tid] = $term->name;
+            if (strpos($filters, 'tid:' . $term->tid) !== FALSE) {
+              $default[] = 'tid:'. $term->tid;
+            }
+          }
+        }
+      }
+
+      // Generate a checkbox list for the vocabulary
+      // TODO: allow this to generate something other than checkboxes
+      $form['filter-' . $project->related_vid] = array(
+        '#type' => 'checkboxes',
+        '#title' => $vocabulary->name,
+        '#default_value' => $default,
+        '#options' => $options,
+      );
+
+    }
+  }
+  return $form;
 }
 
 /**
