Extension:ConditionalMenus

This extension, allows for "conditional menus". It parses the following (example)

ConditionalMenus Extension Leet Category Abraham Category 3

Link1 Link2 Link3

What does it do?
In our example: If the page's name is "ConditionalMenus Extension" then anything inside the content tag is shown. If the page is of category "Leet Category" then anything inside the content tag is shown If the page is of category "Abraham Category" or is of a category that is of category "Abraham Category" (and so on...) then anything inside the content tag is shown In any other scenario nothing is parsed

What is it used for?
For example, you have navigation like:

Introduction Series information Category:Characters Guide Category:Episode List Goofs

And you want to display the list of characters but ONLY in the character pages (and maybe in an intro page), then you'd use:

Introduction Series information Category:Characters Guide Characters Guide Joe Characters Guide 2 Joe Mac Peter Category:Episode List Goofs

this would show the "Joe, Mac and Peter" links to the user ONLY if he is inside the "Characters Guide" page, or if he is inside the Joe page, or if he is inside any page that belongs to the "characters guide" category

This way if the user is browsing the "Introduction" pages he sees the small menu, and as soon as he enters to the "Characters Guide" category page he also sees the list of characters

How to use it

 * 1) Copy everything inside "Code" below into a file called "navigation.php" and put it under your "extensions" folder
 * 2) In LocalSettings.php, add: include("extensions/navigation.php");
 * 3) Done! :)

Code
NOTE: If you want to use special hooks like &lt;htmlets&gt; or even e.g. a &lt;div&gt; tag with attributes (no idea why) within the content of your conditional menu, you need an alternative version that you will find below.

setHook("submenu", "submenusExtension" ); }

/** * This extension parses: * *        *        *        *        *        *  */ function submenusExtension($input) {       global $wgTitle, $wgUser, $wgArticle, $wgContLang;

$namespaceNames = $wgContLang->getNamespaces; $categoryNamespaceName = $namespaceNames[NS_CATEGORY]; // initialize our array $matches = array;

// find out categories this page belongs to       $categories = $wgTitle->getParentCategories; if (!is_array($categories)) $categories = array; $categories = array_keys($categories);

// strip namespace prefix foreach ($categories as &$category) { $category = preg_replace("@($categoryNamespaceName:\s?)?(.*)@is", "\\2", $category); }       // process allow list preg_match_all("@ (.*) @isU", $input, $matches); $allowtitle = array; foreach ($matches[1] as $match) {               $allowtitle[] = trim($match); }       preg_match_all("@ (.*) @isU", $input, $matches); $allowcategory = array; foreach ($matches[1] as $match) {               $match = preg_replace("@($categoryNamespaceName:\s?)?(.*)@is", "\\2", $match); $allowcategory[] = trim($match); }

preg_match_all("@ (.*) @isU", $input, $matches); $allowancestor = array; foreach ($matches[1] as $match) {		$match = preg_replace("@($categoryNamespaceName:\s?)?(.*)@is", "\\2", $match); $allowancestor[] = trim($match); }

// check if we are to parse content $allowed = false; if (in_array($wgTitle->mTextform, $allowtitle) || in_array($wgTitle->mDbkeyform, $allowtitle)) {               $allowed = true; }	// No matching title? Maybe the page is in an "allow category". if (!$allowed) { foreach ($categories as $category) {               	if (in_array(trim($category), $allowcategory)) {                       	$allowed = true; break; }                      	}	}

// Still not allowed? Maybe the page has an "allow ancestor category". if (!$allowed) { foreach ($allowancestor as $ancestor) { if (hasAncestorCategory($wgTitle, $ancestor, $categoryNamespaceName)) {				$allowed = true; break; }		}	}

// if allowed print content, otherwise return blank if (!$allowed) {               return ""; }       preg_match("@ (.*) @isU", $input, $matches); $content = trim($matches[1]); if (!$content) {               return ""; }       // parse the content $parser = new Parser; $parserOptions = ParserOptions::newFromUser($wgUser); $output = $parser->parse($content, $wgTitle, $parserOptions); // rather ugly hack to delete empty dots $returnval = /*trim(*/$output->getText/*)*/; preg_match("@ (.*) @isU", $input, $matches); $level = intval(trim($matches[1])); if ($level) {               $returnval = preg_replace("@ (.*) @isU", "\\1", $returnval); $returnval = preg_replace("@^.*$@m", "\\0", $returnval); $returnval = preg_replace("@\s*@", "", $returnval); for ($i = 0; $i < $level; $i++) {                       $returnval = "$returnval"; }       }        // return final value return "\r\n".$returnval; }

/** * Checks whether a page is a descendant of a given category. * @param title a Title object, representing the given page * @param targetName the name of the given category, WITHOUT prefix * @param categoryNamespaceName the name of the category namespace * @returns true if the page represented by $title is a descendant *         of a category witht the name $targetName */ function hasAncestorCategory($title, $targetName, $categoryNamespaceName) { $parentNames = $title->getParentCategories; if (!is_array($parentNames)) $parentNames = array; $parentNames = array_keys($parentNames);

foreach ($parentNames as &$parentName) { if ($parentName == "$categoryNamespaceName:$targetName" ||			hasAncestorCategory(Title::newFromText($parentName), $targetName, $categoryNamespaceName)) {			return true; }       }

return false; }

?>

Code (Alternative version using Parser->recursiveTagParse
Instead of creating a new Parser object for the &lt;content&gt;, this version uses the existing Parser and its method recursiveTagParse, which is the preferred way to parse from within hooks, I suppose. However, I just went by examples and no further than making this extension work for my purpose, so I can by no means guarantee that this version works correctly in the general case, and so I left the old version above intact. Comments and improvements are appreciated. Kevang 15:29, 13 April 2007 (UTC)

setHook("submenu", "submenusExtension" ); }

/** * This extension parses: * *        *        *        *        *        *  */ function submenusExtension($input, $argv, $parser) {       global $wgTitle, $wgUser, $wgArticle, $wgContLang;

$namespaceNames = $wgContLang->getNamespaces; $categoryNamespaceName = $namespaceNames[NS_CATEGORY]; // initialize our array $matches = array;

// find out categories this page belongs to       $categories = $wgTitle->getParentCategories; if (!is_array($categories)) $categories = array; $categories = array_keys($categories);

// strip namespace prefix foreach ($categories as &$category) { $category = preg_replace("@($categoryNamespaceName:\s?)?(.*)@is", "\\2", $category); }       // process allow list preg_match_all("@ (.*) @isU", $input, $matches); $allowtitle = array; foreach ($matches[1] as $match) {               $allowtitle[] = trim($match); }       preg_match_all("@ (.*) @isU", $input, $matches); $allowcategory = array; foreach ($matches[1] as $match) {               $match = preg_replace("@($categoryNamespaceName:\s?)?(.*)@is", "\\2", $match); $allowcategory[] = trim($match); }

preg_match_all("@ (.*) @isU", $input, $matches); $allowancestor = array; foreach ($matches[1] as $match) {		$match = preg_replace("@($categoryNamespaceName:\s?)?(.*)@is", "\\2", $match); $allowancestor[] = trim($match); }

// check if we are to parse content $allowed = false; if (in_array($wgTitle->mTextform, $allowtitle) || in_array($wgTitle->mDbkeyform, $allowtitle)) {               $allowed = true; }	// No matching title? Maybe the page is in an "allow category". if (!$allowed) { foreach ($categories as $category) {               	if (in_array(trim($category), $allowcategory)) {                       	$allowed = true; break; }                      	}	}

// Still not allowed? Maybe the page has an "allow ancestor category". if (!$allowed) { foreach ($allowancestor as $ancestor) { if (hasAncestorCategory($wgTitle, $ancestor, $categoryNamespaceName)) {				$allowed = true; break; }		}	}

// if allowed print content, otherwise return blank if (!$allowed) {               return ""; }       preg_match("@ (.*) @isU", $input, $matches); $content = trim($matches[1]); if (!$content) {               return ""; }       // parse the content $output = $parser->recursiveTagParse($content); // rather ugly hack to delete empty dots $returnval = trim($output); preg_match("@ (.*) @isU", $input, $matches); $level = intval(trim($matches[1])); if ($level) {               $returnval = preg_replace("@ (.*) @isU", "\\1", $returnval); $returnval = preg_replace("@^.*$@m", "\\0", $returnval); $returnval = preg_replace("@\s*@", "", $returnval); for ($i = 0; $i < $level; $i++) {                       $returnval = "$returnval"; }       }        // return final value return "\r\n".$returnval; }

/** * Checks whether a page is a descendant of a given category. * @param title a Title object, representing the given page * @param targetName the name of the given category, WITHOUT prefix * @param categoryNamespaceName the name of the category namespace * @returns true if the page represented by $title is a descendant *         of a category witht the name $targetName */ function hasAncestorCategory($title, $targetName, $categoryNamespaceName) { $parentNames = $title->getParentCategories; if (!is_array($parentNames)) $parentNames = array; $parentNames = array_keys($parentNames);

foreach ($parentNames as &$parentName) { if ($parentName == "$categoryNamespaceName:$targetName" ||			hasAncestorCategory(Title::newFromText($parentName), $targetName, $categoryNamespaceName)) {			return true; }       }

return false; }

?>