Manual:Writing maintenance scripts/ja

From Linux Web Expert

これは、MediaWiki 1.16 で導入されて書きやすくなったコマンドラインの MediaWiki 管理スクリプトを Maintenance クラス (Maintenance.php 参照)に基づいて書く方法を順番に解説したものです。

Boilerplate

ここでは、単に「Hello, World」と出力する helloWorld.php というメンテナンス スクリプトを説明します。このプログラムは、期待される著作権ヘッダーと同様に、実行に必要な最小限のコードを含んでいます (代替ヘッダーについては、著作権ヘッダーを参照してください):

The below example program will print "Hello, World!".

The way to invoke maintenance scripts changed in 2023 with MediaWiki 1.40, with the new run.php being used to launch all maintenance scripts, rather than directly calling them by filename (although the latter remains supported for now). This tutorial covers both methods, and notes where there are differences between the systems.

MediaWiki コア

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 拡張機能

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;

コマンドラインから実行した場合のみ、Maintenance クラスに HelloWorld クラスを使用してスクリプトを実行するように指示します。

内部的には、RUN_MAINTENANCE_IF_MAIN が別ファイルの doMaintenance.php を読み込み MediaWiki クラスと設定を自動的に読み込むと次に

	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")
…

説明の追加

「しかし、このメンテナンス スクリプトは何のためにあるのだろう?」 という声が聞こえてきそうです。

コンストラクターの addDescription メソッドを使用することで、「--help」の出力の先頭に説明を配置できます:

	public function __construct() {
		parent::__construct();

		$this->addDescription( 'Say hello.' );
	}

これで説明が出力されるようになりました:

$ php helloWorld.php --help

Say hello.

Usage: php helloWorld.php [--help]
…

オプションと引数の解析

世界に挨拶するのもいいですが、個人にも挨拶できるようにしたいですね。

コマンドライン オプションを追加するには、class HelloWorldMaintenanceaddOption() を呼び出すコンストラクターを追加し、execute() のメソッドを新しいオプションを使用するように更新します。 addOption() のパラメーターは $name, $description, $required = false, $withArg = false, $shortName = false であるため、以下のようにします:

	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!" );
	}

これにより、実行すると、与えられた引数によって helloWorld.php スクリプトの出力が変化するようになりました:

$ 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

拡張機能

<td class="mw-version-versionbox" title="<translate nowrap> The latest stable version is <tvar name=1>1.41</tvar></translate>">
<translate> ≥</translate> 1.28
Gerrit change 301709
<translate> MediaWiki version:</translate>

メンテナンス スクリプトが拡張機能向けである場合、拡張機能がインストールされていることを要件に追加する必要があります:

	public function __construct() {
		parent::__construct();
		$this->addOption( 'name', 'Who to say Hello to' );

		$this->requireExtension( 'FooBar' );
	}

これは、拡張機能が有効になっていない場合に、役立つエラー メッセージを提供します。 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:プロファイリング .

テストを書く

他のクラスと同じように、メンテナンス スクリプトのテストを書くことをお勧めします。 ヘルプと例は、メンテナンス スクリプトのガイドを参照してください。