NonincludableNamespaces
This extension is designed to emulate and extend the function of the $wgNonincludableNamespaces configuration variable, which was introduced in MediaWiki v1.10.0.
- In versions of MW < 1.10.0, it emulates the functionality of the config variable, along with the additional functionality detailed below.
- In versions of MW >= 1.10.0 there is already code to handle this variable correctly, but the extension adds a couple of short-cuts that make configuration a bit simpler.
Usage[edit]
This extension adds the full functionality of $wgNonincludableNamespaces
, plus the enhancements below, to versions of MediaWiki < 1.10.0. From 1.10.0 upwards, $wgNonincludableNamespaces
exists natively in the software, in which case the extension simply implements the additional features.
Emulated features[edit]
- If
$wgNonincludableNamespaces
is not set, then all transclusion is allowed. - If
$wgNonincludableNamespaces
is an array then transclusion is not allowed for any namespaces included in the array. Elements must be numeric namespace ids.
Additional features[edit]
- If
$wgNonincludableNamespaces
is not an array then it is evaluated as a boolean with the following results:- If
True
then no transclusion is allowed, except from the template namespace. - If
False
then no transclusion is allowed at all.
- If
Developers[edit]
The extension defines the constant NIN_Installed
when it is loaded, so extension developers can check whether the $wgNonincludableNamespaces
variable is supported, either via MW or this extension, by using the following code:
if ( version_compare($wgVersion, '1.10.0', '>=') || NIN_Installed ) { // Installed }
Source[edit]
Copy the source code to a file called NonincludableNamespaces.php
in your extensions directory, and add the following line to the bottom of your LocalSettings.php
file:
include_once("extensions/NonincludableNamespaces.php");
You may then use the variable $wgNonincludableNamespaces
to configure your wiki, as described above.
Live sourcecode viewer: NonincludableNamespaces.php
Last modified: 2024-06-11 04:19:38
<?php if (!defined('MEDIAWIKI')) die("MediaWiki extensions cannot be run directly."); /** * An extension to emulate (and slightly extend) the functionality of * $wgNonincludableNamespaces. * * @author Mark Clements <mclements at kennel17 dot co dot uk> * @copyright Copyright © 2007-2024, Mark Clements * @license http://creativecommons.org/licenses/by-sa/2.5/ cc-by-sa 2.5 or later * @version $Rev: 2439 $ */ // The $wgVersion global variable was deprecated in MW 1.35, in favour of a new // constant. All code should use the constant rather than the variable, but for // backwards compatibility we create the constant if it is not already defined. // Note that the constant was back-ported to other release branches, but was not // present in the *.0 release, so they do not affect the minimum version requirements // for removing this shim. // @back-compat MW < 1.35 if (!defined("MW_VERSION")) define("MW_VERSION", $wgVersion); // Set version number from SVN revision tag. $pMCExt_Version = '$Rev: 2439 $'; $pMCExt_Version = substr($pMCExt_Version, 6, -2); // Set description depending on MW version in use. $pNIN_Description = '[http://www.mediawiki.org/wiki/Manual' . ':$wgNonincludableNamespaces $wgNonincludableNamespaces]'; if (version_compare(MW_VERSION, '1.10.0', '<')) { $pNIN_Description = 'Emulates (and extends) ' . $pNIN_Description . ' for MW < 1.10.0'; } else { $pNIN_Description = 'Makes configuration of ' . $pNIN_Description . ' easier for a few common situations'; } // Setup extension credits $wgExtensionCredits['other'][] = array( 'name' => "NonincludableNamespaces", 'version' => "r" . $pMCExt_Version, 'author' => "Mark Clements", 'description' => $pNIN_Description, 'url' => "http://www.mediawiki.org/wiki/User_talk:HappyDog", ); // Tidy up global variable. unset($pMCExt_Version); unset($pNIN_Description); $wgExtensionFunctions[] = "wfNIN_Setup"; /* Emulates the functionality of $wgNonincludableNamespaces: (http://www.mediawiki.org/wiki/Manual:%24wgNonincludableNamespaces) * If $wgNonincludableNamespaces is not set, then all transclusion is allowed. * If $wgNonincludableNamespaces is an array then transclusion is not allowed for any namespaces included in the array. Elements must be numeric namespace ids. ...with a few additional features: * If $wgNonincludableNamespaces is not an array, then it is evaluated as a boolean, with the following results: * IF TRUE then NO transclusion is allowed, except from the template namespace. * IF FALSE then NO transclusion is allowed at all. This extension adds the full functionality of $wgNonincludableNamespaces, including the above enhancements to versions of MediaWiki < 1.10.0. From 1.10.0 upwards, $wgNonincludableNamespaces exists natively in the software, in which case the extension simply implements the additional features described above. */ ///////////////////////////////////////////////// define("NIN_Installed", true); ///////////////////////////////////////////////// function wfNIN_Setup() { global $wgNonincludableNamespaces; global $wgCanonicalNamespaceNames; //////// TIDY INPUT // Check value of $wgNonincludableNamespaces and adjust it so it contains a // valid array. // * If not set, or False, convert to empty array. // * If True, convert // all Namespace IDs that should not be transcludable (or an empty array, if all // are transcludable). // NOT SET -> No namespaces disallowed. if (!isset($wgNonincludableNamespaces)) { $wgNonincludableNamespaces = array(); } // ARRAY -> Array of namespaces IDs that are blocked from // transclusion. No modification necessary. elseif (is_array($wgNonincludableNamespaces)) { // Drop through } // NON-ARRAY -> Evaluate as a boolean and block all namespaces (or // all but template namespace). else { // If $wgNonincludableNamespaces is true then pages in the template namespace // may be included, otherwise they are blocked from inclusion. if ($wgNonincludableNamespaces == true) $AllowTemplateInclusion = true; else $AllowTemplateInclusion = false; // Main namespace is not in CanonicalNamespaceNames, as it has no name, so // add it manually here. $wgNonincludableNamespaces = array(NS_MAIN); // Then add all defined namespaces (except the Template namespace if true). // This includes any namespaces specified in $wgExtraNamespaces. foreach ($wgCanonicalNamespaceNames as $NS_ID => $NS_Name) { // If $AllowTemplateInclusion is true then we don't include the template // namespace in the array. if (!($AllowTemplateInclusion && $NS_ID == NS_TEMPLATE)) { $wgNonincludableNamespaces[] = $NS_ID; } } } // //////// END TIDY INPUT // If version is < 1.10.0 (and there are any namespaces that need blocking) // we need to add a handler to deal with the above settings. // @back-compat MW < 1.10 if (version_compare(MW_VERSION, '1.10.0', '<')) { if (count($wgNonincludableNamespaces) > 0) $wgHooks['ParserAfterStrip'][] = "wfNIN_NonincludableNamespaces"; } // MW 1.10 and above will automatically handle the above settings appropriately. } ///////////////////////////////////////////////// // wfNIN_NonincludableNamespaces() // Callback hook for the ParserAfterStrip tag, to prevent inclusion from // non-includable namespaces on MediaWiki < 1.10. // This function is not called on MW 1.10 and above, as the functionality is now // built-in to MediaWiki. // @back-compat MW < 1.10 function wfNIN_NonincludableNamespaces(&$Parser, &$Text, &$StripState) { global $wgNonincludableNamespaces; global $wgContLang, $wgCanonicalNamespaceNames; $BlockedNamespaces = array(); $LocalNamespaces = $wgContLang->getNamespaces(); // Build list of blocked namespaces. foreach ($wgNonincludableNamespaces as $NS_ID) { // Add the 'no prefix' option for the template namespace (as well as the // actual namespace name(s), which are added below). if ($NS_ID == NS_TEMPLATE) $BlockedNamespaces[] = ""; // For the main namespace, there is no name so we just add the colon. if ($NS_ID == NS_MAIN) $BlockedNamespaces[] = ":"; // For all other namespaces, we add the canonical (English) name which works // on all wikis, plus the localised name (if different). else { if (isset($wgCanonicalNamespaceNames[$NS_ID])) $BlockedNamespaces[] = $wgCanonicalNamespaceNames[$NS_ID] . ":"; if (isset($LocalNamespaces[$NS_ID]) && $LocalNamespaces[$NS_ID] != $wgCanonicalNamespaceNames[$NS_ID]) { $BlockedNamespaces[] = $LocalNamespaces[$NS_ID] . ":"; } } } // For each blocked namespace, filter out all transclusions of that namespace. foreach ($BlockedNamespaces as $NS_Name) { // 0 - Entire matched text (from one char before start of template tag to // end of content). // 1 - Character before start of template tag (or blank if at start of // content). // 2 - Namespace (including colon) // 3 - Page name // 4 - Remainder of page content - to be checked to find correct closing tag. $Regex = '/(^|[^{])\{\{(' . $NS_Name . ')([^|}]+)(.*)/is'; $SearchText = $Text; // Match all transclusions of this namespace ($Matches[2] is namespace, // $Matches[3] is page). while (preg_match($Regex, $SearchText, $Matches)) { // Build the Link that will be used to replace the template parameter. $Link = $Matches[3]; if ($Matches[2] == "") $Link = $wgContLang->getNsText(NS_TEMPLATE); elseif ($Matches[2] != ":") $Link = $Matches[2] . $Link; $Link = "[[" . $Link . "]]"; // Work out the BadTemplateCode that will be replaced by the above link. $Pos = 0; // This is an array of tags that need to be closed, which is used like a // stack. Whenever an opening tag is found it is unshift()ed onto the // front of the array, and whenever a closing tag is matched, it is // shift()ed off again. This ensures that template calls that include // templates/special parameters/parser functions, etc. as parameters are // properly replaced. $TagsToMatch = array("}}"); $BadTemplateCode = ""; $Source = $Matches[4]; while (($NextClosePos = strpos($Source, $TagsToMatch[0], $Pos)) !== false) { $NextOpenPos = strpos($Source, "{{{", $Pos); if ($NextOpenPos !== false && $NextOpenPos < $NextClosePos) { array_unshift($TagsToMatch, "}}}"); $Pos = $NextOpenPos + 3; continue; } $NextOpenPos = strpos($Source, "{{", $Pos); if ($NextOpenPos !== false && $NextOpenPos < $NextClosePos) { array_unshift($TagsToMatch, "}}"); $Pos = $NextOpenPos + 2; continue; } // If no opening tags before the matching close tag, remove it from // the array and update the Pos to search from. $Pos = $NextClosePos + strlen($TagsToMatch[0]); array_shift($TagsToMatch); // If no more tags, then we can exit the loop. if (count($TagsToMatch) == 0) break; } $BadTemplateCode = substr($Source, 0, $Pos); // Only replace code if all tags are closed, otherwise this is an invalid // template inclusion and the software will ignore it automatically. if ($BadTemplateCode != "") { $BadTemplateCode = "{{" . $Matches[2] . $Matches[3] . $BadTemplateCode; $Text = str_replace($BadTemplateCode, $Link, $Text); } // Only search in the remainder of the text. This wouldn't be needed if // we could guarantee that all tags were closed, but as we can't we only // search the remainder to avoid getting into an infinite loop. $SearchText = $Source; } } return true; }