Extension talk:CategoryCloud
Exclude categories and maximum limit of categories shown
editI used the code provided at the bottom of this page and modified it so now we have the exclude parameter and the maximum limit of categories shown works.
<?php
/**
* Parser hook extension adds a <category-cloud> tag to wiki markup. The
* following attributes are used:
* category = The category, minus the "Category:". if category is "" then All.
* order = "name" or "count"
* minsize = The minimum size, as percentage. Defaults to 80.
* maxsize = The maximum size, as a percentage. Defaults to 125.
* maxitems = Limiting tag cloud size. Defaults to 80
* class = The CSS class to assign to the outer div, defaults
* to "category-cloud"
* exclude = The list of categories to be excluded from the tag cloud. If not present, then none.
*
* There is also a parser function that uses {{#category-cloud:CategoryName}}
* with optional parameters being includes as "|param=value".
*
* @addtogroup Extensions
* @author Dylan R. E. Moonfire <contact@mfgames.com>
* @copyright 2007 Dylan R. E. Moonfire
* @licence GNU General Public Licence 2.0
* Last Modified: Isaac Contreras Sandoval
* August 25th 2011
* Changed SQL query to include all categories - not only those which have an article created
*/
// Make sure we are being properly
if( !defined( 'MEDIAWIKI' ) ) {
echo( "This file is an extension to the MediaWiki software "
. "and cannot be used standalone.\n" );
die( -1 );
}
// Hook up into MediaWiki
$wgExtensionFunctions[] = 'categoryCloud';
$wgHooks['LanguageGetMagic'][] = 'categoryCloudMagic';
$wgExtensionCredits['parserhook'][] = array(
'name' => 'Category Cloud',
'author' => 'Dylan R. E. Moonfire',
'description' => 'Create a tag cloud using categories.',
'url' => 'http://www.mediawiki.org/wiki/Extension:CategoryCloud',
'version' => '0.4.0'
);
function categoryCloud()
{
global $wgParser, $wgMessageCache;
// Set the hooks
$wgParser->setHook('category-cloud', 'categoryCloudRender');
$wgParser->setFunctionHook('category-cloud', 'categoryCloudFunction');
// Set our messages
$wgMessageCache->addMessages( array(
'categorycloud_missingcategory'
=> 'CategoryCloud: Cannot find category attribute',
'categorycloud_emptycategory'
=> 'CategoryCloud: Category is empty: ',
'categorycloud_cannotparse'
=> 'CategoryCloud: Cannot parse parameter: ',
));
}
// This manipulates the results of the CategoryCloud extension
// into the same function as the <category-cloud> tag.
function categoryCloudFunction($parser)
{
// Get the arguments
$fargs = func_get_args();
$input = array_shift($fargs);
// The first category is required
$category = array_shift($fargs);
$params = array();
$params["category"] = $category;
$params["donotparse"] = 1;
// Split the rest of the arguments
foreach ($fargs as $parm)
{
// Split it into its components
$split = split("=", $parm);
if (!$split[1])
{
return htmlspecialchars(wfMsg(
'categorycloud_cannotparse')
. $parm);
}
// Save it
$params[$split[0]] = $split[1];
}
// Return the cloud
return categoryCloudRender($input, $params, $parser);
}
// Sets up the magic for the parser functions
function categoryCloudMagic(&$magicWords, $langCode)
{
$magicWords['category-cloud'] = array(0, 'category-cloud');
return true;
}
// The actual processing
function categoryCloudRender($input, $args, &$parser)
{
// Imports
global $wgOut;
// Profiling
wfProfileIn('CategoryCloud::Render');
// Disable the cache, otherwise the cloud will only update
// itself when a user edits and saves the page.
$parser->disableCache();
// Get the database handler and specific controls
$dbr =& wfGetDB( DB_SLAVE );
$pageTable = $dbr->tableName('page');
$categoryLinksTable = $dbr->tableName('categorylinks');
// Normalize the order
$order = "count";
if (array_key_exists("order", $args)) $order = $args["order"];
if ($order != "count")
$order = "name";
else // we want reverse
$order = "count DESC";
// Get the list of the subcategories and the number of children
if (!array_key_exists("category", $args))
{
return htmlspecialchars(wfMsg(
'categorycloud_missingcategory'));
}
$categoryName = $args["category"];
$maxitems=80;
if(array_key_exists("maxitems",$args))
$maxitems = $args["maxitems"];
// Build up an SQL of everything
$sql = "SELECT DISTINCT $categoryLinksTable.cl_to as name, count(*) as count "
. "FROM $pageTable "
. "JOIN $categoryLinksTable ON $categoryLinksTable.cl_from = $pageTable.page_id "
. "GROUP BY name "
. "ORDER BY $order "
. "LIMIT $maxitems OFFSET 0";
$res = $dbr->query($sql);
if ($dbr->numRows( $res ) == 0)
{
// Can't find category
return htmlspecialchars(wfMsg(
'categorycloud_emptycategory')
. $categoryName);
}
// Build up an array and keep track of mins and maxes
$minCount = -1;
$maxCount = -1;
$countAll = 0;
$total = 0;
$categories = array();
$names = array();
if (array_key_exists("exclude", $args))
$excluded_categories = explode(",",$args["exclude"]);
while ($row = $dbr->fetchObject($res))
{
// Pull out the fields
$name = $row->name;
$count = $row->count;
if (array_key_exists("exclude", $args)){
if(!in_array($name,$excluded_categories)){
if(!in_array($name,$names)){
// Add it to the array and keep track of min/max
$categories[$name] = $count;
$names[] = $name;
$countAll++;
$total += $count;
if ($minCount < 0 || $minCount > $count)
$minCount = $count;
if ($maxCount < 0 || $maxCount < $count)
$maxCount = $count;
}
}
}
else{
$categories[$name] = $count;
$names[] = $name;
$countAll++;
$total += $count;
if ($minCount < 0 || $minCount > $count)
$minCount = $count;
if ($maxCount < 0 || $maxCount < $count)
$maxCount = $count;
}
}
// Figure out the averages and font sizes
$minSize = 80;
$maxSize = 125;
if (array_key_exists("minsize", $args)) $minSize = $args["minsize"];
if (array_key_exists("maxsize", $args)) $maxSize = $args["maxsize"];
$countDelta = $maxCount - $minCount;
$sizeDelta = $maxSize - $minSize;
$average = $total / $countAll;
// Create the tag cloud div
$class = "category-cloud";
if (array_key_exists("class", $args)) $class = $args["class"];
$text = "<div class='$class'";
if (array_key_exists("style", $args))
$text .= " style='" . $args["style"]. "'";
$text .= ">";
// Go through the categories by name
foreach ($names as $cat)
{
// Wrap the link in a size
if ($countDelta == 0)
$size = 100;
else
$size = (($categories[$cat] - $minCount)
* $sizeDelta / $countDelta) + $minSize;
// Get the link
$cat = str_replace("_", " ", $cat);
$text .= " <span style='font-size: $size%;'>"
. "[[:Category:$cat|$cat]]</span>";
}
// Finish up
$text .= "</div>";
// If donotparse is set to a value, then we don't want
// to parse it into wiki text.
if (array_key_exists("donotparse", $args))
{
wfProfileOut('CategoryCloud::RenderNoParse');
return $text;
}
// Parse the results into wiki text
$output = $parser->parse($text,
$parser->mTitle, $parser->mOptions,
true, false);
// Finish up and return the results
wfProfileOut('CategoryCloud::Render');
return $output->getText();
}
- Use at Wikiprogress(Main Page)
<category-cloud category="" minsize="80" maxsize="200" order="count" maxitems="15" exclude="Templates"></category-cloud>
Using it on Mediawiki 1.6.10
editI'm using MediWiki version 1.6.10, and just changing the query, it started to work. I've used the query taken from SpecialCategories.php. It's:
$NScat = NS_CATEGORY; $categorylinks = $dbr->tableName( 'categorylinks' ); $sql= "SELECT cl_to as name, COUNT(*) as count FROM $categorylinks GROUP BY cl_to";
You will have to check where to put it, but I tested and it works. Thanks! --Fernando Negrotto
Using it on Mediawiki 1.9.3
editI'm using a german MediaWiki Version 1.9.3. The Extension doesn't work, every Category seems to be empty. I changed the SQL-Statement to:
$sql = 'SELECT cl.cl_to as name, count(*) as count ' . ' FROM categorylinks cl' . ' LEFT JOIN page AS p on p.page_title = cl.cl_to' . ' WHERE cl.cl_to LIKE ' . $dbr->addQuotes($categoryName) . ' GROUP BY cl.cl_to' . ' ORDER BY ' . $order;
Now it works. Have fun.
Proposed Extension
editWell... I added a tag in mine so it displays the article/subcategory count for each category. Just add this after line 221:
if ($args["showcount"]) { $catCount = $categories[str_replace(" ", "_", $cat)]; $text .= "<span style='font-size: 8px;vertical-align:sub;'>$catCount</span>"; }
Then it's as easy as {{#category-cloud:CategoryOfTopics|minsize=80|maxsize=125|showcount=1}}
Of course I could've saved the category name var before the "_"s where changed to " ", but I wanted to keep your code unscathed. --Phenome 15:35, 2 June 2007 (UTC)
- I'll add that into the next version, seems like a very useful feature. --Dylan Moonfire 16:09, 5 October 2007 (UTC)
Recursivity
edit"the extension does not recursively go through the sub-categories for additional categories." - Pity... it would be great if it did that. :) -- Schneelocke 20:09, 21 June 2007 (UTC)
- I'll add "recurse=X" where X is the number of levels to recurse. While I don't use it, it seems like a useful one to have. --Dylan Moonfire 16:10, 5 October 2007 (UTC)
Tag for every article in the given category
editIt generates a tag for every sub-category, but not article, in the given category. >> It should ;) And besides the option as tag cloud maybe like the regular list but different font sizes. --Sub
- The main reason I didn't do that is because it wouldn't really create different font sizes. Since there would be one and only one of an article inside a category, it would always have a count of 1. In effect, it would just be a link of everything inside the category, with no font sizes. --Dylan Moonfire 16:21, 5 October 2007 (UTC)
Installation/Use
editCould someone perhaps add a section of Installation and Use? I'm assuming you save it as TagCloud.php in the extension directory and then in LocalSettings.php you use
require_once("$IP/extensions/TagCloud.php");
Can anyone confirm? I would even make the section myself if this is correct.
--Dopple 11:00, 22 August 2007 (UTC)
- Yes, that is how you add it. I'll block in a section the next time I do an update (hopefully in a week or three). --Dylan Moonfire 16:11, 5 October 2007 (UTC)
1.10.1 Problems
editNotice: Undefined index: class in MYWIKIPATH/extensions/CategoryCloud/CategoryCloud.php on line 199 Notice: Undefined index: style in MYWIKIPATH/extensions/CategoryCloud/CategoryCloud.php on line 203
The above error occurs consistently with CategoryCloud enabled on my mediawiki 1.10.1 website. If anyone knows how to fix this or has had this problem before any assistance would be appreciated. Otherwise I'm going to take a look at the wikitagcloud extension and see if it can do (or can be modified to do) the same thing as the categorycloud extension. --Diploid 20:27, 24 August 2007 (UTC)
- Are you using a recent version of the CategoryCloud? I thought I fixed that with one of the later versions, by checking the key existence first. Which version of PHP are you using? You should be able to bypass it by just putting in class="" and style="" depending on your use. --Dylan Moonfire 16:19, 5 October 2007 (UTC)
I've the exact same problem with my Wiki :/
[Wed Dec 3 13:08:06 2008] [error] PHP Notice: Undefined index: class in MYWIKIPATH/extensions/CategoryCloud/category-cloud.php on line 199 [Wed Dec 3 13:08:06 2008] [error] PHP Notice: Undefined index: style in MYWIKIPATH/extensions/CategoryCloud/category-cloud.php on line 203
My installed software: MediaWiki v. 1.13.1, PHP v. 5.1.6 (apache), MySQL v. 4.1.22-log. --Danny373 12:05, 3 December 2008 (UTC)
Limiting tag cloud size
editA couple of other useful options would be:
- An attribute to limit the maximum number of tags in the cloud, such as
maxitems="50"
to show only the top 50 categories. This would be useful to prevent tag clouds getting out of control, especially if used in conjunction with the recursion option discussed above. - Some way of excluding categories that contain less than a certain number of articles. This would default to 1 to replicate the current behaviour of omitting empty categories, but could be set to 0 to include all categories, or some higher number to omit categories containing just a few entries. Again, this would be useful in controlling the maximum size of a tag cloud, but without putting an upper limit on the number of tags that can be displayed.
Other than that, it's a great extension. I've put it to work on the main page of PhilosophyWiki.
Version of My Fix
edit<?php
/**
* Parser hook extension adds a <category-cloud> tag to wiki markup. The
* following attributes are used:
* category = The category, minus the "Category:". if category is "" then All.
* order = "name" or "count"
* minsize = The minimum size, as percentage. Defaults to 80.
* maxsize = The maximum size, as a percentage. Defaults to 125.
* maxitems = Limiting tag cloud size. Defaults to 80. if order != "name".
* class = The CSS class to assign to the outer div, defaults
* to "category-cloud"
*
* There is also a parser function that uses {{#category-cloud:CategoryName}}
* with optional parameters being includes as "|param=value".
*
* @addtogroup Extensions
* @author Dylan R. E. Moonfire <contact@mfgames.com>
* @copyright � 2007 Dylan R. E. Moonfire
* @licence GNU General Public Licence 2.0
*/
// Make sure we are being properly
if( !defined( 'MEDIAWIKI' ) ) {
echo( "This file is an extension to the MediaWiki software "
. "and cannot be used standalone.\n" );
die( -1 );
}
// Hook up into MediaWiki
$wgExtensionFunctions[] = 'categoryCloud';
$wgHooks['LanguageGetMagic'][] = 'categoryCloudMagic';
$wgExtensionCredits['parserhook'][] = array(
'name' => 'Category Cloud',
'author' => 'Dylan R. E. Moonfire',
'description' => 'Create a tag cloud using categories.',
'url' => 'http://www.mediawiki.org/wiki/Extension:CategoryCloud',
'version' => '0.4.0'
);
function categoryCloud()
{
global $wgParser, $wgMessageCache;
// Set the hooks
$wgParser->setHook('category-cloud', 'categoryCloudRender');
$wgParser->setFunctionHook('category-cloud', 'categoryCloudFunction');
// Set our messages
$wgMessageCache->addMessages( array(
'categorycloud_missingcategory'
=> 'CategoryCloud: Cannot find category attribute',
'categorycloud_emptycategory'
=> 'CategoryCloud: Category is empty: ',
'categorycloud_cannotparse'
=> 'CategoryCloud: Cannot parse parameter: ',
));
}
// This manipulates the results of the CategoryCloud extension
// into the same function as the <category-cloud> tag.
function categoryCloudFunction($parser)
{
// Get the arguments
$fargs = func_get_args();
$input = array_shift($fargs);
// The first category is required
$category = array_shift($fargs);
$params = array();
$params["category"] = $category;
$params["donotparse"] = 1;
// Split the rest of the arguments
foreach ($fargs as $parm)
{
// Split it into its components
$split = split("=", $parm);
if (!$split[1])
{
return htmlspecialchars(wfMsg(
'categorycloud_cannotparse')
. $parm);
}
// Save it
$params[$split[0]] = $split[1];
}
// Return the cloud
return categoryCloudRender($input, $params, $parser);
}
// Sets up the magic for the parser functions
function categoryCloudMagic(&$magicWords, $langCode)
{
$magicWords['category-cloud'] = array(0, 'category-cloud');
return true;
}
// The actual processing
function categoryCloudRender($input, $args, &$parser)
{
// Imports
global $wgOut;
// Profiling
wfProfileIn('CategoryCloud::Render');
// Disable the cache, otherwise the cloud will only update
// itself when a user edits and saves the page.
$parser->disableCache();
// Get the database handler and specific controls
$dbr =& wfGetDB( DB_SLAVE );
$pageTable = $dbr->tableName('page');
$categoryLinksTable = $dbr->tableName('categorylinks');
// Normalize the order
$order = "name";
if (array_key_exists("order", $args)) $order = $args["order"];
if ($order != "count")
$order = "name";
else // we want reverse
$order = "count desc";
// Get the list of the subcategories and the number of children
if (!array_key_exists("category", $args))
{
return htmlspecialchars(wfMsg(
'categorycloud_missingcategory'));
}
$categoryName = $args["category"];
$maxitems = 80;
if (array_key_exists("maxitems", $args)) $outsize = $args["maxitems"];
// Build up an SQL of everything
$categoryNamespace = 14;
$sql = "SELECT p1.page_title as name, count(*) as count "
. "FROM $categoryLinksTable cl, $categoryLinksTable cl2, "
. " $pageTable p1, $pageTable p2 "
. "WHERE";
if ($categoryName)
{
$sql .= " cl.cl_to = " . $dbr->addQuotes($categoryName)
. " AND ";
}
$sql .= " cl.cl_from = p1.page_id "
. " AND cl2.cl_to = p1.page_title "
. " AND cl2.cl_from = p2.page_id "
. " AND p1.page_namespace = $categoryNamespace "
. " AND p1.page_id != p2.page_id "
. " GROUP BY p1.page_title "
. " ORDER BY $order ";
if ($order != "name")
{
$sql .= "LIMIT $maxitems OFFSET 0";
}
$res = $dbr->query($sql);
if ($dbr->numRows( $res ) == 0)
{
// Can't find category
return htmlspecialchars(wfMsg(
'categorycloud_emptycategory')
. $categoryName);
}
// Build up an array and keep track of mins and maxes
$minCount = -1;
$maxCount = -1;
$countAll = 0;
$total = 0;
$categories = array();
$names = array();
while ($row = $dbr->fetchObject($res))
{
// Pull out the fields
$name = $row->name;
$count = $row->count;
// Add it to the array and keep track of min/max
$categories[$name] = $count;
$names[] = $name;
$countAll++;
$total += $count;
if ($minCount < 0 || $minCount > $count)
$minCount = $count;
if ($maxCount < 0 || $maxCount < $count)
$maxCount = $count;
}
// Figure out the averages and font sizes
$minSize = 80;
$maxSize = 125;
if (array_key_exists("minsize", $args)) $minSize = $args["minsize"];
if (array_key_exists("maxsize", $args)) $maxSize = $args["maxsize"];
$countDelta = $maxCount - $minCount;
$sizeDelta = $maxSize - $minSize;
$average = $total / $countAll;
// Create the tag cloud div
$class = "category-cloud";
if ($args["class"]) $class = $args["class"];
$text = "<div class='$class'";
if ($args["style"])
$text .= " style='" . $args["style"]. "'";
$text .= ">";
// Go through the categories by name
foreach ($names as $cat)
{
// Wrap the link in a size
if ($countDelta == 0)
$size = 100;
else
$size = (($categories[$cat] - $minCount)
* $sizeDelta / $countDelta) + $minSize;
// Get the link
$cat = str_replace("_", " ", $cat);
$text .= " <span style='font-size: $size%;'>"
. "[[:Category:$cat|$cat]]</span>";
}
// Finish up
$text .= "</div>";
// If donotparse is set to a value, then we don't want
// to parse it into wiki text.
if (array_key_exists("donotparse", $args))
{
wfProfileOut('CategoryCloud::RenderNoParse');
return $text;
}
// Parse the results into wiki text
$output = $parser->parse($text,
$parser->mTitle, $parser->mOptions,
true, false);
// Finish up and return the results
wfProfileOut('CategoryCloud::Render');
return $output->getText();
}
?>
- Use at ProgWiki(Top50分類)
<category-cloud category="" minsize="80" maxsize="200" order="count" maxitems="50"></category-cloud>
Cloud text bunching up
editI'm trying to display the category cloud within a table on my main page, but the text is bunching up on top of itself, rendering it illegible. Is there a way to stop this from happening? --205.194.74.10 20:20, 20 April 2010 (UTC)
What is the right version?
editPlease, what is the right version? I copied the first source used on Wikiprogress, saved with name CategoryCloud.php and con syntax
<category-cloud category="" minsize="80" maxsize="200" order="count" maxitems="15" exclude="Templates"></category-cloud>
but I get Error 500 just in Main Page on my MW 1.19.2.(PHP 5.3)
Thanks in advance --WhiteTigerItaly (talk) 16:19, 4 October 2012 (UTC)
Using it on MediaWiki 1.26.2
editTried installing it on MediaWiki 1.26.2. I had to do some changes because MessageCache was removed in 1.18.0. The following code
// Set our messages $wgMessageCache->addMessages( array( 'categorycloud_missingcategory' => 'CategoryCloud: Cannot find category attribute', 'categorycloud_emptycategory' => 'CategoryCloud: Category is empty: ', 'categorycloud_cannotparse' => 'CategoryCloud: Cannot parse parameter: ', ));
was replaced by:
$wgHooks['categorycloud_missingcategory'][] = 'CategoryCloud: Cannot find category attribute'; $wgHooks['categorycloud_emptycategory'][] = 'CategoryCloud: Category is empty: '; $wgHooks['categorycloud_cannotparse'][] = 'CategoryCloud: Cannot parse parameter: ';