Last modified: 2011-03-13 18:05:07 UTC

Wikimedia Bugzilla is closed!

Wikimedia has migrated from Bugzilla to Phabricator. Bug reports should be created and updated in Wikimedia Phabricator instead. Please create an account in Phabricator and add your Bugzilla email address to it.
Wikimedia Bugzilla is read-only. If you try to edit or create any bug report in Bugzilla you will be shown an intentional error message.
In order to access the Phabricator task corresponding to a Bugzilla report, just remove "static-" from its URL.
You could still run searches in Bugzilla or access your list of votes but bug reports will obviously not be up-to-date in Bugzilla.
Bug 14204 - Extension data: Optionally include example installation + example usage.
Extension data: Optionally include example installation + example usage.
Product: MediaWiki
Classification: Unclassified
General/Unknown (Other open bugs)
All All
: Lowest enhancement (vote)
: ---
Assigned To: Nobody - You can work on this!
Depends on:
  Show dependency treegraph
Reported: 2008-05-21 06:55 UTC by Nick Jenkins
Modified: 2011-03-13 18:05 UTC (History)
2 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Description Nick Jenkins 2008-05-21 06:55:54 UTC
It could be handy for users and for testers if extensions could optionally include an example of the minimal additions required to LocalSettings.php for installing them, and an example of how to use the extension (for Tag extensions or Parser Function extensions that alter wiki syntax). This is partly a problem of agreeing on a good convention, and partly a technical problem.

One possible way might be (using the ImageMap extension as an example) if two elements were added to the $wgExtensionCredits array:
$wgExtensionCredits['parserhook']['ImageMap'] = array(
        'name'           => 'ImageMap',
        'svn-date' => '$LastChangedDate: 2008-05-06 21:59:58 +1000 (Tue, 06 May 2008) $',
        'svn-revision' => '$LastChangedRevision: 34306 $',
        'author'         => 'Tim Starling',
        'url'            => '',
        'description'    => 'Allows client-side clickable image maps using <nowiki><imagemap></nowiki> tag.',
        'descriptionmsg' => 'imagemap_desc',
+        'usage-example'  => "<imagemap>\nImage:Framing_hammer_956.jpg|\nrect 1 1 299 218 [[Use a Hammer Safely]]\ndesc none\n</imagemap>",
+        'basic-install'  => 'require_once( "$IP/extensions/ImageMap/ImageMap.php" );',

... or alternatively, put all of this configuration information into a standard INI file name - e.g. "config.ini" - as having a standard file name containing this type of data could be useful to testers, and for testing software, which could now know how to install and smoketest an extension. An example config.ini could be:
name = ImageMap
svn-date = "$LastChangedDate: 2008-05-06 21:59:58 +1000 (Tue, 06 May 2008) $"
svn-revision = "$LastChangedRevision: 34306 $"
author = "Tim Starling"
url = ""
description = "Allows client-side clickable image maps using <nowiki><imagemap></nowiki> tag."
descriptionmsg = "imagemap_desc"
usage-example = "<imagemap>
rect 1 1 299 218 [[Use a Hammer Safely]]
desc none
basic-install = "require_once( \"$IP/extensions/ImageMap/ImageMap.php\" );"

... and then use a line like to give current behaviour:
$wgExtensionCredits['parserhook']['ImageMap'] = parse_ini_file( 'config.ini' );

Note - the main problem with trying to give current behaviour in the above line is a bug in older versions of PHP with parse_ini_file: I have observed that the parse_ini_file in PHP 5.1.2 does not properly handle escaped quotes (as in the "basic-install" line above), and neither do builds builds from March 2007, but it works correctly with builds now, so at some point between March 2007 and now this PHP bug was fixed.
Comment 1 Brion Vibber 2008-05-22 18:15:38 UTC
How about a nice README file?
Comment 2 Nick Jenkins 2008-05-23 00:29:49 UTC
> How about a nice README file?

A nice README is perfect for humans, but not so good for software (unless there's a standard format). So just to clarify, this is so software can say "okay, this extension can be installed like so, and to get the extension to do something, I do X". Potential applications are for testing, and perhaps for some sort of web interface to make basic extension installation and telling-if-it-is-working possible using a GUI rather than via the command line. Most of my waffle above is talking about possible implementation details, but I probably should have outlined the reasons first :-)
Comment 3 Daniel Friesen 2008-05-23 17:17:56 UTC
INI Files are ugly. And even if they were used, with how badly PHP works with them we'd be using a custom wfParseIni function rather than using PHP's built in.

XML files are nicer, and more extensible. But the PHP support again isn't that great. Though, there is a PHP.XPath project on SourceForge which has a great library which works in both PHP4 and PHP5 that allows XPath to be used with absolutely no extra builtin PHP dependencies.

But honestly we shouldn't be doing this kind of stuff with the aim of GUI installation. Installing by a GUI needs a whole hellovalotta more data than what wgExtensionCredits contains or is meant to contain. You need everything from dependencies on other Extensions, to Dependencies on PHP builtins. And various other info including exactly what configuration options you have, and exactly what type and what kind of input can be put into them.

Before you even think of extending into another format, ask yourself why it is you need another format.
The answer to that is likely "Because I would need to load the Extension's file to get that info and that would install the extension".
That is what needs to be solved, not how extension credits are stored.

What language would we be building a GUI? PHP. Command line stuff would also be PHP. Basically there's little reason for anything other than PHP to be used for anything like installation or anything related to extensions. So what we need is not another format that is hard to make use of in PHP, it's a way to get extension data without actually loading the internals of the extension.

Something I've been pitching for awhile is a builtin Extension class, and a set of things which would make installation of extensions something more builtin.

class WikiCode extends Extension {
	 * Static info functions
	static function getExtensionCredit( $credit, $lang = null ) {
		switch( $credit ) {
			case 'type':return 'parserhook';
			case 'name':return __CLASS__;
			case 'author':return array(
				'realname' => 'Daniel Friesen',
				'url' => '',
				'email' => '
			case 'version':return '1.0a';
			case 'svn-date':return '$LastChangedDate: 2008-05-06 21:59:58 +1000 (Tue, 06 May 2008) $';
			case 'svn-revision':return '$LastChangedRevision: 34306 $';
			case 'url':return '';
			case 'description':
				require self::getExtensionFile( '' );
				return $description[$lang];
	static function getExtensionMessagePrefixes() {
		return 'wikicode';
	static function getExtensionFile( $file = null ) {
		static $eIP = dirname(__FILE__);
		if( isset($file) ) return "$eIP/$file";
		return $eIP;
	 * Config variables
	var $cUseUncacheableFunctions = true;
	var $cUseStringFunctions      = true;
	var $cUseRegex                = true;
	 * Config limits
	var $cLimitTitleQuery         = 100;  // Limit to how many queries for titles may be made.
	var $cLimitTimeChars          = 6000; // 
	var $cLimitStringSearch       = 30;   // 
	var $cLimitStringReplace      = 30;   // 
	var $cLimitStringPad          = 100;  // 
	var $cLimitLoopCount          = 100;  // Total limit to how many loops may be made in a page.
	 * Instanced extension
	function __construct() {
		global $wgAutoloadClasses, $wgHooks, $wgExtensionMessagesFiles;
		$eIP = self::getExtensionFile();
		$wgAutoloadClasses['ExprError']  = "$eIP/Expr.php";
		$wgAutoloadClasses['ExprParser'] = "$eIP/Expr.php";
		// Create autoloads for the individual WikiCode groups
		foreach( array(
			'Logic', 'Loop', 'Page', 'Math', 'String', 'Time', 'Error',
		) as $group ) {
			$wgAutoloadClasses[__CLASS__.'_'.$group"] = "$eIP/FunctionClasses/{$group}.php";
		$wgHooks['ParserGetHooks'][] = __CLASS__.'::SetupParserFunctionsForParser';
		$wgExtensionMessagesFiles[__CLASS__] = "$eIP/";
		return true; // Extension OK
	function SetupParserFunctionsForParser( $parser ) {
		$parser->setFunctionHook( 'fi', array( __CLASS__.'_Logic', 'ifHook' ) );
		return true;
	function SetupLanguageMagic( &$magicWords, $langCode ) {
		# English is used as a fallback, and the English synonyms are
		# used if a translation has not been provided for a given word
		$localWords = array();
		require self::getExtensionFile( '' );
		foreach( $words['en'] as $key => $value ) {
			if( isset($localWords[$key]) && is_array($localWords[$key]) ) {
				$localWords[$key] = array_merge( (array) $localWords[$key], (array) $value );
			} else {
				$localWords[$key] = (array) $value;
		if( $langCode != 'en' && isset($words[$langCode]) ) {
			foreach( $words[$langCode] as $key => $value ) {
				$localWords[$key] = array_merge( (array) $localWords[$key], (array) $value );
		foreach( $localWords as $word => $trans ) {
			$magic = $trans;
			array_unshift( $magic, 0 );
			$magicWords[$word] = $magic;
		return true;

That would be stored in WikiCode/
Say for some reason you stored your extension in /var/mediawiki/extensions
And you also used my 'wiki-tools' subdirectory.
Then to load the extension, you would be using:
$wgExtensionPaths[] = '/var/mediawiki/extensions';
$wgExtensionPaths[] = '/var/mediawiki/extensions/wiki-tools';
$wgLoadExtensions['WikiCode'] = array(
	'LimitTitleQuery' => 250

MediaWiki would load the extension when it is ready to. Additionally the $cLimitTitleQuery config there would be set to 250.
If you didn't notice it, the __construct() is basically equivalent to the $wgExtensionFunctions. And there are a few of my other proposals in there, extension message prefixes, and a hook for loading parserfunctions into the parser.
In short you could even track down a list of their extensions and the info, by grabbing the list of directories inside of the $wgExtensionPaths paths (Each being a name), and then checking if any contain a file, and then including that and calling $name::getExtensionCredit for any piece of info you need.
So static calls are info about the extension (Loading the file doesn't need to mean installation), and an instance is an installed extension. On a side note useful extension functions can also be programmed into the Extension class.

Note You need to log in before you can comment on or make changes to this bug.