A recent client site, which I was building with Drupal, needed a more conventional navigation system. Specifically, we needed a 'block' to do for regular pages what the book navigation block does for book.module - list the categories in a taxonomy, and show a sublist of that category when you either click on the category name, or access a page which is inside that category.

Here it is. I've used the "collapsed","expanded" and "leaf" list classes to make it all fit neatly into Drupal's default style.

One caveat: It assumes a flat term hierarchy and nodes attached to more than one taxonomy term will be assumed to be a member of only one of them.

Copy and paste this code into a new PHP block, and make a couple of locally-relevant changes (read the comments for details).

<?php

switch (arg(0)) {
  case 'node':
    $current = arg(1);
    
    // Note: Change the '7' below to whatever vocabulary ID you're using 
    $cats = taxonomy_node_get_terms_by_vocabulary($current, 7);
    foreach ($cats as $cat) {
      $mycategory = $cat->tid;
    }
    break;
  case 'taxonomy':
    $current = 0;
    $mycategory = arg(2);
    break;
  default:
    $current = 0;
    $mycategory = 0;
    break;
}

// Note: Change the '7' below to whatever vocabulary ID you're using
$terms = taxonomy_get_tree(7);

?>
<div class="menu">
<ul>

<?php

foreach($terms as $term) {
  $looptid = $term->tid;
  $loopname = $term->name;
  if($looptid == $mycategory) {
    print '<li class="expanded"><a href="/taxonomy/term/'. $looptid .'">'. $loopname .'</a><ul>';
    $kiddies = taxonomy_select_nodes(array($mycategory), 'or', 0, FALSE, 'n.title ASC, n.sticky DESC');
    if (db_num_rows($kiddies) > 0) {
      while ($getthem = db_fetch_object($kiddies)) {
        print '<li class="leaf"><a href="/node/"'. $getthem->nid .'">'. $getthem->title .'</a></li>';
      }
    }
    print '</ul>';
    print '</li>'; 
  } 
  else {
    print '<li class="collapsed"><a href="/taxonomy/term/'. $looptid .'">'. $loopname .'</a></li>';
  }
}
?>

</ul>
</div>

You can make it link to path aliases by using the drupal_get_path_alias function:
replace

print '<li class="expanded"><a href="/taxonomy/term/'. $looptid .'">'. $loopname .'</a><ul>';

with

print '<li class="expanded"><a href="/'. drupal_get_path_alias(\'taxonomy/term/$looptid') .'">'. $loopname .'</a><ul>';

and

print '<li class="collapsed"><a href="/taxonomy/term/'. $looptid .'">'. $loopname .'</a></li>';

with

print '<li class="collapsed"><a href="/'. drupal_get_path_alias('taxonomy/term/$looptid') .'">'. $loopname .'</a><ul>';

and for the nodes themselves

print '<li class="leaf"><a href="/node/'. $getthem->nid .'">'. $getthem->title. '</a></li>';

with

print '<li class="leaf"><a href="/'. drupal_get_path_alias('node/$getthem->nid') .'">'. $getthem->title .'</a></li>';

Comments

Azol’s picture

In Drupal 6, you can replace db_num_rows($kiddies) with mysql_num_rows($kiddies) if you are using MySQL

barinder’s picture

Drupal 6: db_affected_rows()

Drupal 7:

$result = db_query("SELECT nid, title FROM {node}"); 
$number_of_rows = $result->rowCount();

More details on : http://drupal.org/node/1251174