Expand term display to show complete paths of related terms
Description
The purpose of this snippet is to replace the term list that is shown below the node title with listing of any related terms and their complete breadcrumb trail. This allows for easy navigation between related terms and eliminates the redundancy of listing the current term underneath the node title.
In each case, I edited the node.tpl file by replacing the
<?php
print $terms
?>Drupal 5
Single vocabulary
This is for taxonomy terms with based only one one vocabulary. I took part of my code from http://drupal.org/node/53089 and documented the stuff that I added.
<?php
$termtoexclude=arg(2); //figure out what term page you are looking at
$printvocab=FALSE;
$vocabs = array();
foreach( (array)$node->taxonomy as $term ) {
$vocab = taxonomy_get_vocabulary($term->vid);
$parents = taxonomy_get_parents_all($term->tid); //get the parents of the current term in the list of terms
if ( !isset($vocabs[$vocab->name]) ) {
$vocabs[$vocab->name] = array();
}
if ($term->tid != $termtoexclude) //make sure the current page term isn't in the list of terms
{
$printvocab=TRUE;
if (count($parents) > 0) //make sure there is at least one level of parents. If not just use the current term
{
$vocabstemp = array(); //need this because taxonomy_get_parents_all starts with the current term and works backwards, so you have to reverse the order.
$vocabsfinal='';
//build your temporary list of parents
foreach ($parents as $parent) {
$vocabstemp[] .= l($parent->name, "taxonomy/term/$parent->tid");
}
$vocabstemp = array_reverse($vocabstemp); //reverse the list of parents so that it makes sense to the human eye. The next "foreach" build the final list of parents, making sure to take out the separator on the last term
foreach ($vocabstemp as $vocabstemp2key => $vocabstemp2) {
if ($vocabstemp2key < count($vocabstemp)-1)
{
$vocabsfinal .= $vocabstemp2.">";
}
else
{
$vocabsfinal .= $vocabstemp2;
}
}
$vocabs[$vocab->name][] = $vocabsfinal;
}
else
{
$vocabs[$vocab->name][] = l($term->name, "taxonomy/term/$term->tid");
}
}
}
//print the term list only if it isn't the current page term.
if ($printvocab) {
foreach ( $vocabs as $name => $termlinks ) {
print '<div class="taxonomy"> See Also: ';
print implode(', ', $termlinks);
print '</div>';
}
}
?>Multiple vocabulary
Use this one if you have a term list where you know the terms come from all different categories. I've only documented the changes from above.
<?php
$termtoexclude=arg(2);
//We don't want to repeat the current page's term or vocabulary. The next 3 lines are the setup for this.
$printvocab=FALSE;
$vocabtermtoskip = taxonomy_get_term($termtoexclude);
$vocabtoskip = taxonomy_get_vocabulary($vocabtermtoskip->vid);
$vocabs = array(); //The $vocabs array has changed to accommodate the multiple vocabularies. $vocabs[$vocab->name]['vocab'] contains the name / links to the vocabularies and $vocabs[$vocab->name]['links'][] contains the names / links to the terms of the vocabulary instance. (Yes, you can have more than one instance of the same vocabulary.)
foreach($node->taxonomy as $term )
{
$vocab = taxonomy_get_vocabulary($term->vid);
$parents = taxonomy_get_parents_all($term->tid);
if ($vocab->name != $vocabtoskip->name)//If we aren't skipping the current page's vocabulary, we are putting the vocabulary in front of the term path.
{
$vocabs[$vocab->name]['vocab']=l($vocab->name, "taxonomy/vocabulary/$term->vid").">";
}
else
{
$vocabs[$vocab->name]['vocab']="";
}
if ($term->tid != $termtoexclude)
{
$printvocab=TRUE;
if (count($parents) > 0)
{
$vocabstemp = array();
$vocabsfinal='';
foreach ($parents as $parent)
{
$vocabstemp[] .= l($parent->name, "taxonomy/term/$parent->tid");
}
$vocabstemp = array_reverse($vocabstemp);
foreach ($vocabstemp as $vocabstemp2key => $vocabstemp2)
{
if ($vocabstemp2key < count($vocabstemp)-1)
{
$vocabsfinal .= $vocabstemp2.">";
}
else
{
$vocabsfinal .= $vocabstemp2;
}
}
$vocabs[$vocab->name]['links'][] = $vocabsfinal;
}
else
{
$vocabs[$vocab->name]['links'][] = l($term->name, "taxonomy/term/$term->tid");
}
}
}
if ($printvocab) //We are using a string called $termcontent because it was the easiest way to make sure that the commas all fell in the right place.
{
$termcontent = '<div class="taxonomy"> See Also: ';
foreach ($vocabs as $vocabcatkey => $vocabitems)
{
if (count($vocabitems['links'])>0)
{
foreach ($vocabitems['links'] as $vocabkey => $vocablinks)
{
$termcontent .= $vocabitems['vocab'];
$termcontent .= $vocablinks;
$termcontent .= ", ";
}
}
}
$trimmed = rtrim($termcontent,", ");
$trimmed .= '</div>';
print $trimmed;
}?>Multiple vocabulary, multiple hierarchy
In this case, it looks at a vocabulary, determines if it's a multiple hierarchy that has more than 1 parent, and then traces the routes of those parents separately.
<?php
$termtoexclude=arg(2);
$printvocab=FALSE;
$vocabtermtoskip = taxonomy_get_term($termtoexclude);
$vocabtoskip = taxonomy_get_vocabulary($vocabtermtoskip->vid);
$vocabs = array();
foreach($node->taxonomy as $term )
{
$vocab = taxonomy_get_vocabulary($term->vid);
$parents = taxonomy_get_parents_all($term->tid);
if ($vocab->name != $vocabtoskip->name)
{
$vocabs[$vocab->name]['vocab']=l($vocab->name, "taxonomy/vocabulary/$term->vid").">";
}
else
{
$vocabs[$vocab->name]['vocab']="";
}
if ($term->tid != $termtoexclude)
{
$printvocab=TRUE;
if (count($parents) > 0)
{
$vocabstemp = array();
$vocabsfinal='';
if ($vocab->hierarchy==2 && count($parents) > 1)
{
$vocabstempmulti = array();
$parentsmulti = taxonomy_get_parents($parents[0]->tid);
foreach ($parentsmulti as $parentmulti)
{
$parentstrees = taxonomy_get_parents_all($parentmulti->tid);
if (count($parentstrees) > 1)
{
foreach ($parentstrees as $parentstree)
{
$vocabstemp[] .= l($parentstree->name, "taxonomy/term/$parentstree->tid");
}
$vocabstemp = array_reverse($vocabstemp);
foreach ($vocabstemp as $vocabstemp2key => $vocabstemp2)
{
if ($vocabstemp2key < count($vocabstemp)-1)
{
$vocabsmultifinal .= $vocabstemp2.">";
}
else
{
$vocabsmultifinal .= $vocabstemp2;
}
}
$vocabstempmulti[] = $vocabsmultifinal;
}
else
{
$parentnumber=$parentstrees[0]->tid;
$vocabstempmulti[] = l($parentstrees[0]->name, "taxonomy/term/$parentnumber");
}
}
$termnumber=$parents[0]->tid;
foreach ($vocabstempmulti as $vocabstempmultikey => $vocabstempmulti2)
{
if ($vocabstempmultikey < count($vocabstempmulti)-1)
{
$vocabsfinal .= $vocabstempmulti2.">".l($parents[0]->name, "taxonomy/term/$termnumber").", ";
}
else
{
$vocabsfinal .= $vocabstempmulti2.">".l($parents[0]->name, "taxonomy/term/$termnumber");
}
}
}
else
{
foreach ($parents as $parent)
{
$vocabstemp[] .= l($parent->name, "taxonomy/term/$parent->tid");
}
$vocabstemp = array_reverse($vocabstemp);
foreach ($vocabstemp as $vocabstemp2key => $vocabstemp2)
{
if ($vocabstemp2key < count($vocabstemp)-1)
{
$vocabsfinal .= $vocabstemp2.">";
}
else
{
$vocabsfinal .= $vocabstemp2;
}
}
}
$vocabs[$vocab->name]['links'][] = $vocabsfinal;
}
else
{
$vocabs[$vocab->name]['links'][] = l($term->name, "taxonomy/term/$term->tid");
}
}
}
if ($printvocab)
{
$termcontent = '<div class="taxonomy"> See Also: ';
foreach ($vocabs as $vocabcatkey => $vocabitems)
{
if (count($vocabitems['links'])>0)
{
foreach ($vocabitems['links'] as $vocabkey => $vocablinks)
{
$termcontent .= $vocabitems['vocab'];
$termcontent .= $vocablinks;
$termcontent .= ", ";
}
}
}
$trimmed = rtrim($termcontent,", ");
$trimmed .= '</div>';
print $trimmed;
}
?>Drupal 6
Single vocabulary
One line was changed to make this work in Drupal 6.
<?php
$termtoexclude=arg(2); //figure out what term page you are looking at
$printvocab=FALSE;
$vocabs = array();
foreach( (array)$node->taxonomy as $term ) {
$vocab = taxonomy_vocabulary_load($term->vid); // Changed for Druapl 6
$parents = taxonomy_get_parents_all($term->tid); //get the parents of the current term in the list of terms
if ( !isset($vocabs[$vocab->name]) ) {
$vocabs[$vocab->name] = array();
}
if ($term->tid != $termtoexclude) //make sure the current page term isn't in the list of terms
{
$printvocab=TRUE;
if (count($parents) > 0) //make sure there is at least one level of parents. If not just use the current term
{
$vocabstemp = array(); //need this because taxonomy_get_parents_all starts with the current term and works backwards, so you have to reverse the order.
$vocabsfinal='';
//build your temporary list of parents
foreach ($parents as $parent) {
$vocabstemp[] .= l($parent->name, "taxonomy/term/$parent->tid");
}
$vocabstemp = array_reverse($vocabstemp); //reverse the list of parents so that it makes sense to the human eye. The next "foreach" build the final list of parents, making sure to take out the separator on the last term
foreach ($vocabstemp as $vocabstemp2key => $vocabstemp2) {
if ($vocabstemp2key < count($vocabstemp)-1)
{
$vocabsfinal .= $vocabstemp2.">";
}
else
{
$vocabsfinal .= $vocabstemp2;
}
}
$vocabs[$vocab->name][] = $vocabsfinal;
}
else
{
$vocabs[$vocab->name][] = l($term->name, "taxonomy/term/$term->tid");
}
}
}
//print the term list only if it isn't the current page term.
if ($printvocab) {
foreach ( $vocabs as $name => $termlinks ) {
print '<div class="taxonomy"> See Also: ';
print implode(', ', $termlinks);
print '</div>';
}
}
?>Notes & References
- If you don't want to affect your whole site, make sure to create a custom content type via CCK or flexinode and then put one of the two snippets in a file called node-.tpl
- All 3 snippets have been tested on Drupal 5.7 using a blue marine customized theme.
- Related pages include:
- Single Vocabulary now works in Drupal 6

D6?
has anyone tried this on D6.x ?
-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
Data will generally define its own structure,
if you can just get out of the way
Yes, I have tried this on D6
Yes, I have tried this on D6 and unfortunately it does not work. I will post a workaround if I can, however any contributions are certainly welcome.
http://drupal.org/node/53089#
http://drupal.org/node/53089#comment-929924
So far this is the closest I have found, and it works quite well.
Aware of non-compatibility with D6
Single vocabulary now works for Drupal 6. Will work on the other versions in the future.