Print a hierarchical list of taxonomy vocabulary terms on a page

Estimated reading time of this article: 4 minutes

Do you want to print a hierarchical list of taxonomy terms with corresponding feeds in Drupal 7?

If so, then put the following code in a module:

<?php/** * Implements hook_menu(). */function YOUR_MODULE_menu() {  $items['termlisting'] = array(    'title' => 'Term listing',    'page callback' => '_YOUR_MODULE_kategorieliste',    'page arguments' => array('1'),    'access arguments' => array('access content'),    'type' => MENU_CALLBACK, // no automatic menu entry  );  return $items;}/** * Builds a nested list of taxonomy terms for a vocabulary. * Very simple, could be optimized. * Algorithm from http://drupal.org/node/223675#comment-900999 */function _YOUR_MODULE_vocabulary_tree($vid) {  $depth = 0;  $num_at_depth = 0;  $tree = taxonomy_get_tree($vid);  $markup = "<ul class=\"termlist\">\n<li class=\"clearfix\">";  foreach ($tree as $term) {    $diffdepth=0;    if ($term->depth > $depth) {      $markup .= "\n<ul>\n<li class=\"clearfix\">";      $depth = $term->depth;      $num_at_depth = 0;    }    if ($term->depth < $depth) {      $diffdepth= $depth -$term->depth;      while ($diffdepth > 0){        $markup .= "</li>\n</ul>\n";        $diffdepth--;      }      $depth = $term->depth;    }    if (($term->depth == $depth) && ($num_at_depth > 0)) {        $markup .= "</li>\n<li class=\"clearfix\">";      }    $markup .= _YOUR_MODULE_build_term_with_feed($term->name, array($term->tid));    $num_at_depth++;  }  $markup .= "</li>\n</ul>\n";  return $markup;}/** * Builds a page which prints hierarchically the kategory taxonomy terms. */function _YOUR_MODULE_kategorieliste($vid = 2) {  $markup = '<p>Introduction text</p>';  $markup .= _YOUR_MODULE_vocabulary_tree($vid);  $markup .= "<h2>Combinations</h2>\n";  $markup .= "<ul class=\"termlist\">\n";  $markup .= "<li>" . _YOUR_MODULE_build_term_with_feed('Terms X+Y', array(19, 20)) . "</li>\n";  $markup .= "<li>" . _YOUR_MODULE_build_term_with_feed('Terms X+Y+ ...', array(14, 15, 18, 19, 20, 21, 16, 17)) . "</li>\n";  $markup .= "</ul>\n";  $build = array();  $build['terms'] = array(    '#weight' => -5,    '#prefix' => '<div class="term-listing">',    '#markup' => $markup,    '#suffix' => '</div>',   );  return $build;}/** * Builds a link with parameter name with (count) and the corresponding feed. * @param $name *  Name of the link * @param $tids *  Array of tids * @return *  A link with parameter name with (count) and the corresponding feed. */function _YOUR_MODULE_build_term_with_feed($name, $tids) {   $count = db_query("SELECT COUNT(nid) FROM {taxonomy_index} WHERE tid IN (:tids) ", array(':tids' => implode(',', $tids)))->fetchField();  $markup = l($name . ' (' . $count . ')', 'taxonomy/term/'. implode('+', $tids), array('attributes' => (array('class' => array('termtext')))));  $markup .= ' ' . YOUR_MODULE_feed_icon(array('url' => 'taxonomy/term/' . implode('+', $tids) . '/all/feed', 'title' => $name));  return $markup;}/** * Copy of theme_feed_icon which avoids double encoding of & * due to issue http://drupal.org/node/1211668. * Uses !feed-title instead of @feed-title for t(). */function YOUR_MODULE_feed_icon($variables) {  $text = t('Subscribe to !feed-title', array('!feed-title' => $variables['title']));  if ($image = theme('image', array('path' => 'misc/feed.png', 'width' => 16, 'height' => 16, 'alt' => $text))) {    return l($image, $variables['url'], array('html' => TRUE, 'attributes' => array('class' => array('feed-icon'), 'title' => $text)));  }}?>

This code is based on http://drupal.org/node/223675#comment-900999.

Some styling:

.term-listing {
  margin-top: 14px;
}

.termlist .termtext {
  margin-right: 18px;
}

#page .term-listing a.feed-icon {
  bottom: -2px;
  border-bottom: none;
}

#block-block-1 a.feed-icon img {
  position: relative;
  bottom: -3px;
  border-bottom: none;
}