Visit example.com/tagadelic/list/2,1,5 to get the vocabularies 2,1 and 5 listed as tag groups.
Visit example.com/tagadelic/chunk/2,1,5 to get a tag cloud of the terms in the vocabularies 2,1 and 5.
Note that we limit to five vocabularies.');
}
}
/**
* Implementation of hook_menu
*/
function tagadelic_menu($may_cache) {
$items = array();
$stylesheet = drupal_get_path('module','tagadelic') .'/tagadelic.css';
drupal_add_css($stylesheet, 'all');
if ($may_cache) {
$items[] = array(
'path' => 'admin/settings/tagadelic',
'title' => t('Tagadelic configuration'),
'description' => t('Configure the tag clouds. Set the order, the number of tags, and the depth of the clouds.'),
'callback' => 'drupal_get_form',
'callback arguments' => 'tagadelic_settings',
'access' => user_access('administer site configuration'));
$items[] = array(
'title' => t('Tags'),
'path' => "tagadelic",
'callback' => 'tagadelic_page_chunk',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM);
$items[] = array(
'title' => t('Tags'),
'path' => "tagadelic/list",
'callback' => 'tagadelic_page_list',
'access' => user_access('access content'),
'type' => MENU_CALLBACK);
$items[] = array(
'title' => t('Tags'),
'path' => "tagadelic/chunk",
'callback' => 'tagadelic_page_chunk',
'access' => user_access('access content'),
'type' => MENU_CALLBACK);
foreach (taxonomy_get_vocabularies($type = NULL) as $vocabulary) {
$items[] = array(
'title' => $vocabulary->name,
'path' => "tagadelic/chunk/$vocabulary->vid",
'callback' => 'tagadelic_page_chunk',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM);
}
}
return $items;
}
/**
* Implementation of hook_nodeapi
* Yuo will have a nice variable in $node available for processing tags!
*/
function tagadelic_nodeapi(&$node, $op, $teaser, $page) {
if ($op == 'load') {
$node->tags = tagadelic_node_get_terms($node);
}
}
/**
* Menu callback. Admin setting page for tagadelic.
*/
function tagadelic_settings() {
$options = array('weight,asc' => t('by weight, ascending'), 'weight,desc' => t('by weight, descending'), 'title,asc' => t('by title, ascending'), 'title,desc' => t('by title, descending'), 'random,none' => t('random'));
$form['tagadelic_sort_order'] = array(
'#type' => 'radios',
'#title' => t('Tagadelic sort order'),
'#options' => $options,
'#default_value' => variable_get('tagadelic_sort_order', 'title,asc'),
'#description' => t('Determines the sort order of the tags on the freetagging page.'),
);
$form['tagadelic_page_amount'] = array(
'#type' => 'textfield',
'#size' => 5,
'#title' => t('Amount of tags'),
'#default_value' => variable_get('tagadelic_page_amount', '60'),
'#description' => t('The amount of tags that will show up in a cloud.'),
);
$form['tagadelic_levels'] = array(
'#type' => 'textfield',
'#size' => 5,
'#title' => t('Number of levels'),
'#default_value' => variable_get('tagadelic_levels', 6),
'#description' => t('The number of levels between the least popular tags and the most popular ones. Different levels will be assigned a different class to be themed in tagadelic.css'),
);
return system_settings_form($form);
}
/**
* menu callback renders a tagadelic page
*/
function tagadelic_page_chunk() {
$vocs = arg(2);
if (is_numeric($vocs)) {
$vocs = array($vocs);
}
elseif (preg_match('/^([0-9]+,){1,5}[0-9]+$/', $vocs)) {
$vocs = explode(',', $vocs);
}
elseif($vocs == NULL) { //create a chunk from all free tagging vocs
foreach (taxonomy_get_vocabularies(NULL) as $vocabulary) {
$vocs[] = $vocabulary->vid;
}
}
$tags = tagadelic_get_weighted_tags($vocs, variable_get('tagadelic_levels', 6), variable_get('tagadelic_page_amount', '60'));
$tags = tagadelic_sort_tags($tags);
$output = theme('tagadelic_weighted',$tags);
if (!$output) {
return drupal_not_found();
}
$output = "
$output
";
return $output;
}
/**
* menu callback renders a tagadelic page with listed items: each voc
*/
function tagadelic_page_list() {
$vocs = arg(2);
if (is_numeric($vocs)) {
$vocs = array($vocs);
}
elseif (preg_match('/^([0-9]+,){1,5}[0-9]+$/', $vocs)) {
$vocs = explode(',', $vocs);
}
else {
return drupal_not_found();
}
foreach ($vocs as $vid) {
$vocabulary = taxonomy_get_vocabulary($vid);
$tags = tagadelic_get_weighted_tags(array($vocabulary->vid), variable_get('tagadelic_levels', 6), variable_get('tagadelic_page_amount', '60'));
$tags = tagadelic_sort_tags($tags);
$output .= theme('tagadelic_list_box', $vocabulary, $tags);
}
if (!$output) {
return drupal_not_found();
}
$stylesheet = drupal_get_path('module','tagadelic') .'/tagadelic.css';
drupal_add_css($stylesheet, 'all');
$output = "$output
";
return $output;
}
/**
* API that returns a multidimensional array with tags given a node
* @param $node. A node object.
*/
function tagadelic_node_get_terms($node) {
if ($terms = taxonomy_node_get_terms($node->nid, 'tid')) {
$vocs = taxonomy_get_vocabularies($node->type);
foreach ($terms as $tid => $term) {
if ($vocs[$term->vid]->tags) {
$tags[$term->vid][$tid] = $term;
}
}
return $tags;
}
}
/**
* API function that returns the tags of a node in fancy titled lists
* @param $node. A node object.
*/
function tagadelic_tags_lists($node) {
if (is_array($node->tags)) {
foreach($node->tags as $vid => $terms) {
$vocabulary = taxonomy_get_vocabulary($vid);
$title = l($vocabulary->name, "tagadelic/chunk/$vid");
$items = array();
foreach ($terms as $term) {
$items[] = l($term->name, taxonomy_term_path($term), array('title' => t('view all posts tagged with "@tag"', array('@tag' => $term->name))));
}
$output .= theme('item_list', $items, $title);
}
return $output;
}
}
/**
* Function that gets the information from the database, passes it along to the weight builder and returns these weighted tags. Note that the tags are unordered at this stage, hence they need orndering either by calling our api or by your own ordering data.
* @param $vids. Vocabulary IDs representing the vocabularies where you want the tags from.
* @param $steps. The amount of tag-sizes you will be using. If you give "12" you sill get six different "weights". Defaults to 6 and is optional.
* @return An unordered array with tags-objects, containing the attribute $tag->weight;
*/
function tagadelic_get_weighted_tags($vids, $steps = 6, $size = 60) {
//CACHING! PLease! Send! in! your! patches! :)
if (!is_array($vids) || count($vids) == 0) {
return array();
}
$result = db_query_range('SELECT COUNT(*) AS count, d.tid, d.name, d.vid FROM {term_data} d INNER JOIN {term_node} n ON d.tid = n.tid WHERE d.vid IN ('. substr(str_repeat('%d,', count($vids)), 0, -1) .') GROUP BY d.tid, d.name, d.vid ORDER BY count DESC', $vids, 0, $size);
return tagadelic_build_weighted_tags($result, $steps);
}
/**
* API that returns an array with weighted tags
* This is the hard part. People with better ideas are very very welcome to send these to ber@webschuur.com. Distribution is one thing that needs attention.
* @param $result. a query result, any query result that contains an object with the following attributes: $tag->count, $tag->tid, $tag->name and $tag->vid. Refer to tagadelic_get_weighted_tags() for an example."
* @param $steps. The amount of tag-sizes you will be using. If you give "12" you sill get six different "weights". Defaults to 6 and is optional.
* @return An unordered array with tags-objects, containing the attribute $tag->weight;
*/
function tagadelic_build_weighted_tags($result, $steps = 6) {
// Find minimum and maximum log-count. By our MatheMagician Steven Wittens aka UnConeD.
$tags = array();
$min = 1e9;
$max = -1e9;
while ($tag = db_fetch_object($result)) {
$tag->number_of_posts = $tag->count;
$tag->count = log($tag->count);
$min = min($min, $tag->count);
$max = max($max, $tag->count);
$tags[$tag->tid] = $tag;
}
// Note: we need to ensure the range is slightly too large to make sure even
// the largest element is rounded down.
$range = max(.01, $max - $min) * 1.0001;
foreach ($tags as $key => $value) {
$tags[$key]->weight = 1 + floor($steps * ($value->count - $min) / $range);
}
return $tags;
}
/**
* API funtion to order a set of tags.
* @todo If you feel like making this more modular, please send me patches.
**/
function tagadelic_sort_tags($tags) {
list($sort, $order) = explode(',', variable_get('tagadelic_sort_order', 'title,asc'));
switch ($sort) {
case 'title':
usort($tags, "_tagadelic_sort_by_title");
break;
case 'weight':
usort($tags, "_tagadelic_sort_by_weight");
break;
case 'random':
shuffle($tags);
break;
}
if ($order == 'desc') {
$tags = array_reverse($tags);
}
return $tags;
}
/**
* callback for usort, sort by count
*/
function _tagadelic_sort_by_title($a, $b) {
return strnatcasecmp($a->name, $b->name);
}
/**
* callback for usort, sort by weight
*/
function _tagadelic_sort_by_weight($a, $b) {
return $a->weight > $b->weight;
}
/**
* theme function that renders the HTML for the tags
* @ingroup themable
*/
function theme_tagadelic_weighted($terms) {
foreach ($terms as $term) {
$output .= l($term->name, taxonomy_term_path($term), array('class'=>"tagadelic level$term->weight")) ." \n";
}
return $output;
}
/**
* theme function that renders an entry in tagadelic/list/ views
* @param $vocabulary, a full vocabulary object
* @param $tags, an array with weigthed tag objects
* @ingroup themable
*/
function theme_tagadelic_list_box($vocabulary, $tags) {
$content = theme('tagadelic_weighted', $tags);
if ($vocabulary->description) {
$content = theme("box", NULL, $vocabulary->description) . $content;
}
$output .= theme('box', $vocabulary->name, $content);
return $output;
}
/**
* implementation of hook_block
*/
function tagadelic_block($op = 'list', $delta = O, $edit = array()) {
if ($op == 'view') {
if ($voc = taxonomy_get_vocabulary($delta)) {
$blocks['subject'] = variable_get('tagadelic_block_title_'. $delta, t('tags in @voc', array('@voc' => $voc->name)));
$tags = tagadelic_get_weighted_tags(array($voc->vid),6, variable_get('tagadelic_block_tags_'. $delta, 12));
$tags = tagadelic_sort_tags($tags);
$blocks['content'] = theme('tagadelic_weighted', $tags);//return a chunk of 12 tags
}
elseif(arg(0) == 'node' && is_numeric(arg(1)) && $node = node_load(arg(1))) {
$blocks['subject'] = t('tags for @title', array('@title' => $node->title));
$blocks['content'] = tagadelic_tags_lists($node);
}
}
elseif ($op == 'list') {
foreach(taxonomy_get_vocabularies() as $voc) {
$blocks[$voc->vid]['info'] = variable_get('tagadelic_block_title_'. $voc->vid, t('tags in @voc', array('@voc' => $voc->name)));
}
$blocks[0]['info'] = t('tags for the current post');
}
elseif ($op == 'configure') {
$voc = taxonomy_get_vocabulary($delta);
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Block title'),
'#default_value' => variable_get('tagadelic_block_title_'. $delta, t('tags in @voc', array('@voc' => $voc->name))),
'#maxlength' => 64,
'#description' => t('The title of the block as shown to the user.'),
);
$form['tags'] = array(
'#type' => 'textfield',
'#title' => t('Tags to show'),
'#default_value' => variable_get('tagadelic_block_tags_'. $delta, 12),
'#maxlength' => 3,
'#description' => t('The number of tags to show in this block.'),
);
return $form;
}
elseif ($op == 'save') {
variable_set('tagadelic_block_title_'. $delta, $edit['title']);
variable_set('tagadelic_block_tags_'. $delta, $edit['tags']);
return;
}
return $blocks;
}