Manual:Special pages
Special pages, with the prefix "Special:", are fairly self contained MediaWiki extensions that do useful things that wouldn't fit in with the normal user interface.
MediaWiki 1.5 offers reflective extension loading, which means hooking up your extension to the system is fast and easy. The possibilities for special pages are limitless, only constrained by your programming ability.
Warning: This page gives MediaWiki 1.5 specific information. You can find the pre-1.5 version here: Writing a new special page, and if anyone is interested in maintaining the old version, feel free to branch it.
Abstract
A special page is, essentially, a PHP function that is called when someone browses to that page. You can pass off the handling of logic to a class (most special pages do that) or you can inline all of the logic in the function.
What makes special pages different from extra PHP pages littered on your server, however, is the fact that they build off the enormous amount of initialization and infrastructure tha MediaWiki offers. Part of the problem is integrating the special page with MediaWiki (a very simple process), but the real deal is utilizing all of MediaWiki's resources, whether they are absolutely necessary, or just "kinda cool."
Tutorial
To add your own extension page, you will need to add two pages to the MediaWiki installation. I am using a naming convention that adds prefixes special to my extension's name since it's a special page. My special page would be viewable at Special:Example.
Extension page
This page resides at extensions/SpecialExample.php. It is included in LocalSettings.php (which is how the system knows the extension exists). This page is responsible for registering the special page and adding the special page's default system messages.
<?php
$wgExtensionFunctions[] = "wfExtensionSpecialExample";
function wfExtensionSpecialExample() {
global $wgMessageCache;
require_once('includes/SpecialPage.php');
$wgMessageCache->addMessages(array('example' => 'An Example Special Page')); //will expand
SpecialPage::addPage( new SpecialPage( 'Example' ) );
}
//extension specific configuration options (like new user groups and perms) here
?>
Include page
This page resides at includes/SpecialExample.php. Nothing extra needed: MediaWiki will automatically include the file for you and call the function. This contains the heavy lifting of the extension.
function wfSpecialExample() {
global $wgOut;
$wgOut->addHTML('Boom!');
}
//or, you can define a bunch of new classes to organize the logic
What happens
The extension page defines a few configuration options and also registers our extension function. Once all initialization is done, MediaWiki calls all the functions enumerated in $wgExtensionFunctions.
The function we assign serves two purposes:
- It initializes the system messages our extension will use (or at the very least, the title of the extension page)
- It registers our extension as a SpecialPage
Then, control is passed back to the flow of the script, and if the page requested is a special page, SpecialPage will call the proper special page, and if it's your page, it will include your page (determined by concatenating Special with the name of your page and '.php') and it will call your function, wfSpecialExample (which was determined by concatenating wfSpecial with the name of your special page).
So with this simple bit of code, we have told MediaWiki everything it needs to know about our extension. Congratulations: you've just made a shiny new, albeit boring, special page.
Globals
MediaWiki makes extensive use of globals. If anyone ever told you globals were bad, well, here's a professional system that uses globals fairly well. All globals are prefixed with $wg, and they contain loads of useful information about the context of the request.
Don't edit core code unless you absolutely have to
Reasons why you shouldn't cave into temptation and edit code elsewhere:
- Upgrading becomes a pain in the arse, especially when they conflict
- You fundamentally change the way MediaWiki works, which leads to logic errors
- It's harder to distribute (you have to give out diffs)
- Your changes are scattered over more pages
- Greater chance your extension will clobber other extensions
- It's unclean
- Because there's often a solution that doesn't require core edits
If you find yourself in a real fix, you can always consider using a decorator on a global like $wgOut.
Advanced topics
The best way to go about learning about all the public methods and classes is to either read the source code or consult the API documentation. The list of stuff covered here is a quick, uncomprehensive reference for the most commonly used classes and methods, and probably is a bit more user friendly then the automatically generated docs.
OutputPage $wgOut
The global variable $wgOut is the variable you will use the most, because it is the way to send output to the browser (no, you don't use echo or print). If you want to use it somewhere, declare the variable global:
function randomFunction() {
global $wgOut;
$wgOut->addHTML('<b>This is not very random...</b>');
}
$wgOut contains an OutputPage object, which you can inspect by viewing includes/OutputPage.php (indeed, all of these can be inspected), but there are a few methods you should definitely know about.
OutputPage::addHTML()
Essentially the quick and dirty substitute for echo. It takes your input and adds it to the buffer: no questions asked. Be careful with it. You should use this for complicated forms and output in your page.
$wgOut->addHTML('<form action="'.$action.'" method="post">');
OutputPage::addWikiText()
For most output, you should be using this function. It's a bit of a black magic function: wikitext goes in, HTML comes out, and a whole lotta of arcane code and demon summonings happen in between.
$wgOut->addWikiText("This is some ''lovely'' [[wikitext]] that will '''get''' parsed nicely.");
What's worth noting is that the parser will view your chunks as cohesive wholes and paragraph accordingly. That is...
$wgOut->addWikiText('* Item 1');
$wgOut->addWikiText('* Item 2');
$wgOut->addWikiText('* Item 3');
Will output three lists with one item each, which probably wasn't intended.
wfMsg()
In most of the real special pages, you will rarely see $wgOut->addWikitext() without wfMsg() popping in. wfMsg() is MediaWiki's way of internationalization (i18n). An example:
$wgOut->addWikiText( wfMsg( 'flubbersuccess' ) );
wfMsg() looks up the system message called flubbersuccess, and then returns it. The actual text of the message can come from a variety of places. Find out more about how to tell MediaWiki what to output in MessageCache.
OutputPage::errorpage()
MessageCache $wgMessageCache
MessageCache is a class that will figure out what the string corresponding to the key (flubbersuccess) you give it. In most circumstances, they will come from these places, with the overriding one on the bottom:
- Default language file
- Added on extension strings
- The MediaWiki namespace
The default language file is all the stuff that comes bundled with Wikipedia. Since we're writing extensions, and we're implementing new functionality, this isn't very useful. Next is extension strings.