User:Robchurch/NCL fixup
From MediaWiki.org
Hacked-about version of JohanTheGhost's hacked-about version; this one shouldn't cause problems with the parser chain referencing $wgOut.
<?php
/*
* Nice Category List extension.
* Generates a list of all pages in the category, including subcategories.
* Unlike the default category list, the generated list is flat and shows
* well, even with long page names.
*
* Usage:
* <ncl [options]>Category:Some Category</ncl>
*
* The following options are available:
* maxdepth Maximum category depth; default 32
* style 'bullet' to show category contents as bullet lists
* 'compact' for a more compact listing
* showcats Non-0 to display sub-category links in "bottom" (ie.
* maxdepth) categories (default 0).
* showarts Non-0 to display articles in categories (default 1).
* headings 'head' to display category headings as Wiki headings;
* 'bullet' to display category headings as large bullets
* ('bullet' works well with 'style=compact').
* headstart With 'headings=head', the heading level to list
* top-level categories with (level increases for sub-cats).
* sort With 'sort=1', the list is sorted alphabetically
* else the category index key is used (as usual)
*
* Examples:
* 1. This:
* <ncl>Category:Some Category</ncl>
* generates a full, recursive listing.
*
* 2. Use this in a template:
* <ncl style=compact maxdepth=2 headings=bullet headstart=2
* showcats=1 showarts=1>Category:{{PAGENAME}}</ncl>
* and include it in major category pages to provide a nice 2-level (or however
* many you like) index of the category.
*
* 3. This:
* <ncl style=compact headings=bullet headstart=2 showcats=1
* showarts=0>Category:Categories</ncl>
* generates a full cagtegory listing, with indentation indicating category
* containment.
*/
if (!defined('MEDIAWIKI')) die();
$wgExtensionFunctions[] = 'wfNiceCategoryList';
$wgExtensionCredits['parserhook'][] = array(
'name'=>'NiceCategoryList',
'author'=>'Kichik',
'url'=>'http://meta.wikimedia.org/wiki/NiceCategoryList_extension',
'description'=>'generate a category page showing all pages in a category, including subcategories',
);
/*
* Global settings for the Nice Category List extension.
*/
$wgNiceCategoryListSettings = array(
'maxdepth' => 32, // Sanity stop level.
'style' => 'bullet', // Default style for "leaf" level.
'showcats' => 0, // Non-0 to display sub-cat links in a category.
'showarts' => 1, // Non-0 to display article links in a category.
'headings' => 'head', // Show category headings as headings.
'headstart' => 1, // Heading level to start at.
'sort' => 0, // Non-0 to sort the list alphabetically, else sort the list regarding the index key
);
/*
* Setup Nice Category List extension.
* Sets a parser hook for <ncl></ncl>.
*/
function wfNiceCategoryList() {
global $wgParser;
$wgParser->setHook('ncl', 'hookNiceCategoryList');
}
/*
* The hook function. Handles <ncl></ncl>.
* Receives the category name as a parameter.
*/
function hookNiceCategoryList($category, $argv, &$parser) {
global $wgNiceCategoryListSettings;
// Get any user-specified parameters.
foreach (array_keys($argv) as $key) {
$wgNiceCategoryListSettings[$key] = $argv[$key];
}
// Replace variables in cat. This is still pretty crappy, as template
// params still won't work.
$poutput = $parser->parse( $category, $parser->mTitle, $parser->mOptions, false, false );
$category = $poutput->getText();
$dbr =& wfGetDB(DB_SLAVE);
$title = Title::newFromText($category);
if (!$title) return '';
$ct = fetchCategoryLinks($dbr, $title, 0);
$poutput = $parser->parse( outputCategory( $ct ), $parser->mTitle, $parser->mOptions, true, false );
return $poutput->getText();
}
/*
* Get all links in a category.
*/
function getCategoryLinks($dbr, $title) {
return $dbr->select(
array( 'page', 'categorylinks' ),
array( 'page_title', 'page_namespace', 'page_len', 'cl_sortkey' ),
array( 'cl_from = page_id',
'cl_to' => $title->getDBKey()),
#'page_is_redirect' => 0),
#+ $pageCondition,
'',
array( 'ORDER BY' => 'cl_sortkey' ) );
}
/*
* Title comparison function
*/
function titleCmp($a, $b) {
return $a->getText() > $b->getText();
}
/*
* CategoryLinks comparison function
*/
function categoryCmp($a, $b) {
return titleCmp($a->title, $b->title);
}
/*
* Simple class to hold category's title, links list,
* and categories list.
*/
class CategoryLinks {
var $title;
var $links = array();
var $categories = array();
var $subcats = array();
function CategoryLinks($title) {
$this->title = $title;
}
/*
* Sort links and categories alphabetically.
*/
function sort() {
global $wgNiceCategoryListSettings;
if ($wgNiceCategoryListSettings['sort']) {
usort($this->links, "titleCmp");
usort($this->categories, "categoryCmp");
}
}
}
/*
*
*/
function fetchCategoryLinks($dbr, $category_title, $depth, $processed = array()) {
global $wgNiceCategoryListSettings;
// avoid recursion
if (in_array($category_title->getText(), $processed))
return NULL;
$processed[] = $category_title->getText();
$cl = new CategoryLinks($category_title);
// get category links from db
$res = getCategoryLinks($dbr, $category_title);
// process all category links
while ($x = $dbr->fetchObject($res)) {
$title = Title::makeTitle($x->page_namespace, $x->page_title);
if ($title->getNamespace() == NS_CATEGORY) {
// if category, recurse. Stop at max depth - but record the cat.
if ($depth + 1 < $wgNiceCategoryListSettings['maxdepth']) {
$fc = fetchCategoryLinks($dbr, $title, $depth + 1, $processed);
if ($fc) $cl->categories[] = $fc;
}
$cl->subcats[] = $title;
} else {
// if regular page, add to list
$cl->links[] = $title;
}
}
// sort
$cl->sort();
return $cl;
}
/*
* Generate output for the list.
*/
function outputCategory($category, $level = 0) {
global $wgContLang, $wgUser;
global $wgNiceCategoryListSettings;
$sk =& $wgUser->getSkin();
if ($level == 0) {
// no need for TOC
$output = "__NOTOC__\n";
} else {
// second level and onwards, has a heading.
// the heading gets smaller as the level grows.
$title = $category->title;
$ptitle = $title->getPrefixedText();
$title = $wgContLang->convert($title->getText());
$link = "[[:" . $ptitle . "|'''" . $title . "''']]";
if ($wgNiceCategoryListSettings['headings'] == 'head') {
$heading = str_repeat('=', $level + $wgNiceCategoryListSettings['headstart']);
$output = $heading . $title . $heading . "\n";
} else {
$stars = str_repeat('*', $level);
if ($level <= 1)
$output = "<big>\n" . $stars . " " . $link . "</big>\n";
else
$output = $stars . " " . $link . "\n";
}
}
$pieces = array();
// output each subcategory
if ($wgNiceCategoryListSettings['showcats'] && !$category->categories) {
foreach ($category->subcats as $title) {
$ptitle = $title->getPrefixedText();
$title = $wgContLang->convert($title->getText());
$disp = "[[:" . $ptitle . "|'''" . $title . "''']]";
$pieces[] = $disp;
}
}
// output each link
if ($wgNiceCategoryListSettings['showarts']) {
foreach ($category->links as $link) {
$ptitle = $link->getPrefixedText();
$title = $link->getText();
$disp = "[[:" . $ptitle . "|" . $title . "]]";
$pieces[] = $disp;
}
}
if (count($pieces) > 0) {
if ($wgNiceCategoryListSettings['style'] == 'bullet')
$output .= "* " . implode("\n* ", $pieces) . "\n";
else
$output .= ":<div style=\"font-size: small\">" . implode(" ยค ", $pieces) . "</div><br>\n";
}
// recurse into each subcategory
foreach ($category->categories as $cat) {
$output .= outputCategory($cat, $level + 1);
}
return $output;
}
?>

