1

Using Drupal 6: I need to show child terms for the currently viewd taxonomy term in a block. I finally stumbled on a piece of code that does exactly what I want. Original code from here

As per the instructions I've added the following to my template.php

function themename_child_terms($vid = 1) {
  if(arg(0) == 'taxonomy' && arg(1) == 'term') {   
    $children = taxonomy_get_children(arg(2), $vid);
      if(!$children) {
        $custom_parent = taxonomy_get_parents(arg(2));
          $parent_tree = array();
          foreach ($custom_parent as $custom_child => $key) {
            $parent_tree = taxonomy_get_tree($vid, $key->tid);
          }
          $children = $parent_tree;
      }

    $output = '<ul>';
    foreach ($children as $term) {
      $output .= '<li>';
      $output .= l($term->name, 'taxonomy/term/' . $term->tid);
      $output .= '</li>';
    }
    $output .= '</ul>';

    return $output;
  }
}

I've then created a block and added :

<?php // $vid is the vocabulary id.
    print themename_child_terms($vid = 1);
?>

This shows the child terms of the current term perfectly. However, it shows ALL terms that exist under the parent term, even if there are no nodes tagged with that term.

e.g. viewing the page with all items in 'Term 1', I get

child 1 child 2 child 3

correctly listed in the block. But, if there are no pieces of content tagged with 'child 3' for example, it's still showing up that term in the block. This isn't very useful as it links to an empty term page.

How would I modify the code to only show children that actually have nodes associated with them. So if there are no children tagged 'Child 3', then that term would not show up..

I've found this function in taxonomy.module Can I use this function to do what I want?

/**
 * Count the number of published nodes classified by a term.
 *
 * @param $tid
 *   The term's ID
 *
 * @param $type
 *   The $node->type. If given, taxonomy_term_count_nodes only counts
 *   nodes of $type that are classified with the term $tid.
 *
 * @return int
 *   An integer representing a number of nodes.
 *   Results are statically cached.
 */
function taxonomy_term_count_nodes($tid, $type = 0) {
  static $count;

  if (!isset($count[$type])) {
    // $type == 0 always evaluates TRUE if $type is a string
    if (is_numeric($type)) {
      $result = db_query(db_rewrite_sql('SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.status = 1 GROUP BY t.tid'));
    }
    else {
      $result = db_query(db_rewrite_sql("SELECT t.tid, COUNT(n.nid) AS c FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.status = 1 AND n.type = '%s' GROUP BY t.tid"), $type);
    }
    $count[$type] = array();
    while ($term = db_fetch_object($result)) {
      $count[$type][$term->tid] = $term->c;
    }
  }
  $children_count = 0;
  foreach (_taxonomy_term_children($tid) as $c) {
    $children_count += taxonomy_term_count_nodes($c, $type);
  }
  return $children_count + (isset($count[$type][$tid]) ? $count[$type][$tid] : 0);
}

Thank you kindly for any solutions.

Nick

1 Answer 1

0

Hmm... I'd try something like this:

Change this part of your code:

foreach ($children as $term) {
  $output .= '<li>';
  $output .= l($term->name, 'taxonomy/term/' . $term->tid);
  $output .= '</li>';
}

to something like this:

// Avoid unnecessary "Invalid foreach" errors showing up in the log:
if (!empty($children)) {
  // If not empty, run the foreach loop:
  foreach ($children as $term) {
    // Then check to see if any nodes exist for that term id:
    $number_of_nodes = taxonomy_term_count_nodes($term->tid);
    // If there ARE nodes...
    if ($number_of_nodes > 0) {
      // ... then add them to the output:
      $output .= '<li>';
      $output .= l($term->name, 'taxonomy/term/' . $term->tid);
      $output .= '</li>';
    }
  }
}

Hope that helps... :)

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.