Requests for comment/Extension registration

From mediawiki.org
Request for comment (RFC)
Extension registration
Component General
Creation date
Author(s) Kunal Mehta
Document status implemented
Accepted by means of merging.
See Phabricator.

This is a request for comments regarding extension registration.

Implementation status[edit]

MediaWiki version:
≥ 1.25
Gerrit change 166705

This is implemented and available, see documentation in Manual:Extension registration. phab:T87875 tracks the conversion of Wikimedia-deployed extensions and skins to use extension registration. Until that is complete they will keep a ExtensionName.php file duplicating the information in extension.json.

Background[edit]

Extensions currently need to "register" information about themselves. This includes autoloading classes, hook functions, and much more. This is typically done in filescope by adding to global variables. As a consequence, it is not possible to figure out what an extension is going to register without including the file, which would enable the extension regardless. In addition, we are planning to move away from configuring things in global scope.

This is a proposal to change the way extensions store metadata about themselves and how we enable them.

Registration components[edit]

This is a list of items that most extensions will typically register.

There are many more, just look at DefaultSettings.php for an idea.

Proposal[edit]

Store all of this in a JSON file in the extension's directory at ExtName/extension.json.

Here's an example of what it might look like for the MassMessage extension (some of it, I didn't include everything). A full schema is available at /Schema.

{
	"name": "MassMessage",
	"version": "0.1.0",
	"url": "https://www.mediawiki.org/wiki/Extension:MassMessage",
	"authors": ["Kunal Mehta"],
	"config": {
		"wgNamespacesToPostIn": [ 4 ],
		"wgNamespacesToConvert": {
			2: 3
		},
		"wgMassMessageAccountUsername": "MediaWiki message delivery",
		"wgAllowGlobalMessaging": true
	}
	"SpecialPages": {
		"MassMessage": "SpecialMassMessage"
	},
	"MessagesDirs": {
		"MassMessage": "./i18n"
	},
	"AutoloadClasses": {
		"ApiMassMessage": "./ApiMassMessage.php",
		"MassMessage": "./MassMessage.body.php",
		"MassMessageHooks": "./MassMessage.hooks.php"
	},
	"APIModules": {
		"massmessage": "ApiMassMessage"

	},
	"JobClasses": {
		"MassMessageJob": "MassMessageJob",
		"MassMessageSubmitJob": "MassMessageSubmitJob"
	},
	"Hooks": {
		"ParserFirstCallInit": "MassMessageHooks::onParserFirstCallInit",
		"SpecialStatsAddExtra": "MassMessageHooks::onSpecialStatsAddExtra",
		"APIQuerySiteInfoStatisticsInfo": "MassMessageHooks::onAPIQuerySiteInfoStatisticsInfo",
		"RenameUserPreRename": "MassMessageHooks::onRenameUserPreRename",
		"UserGetReservedNames": "MassMessageHooks::onUserGetReservedNames"
	},
	"ResourceLoader modules": {
		"ext.MassMessage.special.js": {
			"scripts": [
				"ext.MassMessage.special.js",
				"ext.MassMessage.autocomplete.js",
				"ext.MassMessage.badhtml.js"
			],
			"messages": [
				"massmessage-badhtml",
				"massmessage-parse-badpage"
			],
			"dependencies": [
				"jquery.byteLimit",
				"jquery.ui.autocomplete",
				"jquery.throttle-debounce",
				"mediawiki.jqueryMsg"
			],
			"localBasePath": "./modules",
			"remoteExtPath": "MassMessage/modules"
		}
	},
	"LogTypes": ["massmessage"],
	"LogActionsHandlers": {
		"massmessage/*": "LogFormatter"
	},
	"AvailableRights": ["massmessage"],
	"GroupPermissions": {
		"sysop": {
			"massmessage": true
		}
	}
}

Explanation[edit]

In reality, not much has changed except for the format these options are stored in. For most extensions, this will completely eliminate the ExtName.php loader file. For backwards compatibility, we can provide a stub file, similar to how the JSON i18n migration occurred.

For extensions that absolutely need to handle setup in PHP, a callback may be registered (using a "callback" key), that will be run after the rest of the info.json file has been processed. This would be different than extension functions, which are run after nearly all MediaWiki setup has occurred.

Some large extensions (Wikibase/Wikidata, CentralAuth, etc.) will have to handle more complicated setup. These can set a "registerer" key (I really suck at naming things) to use a custom class that extends the default "ExtensionRegisterer".

Performance[edit]

Reading and parsing a JSON file will be slower than loading a PHP file due to APC and other factors. However, we can mitigate that by providing a script to "compile" all the required JSON files into their PHP equivalents.

Loading extensions[edit]

Currently extensions are loaded by adding: require_once( "$IP/extensions/ExtName/ExtName.php" ); to your LocalSettings/CommonSettings.php file.

Instead of this, we would add a function like wfLoadExtension( 'Math' ). If you want to use a non-standard path, wfLoadExtension( 'Math', "/some/special/path/Math" ). If no path is provided, "$IP/extensions/$name" will be assumed.

wfLoadExtension( 'Math' );
$wgMathSomeOption = 'bar';
wfLoadExtension( 'SpamBlacklist', '/some/weird/location' );

This would also provide a backend for a future web interface to enable/disable extensions.

In MediaWiki's initialization, GlobalFunctions.php is loaded after LocalSettings.php, which means this function will need to exist in a separate file (likely just be a wrapper for an extension loading class).

See also[edit]