Drupal 6: Filtering a view’s exposed filter options to show relevant nodes

Recently I was working on a project that had a view with an exposed filter for country (via location module) and the dropdown list by default showed the entire country list, which was very large. I decided to write a code snippet that would reduce the select options to show only the countries that have been assigned to the nodes.

In my sandbox I create a simple node type for “person” that used the location module to capture the user’s country. I then created a view to show the people’s names and countries, and added an exposed filter for country.

People and Countries View

Clicking on the exposed filter showed all of the available countries, which was a very large list.

Country dropdown

I added the following code to my module to alter the exposed filter form and reduce the country list. (Please note, an alternative approach would be to modify the views object, I wanted to show how this could be accomplished in hook_form_alter())

<?php
/**
 * Implements hook_form_alter()
 */
function MYMODULE_form_alter(&$form, $form_state, $form_id) {

  // define variables
  $view_name = 'people_places';
  $filer_name = 'country';

  // modify country drop down
  if ($form_id == 'views_exposed_form' && is_object($form_state['view']) && $form_state['view']->name==$view_name && is_array($form[$filer_name])) {

    // define SQL to fetch nodes that have countries
    $sql = "
      select distinct
        l.country
      from
        {node} n
      join
        {location_instance} li on li.nid = n.nid and li.vid = n.vid
      join
        {location} l on l.lid = li.lid
      where
       n.status = 1 and n.type = 'person'
    ";

    // fetch results
    $resource = db_query($sql, $tid);
    $countries = array();
    while($row = db_fetch_object($resource)) {
      $countries[] = $row->country;
    }

    // filter country list
    foreach($form[$filer_name]['#options'] as $key => $value) {

      // allow "All"
      if ($key == 'All') {
        continue;
      }

      elseif (!in_array($key, $countries)) {
        unset($form[$filer_name]['#options'][$key]);
      }

    }

  }
}
?>

Now the view only shows countries that match the resulting nodes.

Filtered exposed filter

Updated: