While working on the magazine module I found that it would be very convenient to enhance the _taxonomy_node_select function so that the 'exclude' array could optionally be treated as an 'include' array. The following patch includes an additional optional flag called 'intersect' that causes the 'exclude' array to be treated as an 'include' array if the flag is true. The default value is false, ensuring that this function performs as expected for all existing programs. I've tested it on a few screens and it does what I need and doesn't appear to have any impact on preexisting invocations.

Note, because of it just doesn't make sense to have a parameter named 'exclude' that can be used to include items, I changed the name to a more generic 'filter'. Here's the code:


/*
 * Enhanced _taxonomy_term_select is designed optionally to exclude or include terms.
 * $title - title text of select element
 * $name - name of select element
 * $value - array of selected values
 * $vocabulary_id - used to get taxonomy_tree
 * $description - describes select purpose
 * $multiple - multi select or single select
 * $blank - default value for "none" selected
 * $filter - array of tids for terms to filter by
 * $intersect - 1 means filter is intersection (filter is an include list). 0 means filter is an exclude list
 */
function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $filter = array(), $intersect = 0) {
  $tree = taxonomy_get_tree($vocabulary_id);

  if ($blank) {
    $options[] = array("tid" => 0, "name" => $blank);
  }

  if ($tree) {
    foreach ($tree as $term) {
      if ($intersect && in_array($term->tid, $filter)) {
        $options[] = array("tid" => $term->tid, "name" => _taxonomy_depth($term->depth, '-').$term->name);
      }
      elseif (!$intersect && !in_array($term->tid, $filter)) {
        $options[] = array("tid" => $term->tid, "name" => _taxonomy_depth($term->depth, '-').$term->name);
      }
    }
    if (!$blank && !$value) {
      // required but without a predefined value, so set first as predefined
      $value = $tree[0]->tid;
    }
  }

  if (count($options) > 0) {
    foreach ($options as $option) {
      $select .= "<option value=\"". $option["tid"] ."\"". (is_array($value) ? (in_array($option["tid"], $value) ? " selected=\"selected\"" : "") : ($option["tid"] == $value ? " selected=\"selected\"" : "")) .">". check_form($option["name"]) ."</option>";
    }

    $size = min(12, count($options));

    return form_item($title, "<select name=\"edit[$name][]\"". ($multiple ? " multiple size=\"$size\"" : "") . ($extra ? " $extra" : "") .">$select</select>", $description);
  }
}

Comments

moshe weitzman’s picture

Why is this useful? Please explain and then move this back to patch status ... if possible, submit a proper patch as well.

moshe weitzman’s picture