Руководство:Написание скриптов обслуживания

From mediawiki.org
This page is a translated version of the page Manual:Writing maintenance scripts and the translation is 63% complete.
Outdated translations are marked like this.

Это пошаговое руководство по написанию скрипта обслуживания на основе класса Maintenance (см. Maintenance.php ), который был введен в MediaWiki 1.16 для упрощения написания скриптов обслуживания MediaWiki в командной строке.

Шаблонный код

Мы рассмотрим скрипт обслуживания helloWorld.php, который просто печатает "Hello, World". Эта программа содержит минимально необходимое количество кода (см. также copyright headers).

В приведенном ниже примере программы будет выведено значение "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;

Пояснения к шаблонам кода

require_once __DIR__ . "/Maintenance.php";

Мы включаем Maintenance.php. Это определяет class Maintenance, который обеспечивает основу для всех скриптов обслуживания, включая средства для разбора аргументов командной строки, чтения ввода консоли, подключения к базе данных и т.д.

class HelloWorld extends Maintenance {
}

Мы объявляем наш подкласс Maintenance.

$maintClass = HelloWorld::class;
require_once RUN_MAINTENANCE_IF_MAIN;

Указывает классу Maintenance запустить скрипт, использующий наш класс HelloWorld, только если он выполняется из командной строки.

Внутри, RUN_MAINTENANCE_IF_MAIN загружает другой файл doMaintenance.php, который автозагружает классы и конфигурацию MediaWiki, а затем

	public function execute() {
	}

Метод execute() является точкой входа для скриптов обслуживания, и именно здесь будет находиться основная логика вашего скрипта. Избегайте запуска любого кода из конструктора.

Когда наша программа будет запущена из командной строки, фреймворк обслуживания ядра позаботится об инициализации ядра MediaWiki, конфигурации и т.д., а затем вызовет этот метод.

Команда помощи

Одной из встроенных функций, которой обладают все скрипты обслуживания, является опция --help. Приведенный выше пример шаблона приведет к следующей странице помощи:

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

Добавление описания

"Но для чего нужен этот скрипт обслуживания?" Я слышу ваш вопрос.

Мы можем поместить описание в верхней части вывода "--help", используя метод addDescription в нашем конструкторе:

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

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

Теперь на выходе мы получаем описание:

$ php helloWorld.php --help

Say hello.

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

Разбор опций и аргументов

Приветствовать весь мир - это хорошо, но мы хотим иметь возможность приветствовать и отдельных людей.

Чтобы добавить опцию командной строки, добавьте конструктор к class HelloWorld, который вызывает Maintenance addOption(), и обновите метод 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

Расширения

Версия MediaWiki:
1.28
Gerrit change 301709

Если ваш скрипт обслуживания предназначен для расширения, то вы должны добавить требование, чтобы расширение было установлено:

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

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

Это позволяет получить полезное сообщение об ошибке, когда расширение не включено. Например, во время локальной разработки определенное расширение может быть еще не включено в LocalSettings.php, или при работе вики-фермы расширение может быть включено на подмножестве вики-сайтов.

Помните, что никакой код не может быть выполнен иначе, чем через метод execute(). Попытки вызвать службы, классы или функции ядра MediaWiki или вызвать ваш собственный код расширения до этого, вызовут ошибки или будут ненадежными и неподдерживаемыми (например, за пределами объявленного класса или в конструкторе).

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 Руководство:Профилирование .

Написание тестов

Рекомендуется писать тесты для скриптов обслуживания, как и для любого другого класса. Помощь и примеры см. в руководстве по скриптам обслуживания.