How to add a "Tags cloud" to the main page

Post about your customizations to share with others.

Moderators: Developer, Contributor

Post Reply
cdsaenz
Posts: 2
Joined: 21 Dec 2008, 16:38

How to add a "Tags cloud" to the main page

Post by cdsaenz »

I just found that there is a capability in Mantis to add tags to each issue. I would like to build a "tag cloud" perhaps on the main screen in order to show the outstanding tags. I believe this can be built in php from scratch, but not wanting to reivent the wheel I was wondering if there is anything around that I could reuse. Thanks a lot! :)
vboctor
Site Admin
Posts: 1293
Joined: 13 Feb 2005, 22:11
Location: Redmond, Washington
Contact:

Re: How to add a "Tags cloud" to the main page

Post by vboctor »

Yep, the tags cloud would be a useful feature which we discussed when designing the feature. I'm sure code can be re-used from any other PHP open source project that implements the feature (not sure of exact names). If anyone implements it, we would glady integrate it.

It would be cool if this gets implemented as a plugin for 1.2.x.
Migrate your MantisBT to the MantisHub Cloud
cdsaenz
Posts: 2
Joined: 21 Dec 2008, 16:38

Re: How to add a "Tags cloud" to the main page

Post by cdsaenz »

Hi vboctor, I agree, the plugin thing would be wonderful... I will try to investigate about this. For now i´ve created some basic php program (which I called tag_cloud.php). I used some nice code from http://www.v-nessa.net/2007/02/12/how-t ... -tag-cloud.

I basically call it from main_page.php and get the code with the "cloud" thing and some styling done. This is it if someone finds it useful (pardon my patching around the arrays handling, they still require some effort for me lol)

Code: Select all

require_once( 'core.php' );

function tag_info() {

  $t_tag_table	= config_get( 'mantis_tag_table' );
  $t_bug_tag_table	= config_get( 'mantis_bug_tag_table' );

  $query = "SELECT bt.tag_id AS id, tg.name AS tag, count(*) AS count
            FROM $t_bug_tag_table bt
               JOIN $t_tag_table tg ON tg.id = bt.tag_id
               GROUP BY bt.tag_id
               ORDER BY count DESC
               LIMIT 0 , 30";

  $result = db_query( $query );
  $tags   = array();
  while ( $row = db_fetch_array( $result ) ) {
      $tags[0][$row['tag']] = $row['count'];
      $tags[1][$row['tag']] = $row['id'];
  }
  return $tags;
}

function tag_html() {

    $min_size = 10;
    $max_size = 30;

    // extract the array dimensions
    $full_tags = tag_info();
    $tags = $full_tags[0];

    if ( is_null($tags) ) {
        return "No Tags Exist";
    }

    ksort($tags);

    $minimum_count = min(array_values($tags));
    $maximum_count = max(array_values($tags));
    $spread = $maximum_count - $minimum_count;

    if($spread == 0) {
        $spread = 1;
    }

    $cloud_html = '';
    $cloud_tags = array(); // create an array to hold tag code

    foreach ($tags as $tag => $count) {

        $size = $min_size + ($count - $minimum_count)
            * ($max_size - $min_size) / $spread;

        $id = $full_tags[1][$tag];

        $cloud_tags[] = '<a style="font-size: '. floor($size) . 'px'
            . '" class="tag_cloud" target="_blank" href="tag_view_page.php?tag_id=' . $id
            . '" title="\'' . $tag  . '\' returned a count of ' . $count . '">'
            . htmlspecialchars(stripslashes($tag)) . '</a>';
    }

    $cloud_html = join("\n", $cloud_tags) . "\n";
    return $cloud_html;
}

?>
NT
Posts: 21
Joined: 30 Oct 2007, 13:35

Re: How to add a "Tags cloud" to the main page

Post by NT »

Hi Victor

I have made a 1.2 plugin to add a TagCloud to the view bugs page.
I have posted it here as the most appororiate place rather than on the bug tracker.

How are contributed plugins going to be handled (and maintained) ?
Some Open Source projects hold them in their own source code repositories, while others publish
links to the authors web pages.

There are still a few improvements that I should make to this plugin, such as configuration page error messages, and default values being made constants rather than hard coded.

NT

plugins/TagCloud/TagCloud.php

Code: Select all

<?php
/**
 * plugin for Tag Clouds.
 * @package TagCloud
 */
 /**
 */
    require_once( config_get( 'class_path' ) . 'MantisPlugin.class.php' );

/**
 * A plugin for outputing a Tag Cloud.
 * @package TagCloud
 */
class TagCloudPlugin extends MantisPlugin {

	/**
	 * an array to hold the tags.
	 */
	private $tags;

	/**
	 *  A method that populates the plugin information and minimum requirements.
	 */
	function register() {
		$this->name			= lang_get( 'plugin_tagcloud_title' );
		$this->description	= lang_get( 'plugin_tagcloud_description' );
		$this->page			= 'config';
		$this->version		= '1.0.0';
		$this->requires		= array(
			'MantisCore' => '1.2.0',
		);
		$this->author		= 'Nick Tucker';
		$this->contact		= 'mantisbt-dev@lists.sourceforge.net';
		$this->url			= 'http://www.mantisbt.org';
	}

	/**
	 * Event hook declaration.
	 */
	function hooks() {
		$t_hooks =  array(
			'EVENT_LAYOUT_RESOURCES'		=> 'print_header',	# Add css to page header
			'EVENT_LAYOUT_CONTENT_BEGIN'	=> 'print_content',	# Add Cloud Tag to page
		);
		return array_merge( parent::hooks(), $t_hooks );
	}

	/**
	 * Default plugin configuration.
	 */
	function config() {
		return array(
			'steps'	=> 4,
			'max_tags'	=> 16,
			'order'	=> 1,
		);
	}

	/**
	 * Output link to plugin stylesheet.
	 */
	function print_header() {
		if ($this->get_page_name() == 'view_all_bug_page') {
			$t_css_path = helper_mantis_url( 'plugins/TagCloud/pages/tagcloud.css' );
			echo '<link rel="stylesheet" type="text/css" href="' . $t_css_path . '" />';
		}
	}

	/**
	 * Add tagcloud to the page.
	 */
	function print_content() {
		if ($this->get_page_name() == 'view_all_bug_page') {
			$this->print_tag_cloud();
		}
	}

	/**
	 * Print the tagcloud.
	 */
	function print_tag_cloud() {
		$t_tag_table = db_get_table( 'mantis_tag_table' );
		$t_bug_tag_table = db_get_table( 'mantis_bug_tag_table' );
		$t_max_tags = plugin_config_get( 'max_tags' );
		$query = "SELECT count(*) as num, t.name
						FROM $t_tag_table as t
						LEFT JOIN $t_bug_tag_table as b
							on t.id=b.tag_id
						GROUP BY t.name
						ORDER BY num DESC";
		$result = db_query_bound( $query, null, $t_max_tags );
		$this->tags = array();
		$t_max = -1;
		$t_min = PHP_INT_MAX;
		$t_steps = plugin_config_get( 'steps' );
		while( $row = db_fetch_array( $result ) ) {
			$t_value = $row['num'];
			if ($t_value < $t_min) {
				$t_min = $t_value;
			}
			if ($t_value > $t_max) {
				$t_max = $t_value;
			}
			$this->tags[] = array('count' => $t_value,
								'tagname' => $row['name']);
		}

        echo '<div class="tagcloud">';
        echo '<div class="title">' . lang_get( 'plugin_tagcloud_title' ) .'</div>';
        echo '<div class="content">';
		$t_url = 'view_all_set.php?type=1&temporary=y&' . FILTER_PROPERTY_TAG_STRING . '=';

		switch (plugin_config_get('order')) {
			case 0:
				shuffle( $this->tags );
				break;
			case 1:
				usort( $this->tags, "_tagcloud_callback_name_asc" );
				break;
			case 2:
				usort( $this->tags, "_tagcloud_callback_name_desc" );
				break;
			case 3:
				usort( $this->tags, "_tagcloud_callback_count_asc" );
				break;
			case 4:
				usort( $this->tags, "_tagcloud_callback_count_desc" );
				break;
		}

		foreach($this->tags as $tag)
		{
			$t_weight = $this->get_tag_weight( $tag['count'], $t_min, $t_max, $t_steps );
			echo '<a class="tag' .$t_weight .'" href="'. $t_url .$tag['tagname'].'">'.$tag['tagname'].'</a>'."\n";
		}
        echo '</div></div>';
	}

	/**
	 * Calculate the weighting for a tag (1 to $p_steps).
	 * @param int $p_value the number of times this tag is used.
	 * @param int $p_min the lowest number of times a tag in  the cloud is used.
	 * @param int $p_max the highest number of times a tag in  the cloud is used
	 * @param int $p_steps the highest weighting value allowed.
	 * @return int the tag weight.
	 */
	protected function get_tag_weight( $p_value, $p_min, $p_max, $p_steps ) {
		if ($p_value >= $p_max) {
			return $p_steps;
		}
		$t_value = $p_value - $p_min;
		$t_range = $p_max - $p_min;
		return  floor(($p_steps * $t_value )/ $t_range) + 1;
	}

	/**
	 * Retrieves the name of the current page
	 * @return string the name of the current page.
	 */
	protected static function get_page_name() {
		ereg( "([^/]*)\.php", $_SERVER['PHP_SELF'], $t_matches );
		return $t_matches[1];
	}
}

/**
 * Generalised sort comparator for tags
 * @param array $p_left an associative array containing details for a tag.
 * @param array $p_right an associative array containing details for a tag.
 * @param string $p_key the key of the array elements to compare.
 * @return int the sort comparator value 0:equal, -1:$p_left highest:-1 $p_right highest.
 */
function _tagcloud_callback($p_left, $p_right, $p_key) {
    if ($p_left[$p_key] == $p_right[$p_key]) {
        return 0;
    }
    return ($p_left[$p_key] > $p_right[$p_key]) ? -1 : 1;
}

/**
 * Comparator to sort tags into descending name order
 * @param array $p_left an associative array containing details for a tag.
 * @param array $p_right an associative array containing details for a tag.
 * @return int the sort comparator value
 */
function _tagcloud_callback_name_desc($p_left, $p_right) {
    return _tagcloud_callback($p_left, $p_right, 'tagname');
}

/**
 * usort callback to sort tags into ascending name order
 * @param array $p_left an associative array containing details for a tag.
 * @param array $p_right an associative array containing details for a tag.
 * @return int the sort comparator value
 */
function _tagcloud_callback_name_asc($p_left, $p_right) {
    return _tagcloud_callback($p_right, $p_left, 'tagname');
}

/**
 * usort callback to sort tags into descending usage order
 * @param array $p_left an associative array containing details for a tag.
 * @param array $p_right an associative array containing details for a tag.
 * @return int the sort comparator value
 */
function _tagcloud_callback_count_desc($p_left, $p_right) {
    return _tagcloud_callback($p_left, $p_right, 'count');
}

/**
 * usort callback to sort tags into ascending usage order
 * @param array $p_left an associative array containing details for a tag.
 * @param array $p_right an associative array containing details for a tag.
 * @return int the sort comparator value
 */
function _tagcloud_callback_count_asc($p_left, $p_right) {
    return _tagcloud_callback($p_right, $p_left, 'count');
}

?>
plugins/TagCloud/pages/config.php

Code: Select all

<?php
/**
 * Tag Clouds Plugin Configuration page.
 * @package TagCloud
 */

auth_reauthenticate( );
access_ensure_global_level( config_get( 'manage_plugin_threshold' ) );

html_page_top1( lang_get( 'plugin_tagcloud_title' ) );
html_page_top2( );

print_manage_menu( );
$t_order = plugin_config_get( 'order' );
?>

<br/>
<form action="<?php echo plugin_page( 'config_edit' ) ?>" method="post">
<table align="center" class="width50" cellspacing="1">

<tr>
	<td class="form-title" colspan="3">
		<?php echo lang_get( 'plugin_tagcloud_title' ) . ': ' . lang_get( 'plugin_tagcloud_config' ) ?>
	</td>
</tr>

<tr <?php echo helper_alternate_class( ) ?>>
	<td class="category" width="60%">
		<?php echo lang_get( 'plugin_tagcloud_steps' ) ?>
	</td>
	<td class="center" width="40%">
		<input type="text" id="tag_steps" name="tag_steps" value="<?php echo plugin_config_get( 'steps' ) ?>"/>
	</td>
</tr>

<tr <?php echo helper_alternate_class( )?>>
	<td class="category" width="60%">
		<?php echo lang_get( 'plugin_tagcloud_max_tags' ) ?>
	</td>
	<td class="center" width="40%">
		<input type="text" id="max_tags"  name="max_tags" value="<?php echo plugin_config_get( 'max_tags' ) ?>"/>
	</td>
</tr>

<tr <?php echo helper_alternate_class( ) ?>>
	<td class="category" width="60%">
		<?php echo lang_get( 'plugin_tagcloud_order' ) ?>
	</td>
	<td class="center" width="40%">
		<select id="tag_order" name="tag_order" tabindex="1">
			<?php _tagcloud_config_print_option( 0, 'plugin_tagcloud_random_order', $t_order ) ?>
			<?php _tagcloud_config_print_option( 1, 'plugin_tagcloud_asc_name_order', $t_order ) ?>
			<?php _tagcloud_config_print_option( 2, 'plugin_tagcloud_desc_name_order', $t_order ) ?>
			<?php _tagcloud_config_print_option( 3, 'plugin_tagcloud_asc_freq_order', $t_order ) ?>
			<?php _tagcloud_config_print_option( 4, 'plugin_tagcloud_desc_freq_order', $t_order ) ?>
		</select>
	</td>
</tr>

<tr>
	<td class="center" colspan="3">
		<input type="submit" class="button" value="<?php echo lang_get( 'change_configuration' )?>" />
	</td>
</tr>

</table>
<form>

<?php
html_page_bottom1( __FILE__ );

/**
 * print the tag order select option elements.
 * @param int $p_index the option value.
 * @param string $p_lang_str the language string key of the option text.
 * @param int $p_order the value of the currently selected option.
 */
function _tagcloud_config_print_option($p_index, $p_lang_str, $p_order) {
	echo '<option value="' . $p_index .'"';
	if ($p_index == $p_order) {
		echo ' selected="1"';
	}
	echo '>' . lang_get($p_lang_str) . '</option>';
}
plugins/TagCloud/pages/config_edit.php

Code: Select all

<?php

/**
 * Tag Clouds Plugin Configuration processing page.
 * @package TagCloud
 */

auth_reauthenticate( );
access_ensure_global_level( config_get( 'manage_plugin_threshold' ) );

$f_steps = gpc_get_int( 'tag_steps', 4 );
$f_max_tags = gpc_get_int( 'max_tags', 16 );
$f_order = gpc_get_int( 'tag_order', 1 );

# make sure form values are within sensible ranges
if ( ($f_steps < 1) or ($f_steps > 10) ) {
	$f_steps = 4;
}
if ($f_max_tags < 1) {
	$f_max_tags = 1;
}
if ( ($f_order < 0) or ($f_orders > 4) ) {
	$f_order = 0;
}

if( plugin_config_get( 'steps' ) != $f_steps ) {
	plugin_config_set( 'steps', $f_steps );
}
if( plugin_config_get( 'max_tags' ) != $f_max_tags ) {
	plugin_config_set( 'max_tags', $f_max_tags );
}

if( plugin_config_get( 'order' ) != $f_order ) {
	plugin_config_set( 'order', $f_order );
}


print_successful_redirect( plugin_page( 'config', true ) );
plugins/TagCloud/pages/tagcloud.css

Code: Select all

div.tagcloud {
	color: #dda0dd;
	font-family: Verdana,Arial,Helvetica,sans-serif;
	width:75%;
	margin-top:1em;
	margin-left:12.5%;
	padding:0;
	border: 1px solid black;
	text-align: center;
}

.tagcloud a {
	color: blue;
	text-decoration: none;
	text-transform: capitalize;
}

.tagcloud div.title {
	background-color:#C8C8E8;
	border-bottom:1px solid #000000;
	font-weight:bold;
	color:#000000;
	text-align:left;
	text-transform: capitalize;
	border-bottom: 1px solid black;
}

.tagcloud a.tag0 { font-size:.8em; }
.tagcloud a.tag1 { font-size:1em; }
.tagcloud a.tag2 { font-size:1.2em; }
.tagcloud a.tag3 { font-size:1.4em; }
.tagcloud a.tag4 { font-size:1.6em; }
.tagcloud a.tag5 { font-size:1.8em; }
.tagcloud a.tag6 { font-size:2em; }
.tagcloud a.tag7 { font-size:2.2em; }
.tagcloud a.tag8 { font-size:2.4em; }
.tagcloud a.tag9 { font-size:2.6em; }
.tagcloud a.tag10 { font-size:2.8em; }
plugins/TagCloud/lang/strings_english.txt

Code: Select all

<?php
$s_plugin_tagcloud_title = 'Tag Cloud';
$s_plugin_tagcloud_description = 'Tag Cloud plugin.';
$s_plugin_tagcloud_config = 'Configuration';
$s_plugin_tagcloud_steps = 'Number of levels (1-10)';
$s_plugin_tagcloud_max_tags = 'Maximum number of tags to display.';
$s_plugin_tagcloud_order = 'Tag Order';
$s_plugin_tagcloud_random_order = 'Random';
$s_plugin_tagcloud_asc_name_order = 'By Name (ascending)';
$s_plugin_tagcloud_desc_name_order = 'By Name (descending)';
$s_plugin_tagcloud_asc_freq_order = 'By Usage (ascending)';
$s_plugin_tagcloud_desc_freq_order = 'By Usage (descending)';
?>
vboctor
Site Admin
Posts: 1293
Joined: 13 Feb 2005, 22:11
Location: Redmond, Washington
Contact:

Re: How to add a "Tags cloud" to the main page

Post by vboctor »

Hi NT,

Thanks for your contribution. I pinged jreese / paulr on this. Ideally the plugin would be hosted on git.mantisforge.org. I can see there is already a repo setup for it.

You can keep this thread up to date relating to the progress of the plugin.

Thanks.
Migrate your MantisBT to the MantisHub Cloud
Michael.S
Posts: 4
Joined: 14 Jan 2009, 09:11
Location: Germany

Re: How to add a "Tags cloud" to the main page

Post by Michael.S »

is that plugin visible for all projects, or does the admin/manager hast to add it?
and uses it only tags from one (or more selcted) project?
NT
Posts: 21
Joined: 30 Oct 2007, 13:35

Re: How to add a "Tags cloud" to the main page

Post by NT »

The plugin has been put on http://git.mantisforge.org/.
This should work with release 1.2.0a3.

When enabled, the Tag Cloud is visible for all projects,

The latest code will only show the tags from the currently selected project.
If 'All Projects' is selected on the view bugs page, then tags will be shown from all projects, but
there is still some work to do to as I have not taken private projects into consideration.

Nick
Post Reply