Manual:Writing maintenance scripts
This is a step-by-step tutorial on writing a maintenance script based on the Maintenance
class (see Maintenance.php ) which was introduced in MediaWiki 1.16 to make it easier to write command-line MediaWiki maintenance scripts.
Boilerplate
We'll walk through a helloWorld.php
maintenance script that simply prints "Hello, World". This program contains the minimum amount of code needed (see also copyright headers).
The below example program will print "Hello, World!".
MediaWiki core
- Command
$ ./maintenance/run HelloWorld Hello, World!
- Filename
maintenance/HelloWorld.php
- Code
<?php require_once __DIR__ . '/Maintenance.php'; /** * Brief oneline description of Hello world. * * @since 1.17 * @ingroup Maintenance */ class HelloWorld extends Maintenance { public function execute() { $this->output( "Hello, World!\n" ); } } $maintClass = HelloWorld::class; require_once RUN_MAINTENANCE_IF_MAIN;
MediaWiki extension
- Command
$ ./maintenance/run MyExtension:HelloWorld Hello, World!
- Filename
extensions/MyExtension/maintenance/HelloWorld.php
- Code
<?php namespace MediaWiki\Extension\MyExtension\Maintenance; use Maintenance; $IP = getenv( 'MW_INSTALL_PATH' ); if ( $IP === false ) { $IP = __DIR__ . '/../../..'; } require_once "$IP/maintenance/Maintenance.php"; /** * Brief oneline description of Hello world. */ class HelloWorld extends Maintenance { public function __construct() { parent::__construct(); $this->requireExtension( 'Extension' ); } public function execute() { $this->output( "Hello, World!\n" ); } } $maintClass = HelloWorld::class; require_once RUN_MAINTENANCE_IF_MAIN;
Boilerplate explained
require_once __DIR__ . "/Maintenance.php";
We include Maintenance.php
. This defines class Maintenance
which provides the basis for all maintenance scripts, including facilities to parse command-line arguments, read console input, connect to a database, etc.
class HelloWorld extends Maintenance {
}
We declare our Maintenance subclass.
$maintClass = HelloWorld::class;
require_once RUN_MAINTENANCE_IF_MAIN;
Tells the Maintenance class to run the script using our HelloWorld
class, only if being executed from the command line.
Internally, RUN_MAINTENANCE_IF_MAIN
loads another file doMaintenance.php which autoloads MediaWiki classes and configuration, and then runs our execute()
method.
public function execute() {
}
The execute()
method is the entrypoint for maintenance scripts, and is where the main logic of your script will be. Avoid running any code from the constructor.
When our program is run from the command-line, the core maintenance framework will take care of initialising MediaWiki core and configuration etc, and then it will invoke this method.
Help command
One of the built-in features that all maintenance scripts enjoy is a --help
option. The above example boilerplate would produce the following help page:
$ php helloWorld.php --help Usage: php helloWorld.php […] Generic maintenance parameters: --help (-h): Display this help message --quiet (-q): Whether to suppress non-error output --conf: Location of LocalSettings.php, if not default --wiki: For specifying the wiki ID --server: The protocol and server name to use in URL --profiler: Profiler output format (usually "text") …
Adding a description
"But what is this maintenance script for?" I can hear you asking.
We can put a description at the top of the "--help
" output by using the addDescription
method in our constructor:
public function __construct() {
parent::__construct();
$this->addDescription( 'Say hello.' );
}
The output now gives us the description:
$ php helloWorld.php --help Say hello. Usage: php helloWorld.php [--help] …
Option and argument parsing
Greeting the world is all well and good, but we want to be able to greet individuals, too.
To add a command-line option, add a constructor to class HelloWorld
that calls Maintenance
's addOption()
and update the execute()
method to use the new option.
addOption()
's parameters are $name, $description, $required = false, $withArg = false, $shortName = false
, so:
public function __construct() {
parent::__construct();
$this->addDescription( 'Say hello.' );
$this->addOption( 'name', 'Who to say Hello to', false, true );
}
public function execute() {
$name = $this->getOption( 'name', 'World' );
$this->output( "Hello, $name!" );
}
This time, when executed, the output of the helloWorld.php
script changes depending on the argument provided:
$ php helloWorld.php Hello, World! $ php helloWorld.php --name=Mark Hello, Mark! $ php helloWorld.php --help Say hello. Usage: php helloWorld.php […] … Script specific parameters: --name: Who to say Hello to
Extensions
<td class="mw-version-versionbox" title="<translate nowrap> The latest stable version is <tvar name=1>1.41</tvar></translate>"><translate> MediaWiki version:</translate> |
If your maintenance script is for an extension, then you should add a requirement that the extension is installed:
public function __construct() {
parent::__construct();
$this->addOption( 'name', 'Who to say Hello to' );
$this->requireExtension( 'FooBar' );
}
This provides a helfpul error message when the extension is not enabled. For example, during local development a particular extension might not yet be enabled in LocalSettings.php, or when operating a wiki farm an extension might be enabled on a subset of wikis.
Be aware that no code may be executed other than through the execute()
method.
Attempts to call MediaWiki core services, classes, or functions, or calling your own extension code prior to this, will cause errors or is unreliable and unsupported (e.g. ouside the class declaration, or in the constructor).
Profiling
Maintenance scripts support a --profiler
option, which can be used to track code execution during a page action and report back the percentage of total code execution that was spent in any specific function.
See Manual:Profiling .
Writing tests
It's recommended to write tests for your maintenance scripts, like with any other class. See the Maintenance scripts guide for help and examples.