Drupal tag cloud for unique terms in a given post

28 Oct 2009
Posted by Eddie

These are the tags assigned to a sample post. The tag "sonoma" appears slightly larger than the other tags assigned to this post because it appears more frequently throughout all other posts.

A recent development project called for a tag cloud on the right rail. Easy to do generally; drupal has plenty of taxonomy modules available to take care of this for the most part.

What I needed that was different than any existing functionality I found was a tag cloud that showed:

1) A list of the node's terms in a block. These would be terms assigned to this post rather than an entire vocabulary.
2) The relative weights of those terms (and displayed visually using font size) as in a typical tag cloud.

The challenge was combining parts one and two. If you needed to apply this, the only thing in theory you'd need to change would be the vid = 5 in the database query to what ever vocabulary ID in which you want to run your query. So here is some code that does the trick (it could be simplified I think):


<?php
class tag
{
    var $name = "";
    var $count = 0;
    var $tid = 0;

    function getCount()
    {
        return $this->count;
    }
    function getName()
    {
        return $this->name;
    }
    function setCount($var)
    {
        $this->count = $var;
    }
    function setName($var)
    {
        $this->name = $var;
    }
    function setTID($var)
    {
        $this->tid = $var;
    }
    function getTID()
    {
        return $this->tid;
    }
}
$count = 0; // Overall count of used tags
$threshold = 0; // How many tags are needed to get displayed
$font_size = 0.8;
$node = node_load(arg(1));
$nid = $node->nid;
$query = "SELECT d.name,d.tid, dn.nid FROM {term_data} d, {term_node} dn WHERE dn.tid=d.tid and d.vid='5';";
$result = db_query($query);
$tags['Test'] = 0;
while($node = db_fetch_array($result))
{
    
    if ($tags[$node['name']] == NULL)
    {
        $tags[$node['name']] = new tag();
        $tags[$node['name']]->setName($node['name']);
        $tags[$node['name']]->setCount(1);
        $tags[$node['name']]->setTID($node['tid']);
        $count = $count + 1;
    }
    else
    {
        $tags[$node['name']]->setCount(
            $tags[$node['name']]->getCount() + 1
        );
        $count = $count + 1;
    }
}

$query2 = "SELECT d.name,d.tid, dn.nid FROM {term_data} d, {term_node} dn WHERE dn.tid=d.tid and dn.nid = '$nid' and d.vid='5';";
$result2 = db_query($query2);
$match1 =  $node['name'];
$match2 = $tag->name;
	while($node = db_fetch_array($result2)) {
			$termnames[] = $node['name'];
	}

foreach($tags as $tag)
{
    foreach($termnames as $termname){              
                 if($tag->name == $termname){
                 $matches[] = $tag; 
				}	
		}
}

foreach($matches as $match)
 {
    $mycount = $match->count;

    if($mycount > $threshold) 

    {
        $fraction = ((int)(($mycount / $count) * 60)) / 10;
        if($fraction < $font_size)
        {
            $fraction = $font_size;
        }
        echo '<span style="font-size: ' . $fraction . 'em;">' . l($match->name,'taxonomy/term/' . $match->tid,array('title="' . $match->count . ' Nodes"')).'</span> ';
    }
}

?>

The first half of the code I lifted from a snippet or forum post on Drupal.org many months ago, and the second half I managed to cobble together somehow on a cloudy day when the code gods were looking the other way.