Extension talk:NiceCategoryList2

New option to sort regarding the key
I added a new option to avoid ncl to sort the list alphabetically, to have index key sorting like mediawiki does.

Thanks for your extension of the extension. Jej 10:46, 9 November 2006 (UTC)

Cannot add more than one set of ncl tags
Why can't I add more than one set of tags in a page?

Sarwar (sarwar@metafour.com)


 * It seems to be working for me... maybe try the new version? JohanTheGhost 00:42, 2 March 2007 (UTC)

Broken with 1.9a
I'm running a recently-upgraded 1.9a, and I get this with any NCL listing: UNIQa23a55a20531f14-ncl-00000002-QINU Or something similar anyway. Different everytime I load the page. Not sure what's up, can you perhaps tell me what to fix? &#8465;ilver&#167;&#8465;ide 18:39, 4 January 2007 (UTC)


 * Yup, I've finally run into this myself. I've uploaded a new version which seems to fix it. Cheers, JohanTheGhost 00:36, 2 March 2007 (UTC)


 * Do you have this fix in v1.0 also? I have MW 1.8.3 and recently run into same problem... Thanks! Khitrenovich 11:05, 25 July 2007 (UTC)

Help (mediawiki 1.6,ncl 1.0)
I've installed the code[includes....] in my localsetting.php, and upload the version 1.0 in extensions. And when i put category:... , it display the category listing when I modified the page but when I saved, it isnt display anything.(sorry for my bad english) Idon't understand.--Add 02:23, 19 June 2007 (UTC)


 * I don't know why that would be, but it sounds like a cache issue.... edit it again, and do "Show preview" -- does the list appear? And when you save again, what exactly is displayed? JohanTheGhost 15:23, 20 June 2007 (UTC)


 * I have already test that, but when I do "Preview" it display correctly the category, but when i save it display "nothing", a blank. I have put require_once("$IP/extensions/NiceCategoryList.php");, maybe if I change it to require_once($IP."/extensions/NiceCategoryList.php"); but I thing that it's no importante.I test and i post if it anything changed.--Add 02:26, 21 June 2007 (UTC)


 * The only thing I can think of is that another extension may be interfering with it. Someone recently had a similar problem with the SelectCategory extension.  Do you have other extensions installed?  What happens if you disable them (comment out the "require_once" lines from LocalSettings)?  JohanTheGhost 14:51, 21 June 2007 (UTC)



MediaWiki: 1.6.10 PHP: 4.4.3-dev (cgi-fcgi) MySQL: 5.0.37 Extensions:

* Special pages: o Edit Count, Gets the edit count of a user, by Benjamin Peterson o MakeBot, Special page allows local bureaucrats to grant and revoke bot permissions, by Rob Church * Parser hooks: o CharInsert, Allows creation of JavaScript box for inserting non-standard characters, by Brion Vibber o Edit Count, Gets the edit count of a user, by Benjamin Peterson o MultipleUpload, Allows users to upload several files at once., by Travis Derouin o NiceCategoryList, generate a category page showing all pages in a category, including subcategories, by Kichik o Sort, Simplify the creation of sorted lists., by Rob Church * Other: o Newuserlog, adds a log of account creations to Special:Log, by Ævar Arnfjörð Bjarmason

style=compact not working?
Hi,

Great extension! Im fairly new to MediaWiki but would really like to use your extension. I installed it but for some reason when I specify the style=compact option nothing shows up. If I used the style=bullet option it works, but I'm really after that nice compact look :(

Im running php5, MW 1.10. Tried NiceCategoryList version 1 but still no luck. Any idea?

Thanks again

Cheers, Dave (psytwo@gmail.com)


 * Weird. I just upgraded my test wiki to 1.10, and style=compact works fine for me; in fact, it's the style I use for my main index.  Here's the exact code (it's in a template which I include in category pages):

Category:
 * Try these exact parameters; if there's some parameter combination which doesn't work, let me know, and I'll try to fix it. Otherwise, all I can suggest is that you have some strange conflict with another extension you have installed.  Try temporarily disabling them one by one to see if you can find which one is causing problems? JohanTheGhost 15:50, 5 July 2007 (UTC)


 * JohanTheGhost: style=compact and headings=bullet don't quite work together if you have categories which have non-category siblings. For example, if you have a category 1, and you have 1.1 and 1.2 under 1, but you also have an articles X and Y under category 1, then NCL2 renders something like this:


 * Category 1
 * Article X • Article Y


 * Category 1.1
 * Category 1.2
 * Notice that the articles introduce a newline before the subcategories. MediaWiki thinks this means that the subcategories are not part of the category list, and puts two bullets in front of Category 1.1. You can solve this by doing, e.g.,


 * Category 1 :Article X • Article Y
 * Category 1.1
 * Category 1.2
 * Doing this without breaking the other layout types looks a little annoying, though.
 * Follow-up: I think I fixed that bug, plus made "style=bullet headings=bullet" work properly in the situation where categories and articles are siblings. I posted my changes as version 2.1.

Allow for parser syntax
This is a great extension. However, I was trying to use it in a template and ran into an issue that the template arguements were not getting parsed by the extension. This is typical for non parser-style extensions. I have made the modifications to your code, v2.0. See below Category:Some Category * * 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). * * Examples: * 1. This: *     Category:Some Category *   generates a full, recursive listing. * * 2. Use this in a template: *     Category: *   and include it in major category pages to provide a nice 2-level (or however *    many you like) index of the category. * * 3. This: *     Category:Categories *   generates a full category listing, with indentation indicating category *   containment. * * Caveat: When used in a template, the category list will not refresh * immediately when reloaded; edit and save the article to see updates. */

if (!defined('MEDIAWIKI')) die;

$wgExtensionFunctions[] = 'wfNiceCategoryList'; $wgHooks['LanguageGetMagic'][] = 'wfNclParserFunction_Magic'; $wgExtensionCredits['parserhook'][] = array( 'name' =>        'NiceCategoryList',  'author' =>      'Kichik, Johan the Ghost',  'url' =>         'http://meta.wikimedia.org/wiki/NiceCategoryList_extension',  'description' => 'generate a category page showing all pages in a category, including subcategories', );

function wfNclParserFunction_Magic( &$magicWords, $langCode ) { # Add the magic word # The first array element is case sensitive, in this case it is not case sensitive # All remaining elements are synonyms for our parser function $magicWords['ncl'] = array( 0, 'ncl' ); # unless we return true, other parser functions extensions won't get loaded. return true; }

/* * Setup Nice Category List extension. * Sets a parser hook for. */ function wfNiceCategoryList { new NiceCategoryList; }

/* * Simple class to hold category's title, links list, * and categories list. */ class NiceCategoryList_Links {

private $title; private $articles = array; private $categories = array; private $subcats = array;

public function __construct($title) { $this->title = $title; }

public function addCategory($title, $links) { $this->subcats[] = $title; if ($links) $this->categories[] = $links; }

public function addArticle($title) { $this->articles[] = $title; }

/*    * Get the title of this category. */   public function getTitle { return $this->title; }

/*    * Get the titles of the sub-categories of this category. */   public function getCatTitles { return $this->subcats; }

/*    * Get the titles of the articles in this category. */   public function getArtTitles { return $this->articles; }

/*    * Get the link records of the sub-categories of this category, * if we have them. * Returns an array of NiceCategoryList_Links objects. */   public function getCategories { return $this->categories; }

/*    * Return true iff we have link records for the sub-categories * of this category. */   public function hasCatLinks { return count($this->categories) > 0; }

/*    * Title comparison function */   private function titleCmp($a, $b) { return $a->getText > $b->getText; }

/*    * NiceCategoryList_Links comparison function */   private function categoryCmp($a, $b) { return self::titleCmp($a->title, $b->title); }

/*    * Sort links and categories alphabetically. */   public function sort { usort($this->articles, array(&$this, "titleCmp")); usort($this->categories, array(&$this, "categoryCmp")); }

}

class NiceCategoryList {

////////////////////////////////////////////////////////////////////////   // Configuration ////////////////////////////////////////////////////////////////////////

/*    * Default settings for the category list. */   private $settings = 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 according to the                                     // index key.    );

////////////////////////////////////////////////////////////////////////   // Constructor ////////////////////////////////////////////////////////////////////////

/*    * Setup Nice Category List extension. * Sets a parser hook for. */   public function __construct { global $wgParser; $wgParser->setHook('ncl', array(&$this, 'hookNcl')); $wgParser->setFunctionHook('ncl', array(&$this, 'hookParserNcl')); }

////////////////////////////////////////////////////////////////////////   // Hook ////////////////////////////////////////////////////////////////////////

/*    * The hook function. Handles. *    $category   The tag's text content (between and ); *                this is the name of the category we want to index. *    $argv       List of tag parameters; these can be any of the settings *                in $this->settings. *    $parser     Parser handle. */   public function hookNcl($category, $argv, &$parser) { // Get any user-specified parameters, and save them in $this->settings. foreach (array_keys($argv) as $key) $this->settings[$key] = $argv[$key];

return NiceCategoryList::doNcl($category, &$parser, false); }

public function hookParserNcl(&$parser, $params) { $options = preg_split('/\s?,\s?/', $params, -1, PREG_SPLIT_NO_EMPTY); $this->settings['category'] = ''; foreach ($options as $option) { $nameval = preg_split('/\s*=\s*/', $option); $this->settings[$nameval[0]] = $nameval[1]; }

return NiceCategoryList::doNcl($this->settings['category'], &$parser, true); }

public function doNcl($category, &$parser, $is_parser) { // Replace variables in $category by calling the parser on it. This // allows it to use, etc.       $localParser = new Parser; $category = $localParser->parse($category, $parser->mTitle, $parser->mOptions, false); $category = $category->getText;

// Make a Title objhect for the requested category. $title = Title::newFromText($category); if (!$title) return ' Failed to create title! ';

// Get the database handle, and get all the category links for // this category. $dbr =& wfGetDB(DB_SLAVE); $catData = $this->searchCategory($dbr, $title, 0);

// Generate the category listing. $output = $this->outputCategory($catData);

// There's no need for a TOC, so suppress it. $output .= "\n";

if ($is_parser) { return $output; } else { // Convert the listing wikitext into HTML and return it. $localParser = new Parser; $output = $localParser->parse($output, $parser->mTitle, $parser->mOptions); return $output->getText; }   }

////////////////////////////////////////////////////////////////////////   // Database Access ////////////////////////////////////////////////////////////////////////

/*    * Get all of the direct and indirect members of a given category: ie.     * all of the articles and categories which belong to that category * and its children. *    $dbr        The database handle *    $catTitle   The Title object for the category to search *    $depth      Our current recursion depth: starts at 0 *    $processed  List of categories that have been searched to date *                (to prevent looping) *    * Returns null if this category has already been searched; otherwise, * a NiceCategoryList_Links object for the given category, containing all * the sub-categories and member articles. */   private function searchCategory($dbr, $catTitle, $depth, $processed = array) { // Avoid endless recursion by making sure we haven't been here before. if (in_array($catTitle->getText, $processed)) return null; $processed[] = $catTitle->getText;

// Get all of the category links for this category. $links = $this->getCategoryLinks($dbr, $catTitle);

// Build a list of items which belong to this category. $cl = new NiceCategoryList_Links($catTitle); foreach ($links as $l) { // Make a Title for this item. $title = Title::makeTitle($l->page_namespace, $l->page_title);

if ($title->getNamespace == NS_CATEGORY) { // This item is itself a category: recurse to find all its // links, unless we've hit maxdepth. $subLinks = null; if ($depth + 1 < $this->settings['maxdepth']) $subLinks = $this->searchCategory($dbr, $title,                                                     $depth + 1, $processed);

// Record the subcategory name, and its links if we got any. $cl->addCategory($title, $subLinks); } else { // This is a regular page; just add it to the list. $cl->addArticle($title); }       }

// Sort the item lists, if requested. (Thanks, Jej.) if ($this->settings['sort']) $cl->sort;

return $cl; }

/*    * Get all of the direct members of a given category. *    $dbr        The database handle *    $title      The Title object for the category to search *    * Returns an array of objects, each representing one member of the named * caregory. Each object contains the following fields from the database: *     page_title *     page_namespace *     cl_sortkey */   private function getCategoryLinks($dbr, $title) { // Query the database. $res = $dbr->select(           array('page', 'categorylinks'),            array('page_title', 'page_namespace', 'cl_sortkey'),            array('cl_from = page_id', 'cl_to' => $title->getDBKey),            '',            array('ORDER BY' => 'cl_sortkey')        ); if ($res === false) return array;

// Convert the results list into an array. $list = array; while ($x = $dbr->fetchObject($res)) $list[] = $x;

// Free the results. $dbr->freeResult($res);

return $list; }

////////////////////////////////////////////////////////////////////////   // Output ////////////////////////////////////////////////////////////////////////

/*    * Generate output for the list. */   function outputCategory($category, $level = 0) { global $wgContLang;

$output = '';

// The second level and onwards has a heading. // The heading gets smaller as the level grows. if ($level > 0) { $title = $category->getTitle; $ptitle = $title->getPrefixedText; $title = $wgContLang->convert($title->getText); $link = "" . $title . "";

// Do the heading. If settings['headings'] == 'head', then // the heading is a real Wiki heading; otherwise, it's a nested // bullet item. if ($this->settings['headings'] == 'head') { $heading = str_repeat('=', $level + $this->settings['headstart']); $output .= $heading. $title. $heading. "\n"; } else { $stars = str_repeat('*', $level); if ($level <= 1) $output .= " \n". $stars. " " . $link. " \n"; else $output .= $stars. " " . $link. "\n"; }       }

// Now generate the category output. We put the various items in       // $pieces at first. $pieces = array;

// Output each subcategory's name, if we don't have a real // listing of its contents (because we hit maxdepth), and // if settings['showcats']. if ($this->settings['showcats'] && !$category->hasCatLinks) { $subCatTitles = $category->getCatTitles; foreach ($subCatTitles as $title) { $ptitle = $title->getPrefixedText; $title = $wgContLang->convert($title->getText); $disp = "" . $title . ""; $pieces[] = $disp; }       }

// Output each article in the category, if settings['showarts']. if ($this->settings['showarts']) { $articleTitles = $category->getArtTitles; foreach ($articleTitles as $link) { $ptitle = $link->getPrefixedText; $title = $link->getText; $disp = "" . $title . ""; $pieces[] = $disp; }       }

// If we got some items, then display them in the requested style. if (count($pieces) > 0) { if ($this->settings['style'] == 'bullet') $output .= "* ". implode("\n* ", $pieces). "\n"; else { $pre = $level == 0 ? " " : str_repeat('*', $level - 1). ':';               $post = $level == 0 ? " " : '';               $output .= $pre. implode(" &bull; ", $pieces). $post. " \n"; }       }

// Recurse into each subcategory. $subCategories = $category->getCategories; foreach ($subCategories as $cat) $output .= $this->outputCategory($cat, $level + 1);

return $output; }

}

?>