Manual:Special pages/ru

From MediaWiki.org
Jump to: navigation, search
Gnome-preferences-other.svg Расширения:Manual:Extensions РазработкаManual:Developing extensions Теги расширенийManual:Tag extensions Руководство:функции парсераManual:Parser functions ПрерыванияManual:Hooks Служебные страницыManual:Special pages Стили оформления (skins)Manual:Skins Волшебные словаManual:Magic words APIAPI:Extensions

Специальные страницы (special pages) — необходимы для управления и наблюдением за Wiki. Например, специальная страница может показать все статьи, которые имеют одну или более ссылок на внешние сайты. Или в специальных страницах можно создать форму обратной связи для пользователей. И многое другое. Специальные страницы расположены в собственном пространстве имён (Special:/Служебная:), который нельзя изменить. Разработчики Wiki могут создавать новые специальные страницы, расширяющие функционал администраторов и пользователей, узнать какие страницы доступны вам можно в любой момент, перейдя в раздел Спецстраницы. Существуют в wiki и суперспециальные страницы, которые видны только разработчикам.

Основная информация[edit]

Все встроенные в MediaWiki спецстраницы (их около 75) описаны в файле SpecialSomename.php и размещаются в этой директории: includes/specials. Специальные страницы созданные сторонними разработчиками хранятся, как правило, в папке предназначенной для расширений: extensions. Объединяет их подчинённость одному классу SpecialPage, описанному в SpecialPage.php.

При создании новой спецстраницы можно определить категорию пользователей, имеющих к ней доступ.

Все специальные страницы имеют уникальные имена, также как и статьи. По умолчанию шаблон спецстраниц выглядит так: "Special:Pagename", но можно настроить, чтобы и "Special", и "Pagename" отображались по-иному. Например, префикс "Special" может быть переведён на другие языки (в русской локализации wiki чаще всего используется "Служебная").

На спецстраницах ввод может быть и разрешён и запрещён. Например, Special:Export позволяет пользователям экспортировать статьи. Если специальная страница разрешает ввод информации, дополнительные параметры будут переданы в виде query string, являющейся частью URL, для обработки. Например: http://www.mediawiki.org/w/index.php?title=Special:Recentchanges&days=3&limit=250.

Примечания:

  • Существуют различные способы создания спецстраниц, но лучше всего делать их в качестве расширений. Не забудьте включить себя в титры. Подробнее об этом читайте здесь: $wgExtensionCredits.
  • После создания новой специальной страницы добавьте её в Category:Special page extensions/ru, чтобы другие пользователи могли её найти.
  • Приведённые ниже методы не будут работать на PHP 4, потому что в нём отсутствует класс "autoloading", присутствующий в PHP 5. Из-за этого страницы написанные для PHP 5 не всегда совместимы с MediaWiki до версии 1.7.0. Если вы используете более раннюю версию MediaWiki на более современной версии PHP, обновите MediaWiki.

Шаблоны базовых спецстраниц[edit]

Большинству служебных страниц требуется четыре файла: небольшой файл установки, который будет запускаться при загрузке MediaWiki, файл локализации, файл псевдонима (alias) и файл с основным кодом. Все они размещаются в отдельной директории внутри папки /extensions/. Согласно конвенции кодирования MediaWiki эти файлы должны выглядеть следующим образом:

  • <имя_служебной_страницы>.php - установочный файл.
  • <имя_служебной_страницы>_body.php - файл с основным кодом.
  • <имя_служебной_страницы>.i18n.php - файл локализации.
  • <имя_служебной_страницы>.alias.php - псевдоним (alias).

В дальнейших примерах <имя_служебной_страницы> имеет значение MyExtension. Вы можете скачать эти файлы по ссылке, приведённой ниже.

После создания четырёх файлов, необходимо добавить строку в LocalSettings.php:

  • require_once( "$IP/extensions/MyExtension/MyExtension.php" );

Установочный файл[edit]

Так выглядит файл установки:

<?php
# Предупреждаем пользователя, что это не точка входа на Wiki, если он попытается получить доступ к спецстраницам напрямую.
if (!defined('MEDIAWIKI')) {
        echo <<<EOT
To install my extension, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/MyExtension/MyExtension.php" );
EOT;
        exit( 1 );
}

$wgExtensionCredits['specialpage'][] = array(
	'name' => 'MyExtension',
	'author' => 'My name',
	'url' => 'http://www.mediawiki.org/wiki/Extension:MyExtension',
	'description' => 'Default description message',
	'descriptionmsg' => 'myextension-desc',
	'version' => '0.0.0',
);

$dir = dirname(__FILE__) . '/';

$wgAutoloadClasses['MyExtension'] = $dir . 'MyExtension_body.php'; # Попросите MediaWiki загрузить тело основного файла.
$wgExtensionMessagesFiles['MyExtension'] = $dir . 'MyExtension.i18n.php';
$wgExtensionAliasesFiles['MyExtension'] = $dir . 'MyExtension.alias.php';
$wgSpecialPages['MyExtension'] = 'MyExtension'; # Сообщите MediaWiki о Вашей новой спецстранице.

Этот небольшой код содержит четыре основных параметра:

  • Путь к файлу MyExtension.
  • Путь к файлу сообщений.
  • Путь к файлу алиасов.
  • Новую служебную страницу и её название.

Файл с основным кодом[edit]

Основной файл MyExtension_body.php содержит подкласс SpecialPage. Он будет загружаться автоматически, когда пользователь вызовет служебную страницу.

<?php
class MyExtension extends SpecialPage {
	function __construct() {
		parent::__construct( 'MyExtension' );
		wfLoadExtensionMessages('MyExtension');
	}

	function execute( $par ) {
		global $wgRequest, $wgOut;
		
		$this->setHeaders();

		# Get request data from, e.g.
		$param = $wgRequest->getText('param');
		
		# Do stuff
		# ...

		# Output
		# $wgOut->addHTML( $output );
	}
}

execute() — это основная функция, которая вызывается при запуске служебной страницы.

wfLoadExtensionsMessages('MyExtension') загружает сообщения из файла сообщений, ссылка на который была дана в установочном файле (MyExtension.php). Подробнее об этом далее.

The Messages File[edit]

All special pages must specifiy a title to appear in the title and <H1> elements of the extension's page and on Special:Specialpages. The extension specifies the title through a message. The structure of the message is a key-value pair. The ID, 'myextension', must be in all lowercase when specified in the key portion of the key-value pair, even if everywhere else it is MyExtension. The title, 'My Extension', can be anything, however it is convenient if the page title is the same as the ID. At its barest minimum, the message file should look like:

<?php
$messages = array();

$messages['en'] = array( 
	'myextension' => 'My Extension',
);


The message file can contain a great deal more information. The following example adds a description of the extension. It also adds a text for browsers specifying a preference for German.

<?php
$messages = array();

/* *** English *** */
$messages['en'] = array( 
	'myextension' => 'My Extension',
	'myextension-desc' => "Extension's description",
);

/* *** German (Deutsch) *** */
$messages['de'] = array(
	'myextension' => 'Meine Erweiterung',
	'myextension-desc' => 'Beschreibung der Erweiterung',
);


Note that IDs should not start with an uppercase letter, and that a space in the ID should be written in the code as an underscore. For the page header and linking, the usual rules for page names apply. If $wgCapitalLinks is true, a lowercase letter is converted to uppercase, and an underscore is displayed as a space. For example: instead of the above, we could have used 'my_extension' => 'My extension', assuming we consistently identified the extension as my_extension elsewhere.

The Alias files[edit]

This file has about the same format as the messages file.

<?php
$aliases = array();

/** English */
$aliases['en'] = array(
    'MyExtension' => array( 'MyExtension' ),
);

/** German (Deutsch) */
$aliases['de'] = array(
	'MyExtension' => array( 'MeineErweiterung', 'Meine Erweiterung' ),
);

It allows the page title to be translated to another language. The page title can be customized into another language, the URL of the page would still be something like .../Special:MyExtension, even when the user language is not English. In this example, the special page MyExtension registers an alias so the page becomes accessible via .../Special:My_Extension eg. .../Spezial:Meine_Erweiterung in German, and so on.


A version of this example has been tested, and is checked in to MediaWiki SVN in examples/FourFileTemplate.

Other Important Files[edit]

SpecialPage.php[edit]

Constructor[edit]

You can overload the constructor to initialize your own data, but the main reason you would want to do it is to change the behavior of the SpecialPage class itself. When you call the base class constructor from your child class, the following parameters are available:

function SpecialPage( $name = '', $restriction = '', $listed = true, $function = false, $file = 'default', $includable = false )
  • string $name Name of the special page, as seen in links and URLs
  • string $restriction User right required, e.g. "block" or "delete"
  • boolean $listed Whether the page is listed in Special:Specialpages
  • string $function A global function to call at run time if your subclass doesn't override execute(). By default it is constructed from $name as "wfSpecial$name".
  • string $file File which is included by execute(). It is also constructed from $name by default
  • boolean $includable Whether the special page can be included from other pages using {{Special:...}}

SpecialPage->setHeaders()[edit]

This initialises the OutputPage object $wgOut with the name and description of your special page. It should always be called from your execute() method.

SpecialPage->including()[edit]

This returns a boolean value telling you what context the special page is being called from: false if it is a separate web page, and true if it is being included from within another web page. Usually you will want to strip down the presentation somewhat if the page is being included.

Including from another web page is only possible if you declared the page to be includable in the constructor. You can do this by adding the following in the __construct() method after the parent class initalization:

$this->mIncludable = true;

SpecialPage->execute()[edit]

This is the function which your child class should overload. It passes a single parameter, usually referred to cryptically as $par. This parameter is the subpage component of the current title. For example, if someone follows a link to Special:MyExtension/blah, $par will contain "blah".

OutputPage.php[edit]

The global variable $wgOut (of type OutputPage) 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 a pipe...</b>');
}

You can inspect the OutputPage class 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()[edit]

Essentially the quick and dirty substitute for echo. It takes your input and adds it to the buffer: no questions asked. In the below action, if $action contains user-data, it could easily have XSS, evil stuff, or the spawn of Satan injected in. You're better off using escaping or the XML builders class to build trusted output.

$wgOut->addHTML('<form action="'.$action.'" method="post">');

OutputPage->addWikiText()[edit]

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 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.

WARNING: If your special page is intended to be included in other pages, you should probably not use addWikiText(). Due to what seems to be a bug in MediaWiki, an included special page will mess up any inclusion before it on the same including page, showing just strings like UNIQ10842e596cbb71da.

workaround #1[edit]

As a workaround, you can have your extensions convert Wikitext to HTML using a separate Parser object and then use addHTML(). Example:

$wgOut->addHTML(sandboxParse("Here's some '''formated''' text."));
function sandboxParse($wikiText) {
	global $wgTitle, $wgUser;
	$myParser = new Parser();
	$myParserOptions = new ParserOptions();
	$myParserOptions->initialiseFromUser($wgUser);
	$result = $myParser->parse($wikiText, $wgTitle, $myParserOptions);
	return $result->getText();
}
workaround #2[edit]

I tried the above, and found that the same problem now applied to any <tag>s in the transcluded text. This won't be a problem for a lot of extensions, but the extension I was writing was intended to show wikitext from another page as part of its functionality, so this was a problem.

The process for parsing a page which transcludes a special page seems to be this:

  1. Replace {{Special:MyExtension}} with a UNIQ-QINU marker (because SpecialPage output is expected to be ready-to-output HTML)
  2. Replace any <tag>s with QINU markers as above
  3. Parse everything else from wikitext to HTML
  4. Replace all QINU markers with their respective stored values, in a single pass

The process for parsing a page which transcludes a non-special page, though, is apparently like this:

  1. Replace {{:Normal Article Name}} or {{Template Name}} with contents of transcluded page (because transcluded pages contain unparsed wikitext)
  2. Replace any <tag>s with QINU markers as above
  3. Parse everything else from wikitext to HTML
  4. Replace all QINU markers with their respective stored values, in a single pass

The problem is apparently that in the earlier case, the parsing of the SpecialPage's wiki text is lacking the final QINU decoding step (why?), so all the QINU markers are left undecoded. (This may be a leftover from using the same syntax to invoke transclusion of a wikitext page, which is just pasted straight into the host page's wikitext contents and parsed, as is used to invoke transclusion of a SpecialPage, which must not be parsed at all. Wherever the code is that decides "wait, this is a special page -- replace it with a QINU", it should be doing the extra unstripGeneral before doing the QINU substitution.)

So I just did the following -- after this line:

$htOut = $wgParser->recursiveTagParse($iText);

...I added these lines (the second one is only because the function definition for the first one recommends it):

$htOut = $wgParser->mStripState->unstripGeneral($htOut);
$htOut = $wgParser->mStripState->unstripNoWiki($htOut);

Since I have now documented this, of course, I will now find a tragic flaw with it and feel really stupid... but as long as it seems to be working, I had to note it here. (It is also important to note the problem with work-around #1.) Also, I have only tested this with MediaWiki 1.10.1. The problem still exists under MW 1.14, but this solution may or may not work. --Woozle 18:26, 9 April 2009 (UTC)

wfMsg()[edit]

In most of the real special pages, you will rarely see $wgOut->addWikitext() without wfMsg() popping in.

wfMsg() is a MediaWiki internationalization (i18n) function. See wfMsg() for more information.

OutputPage->showErrorPage()[edit]

An error page is shown. The arguments $title and $msg specify keys into wfMsg(), not text. An example:

$wgOut->showErrorPage('error','badarticleerror');
  • 'error' refers to the text "Error".
  • 'badarticleerror' refers to the text "This action cannot be performed on this page.".

MessageCache.php[edit]

MessageCache is a class that will turn messages into the value defined in the wiki for that value. See m:Help:System message for more information. In most circumstances, system messages will come from one of these places, in increasing order of importance:

  1. The default language file
  2. Messages defined in extension internationalization files
  3. 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. Messages are accessible from extensions by including the global $wgMessageCache in the page.

MessageCache->addMessages()[edit]

MessageCache->addMessages() is usually used for adding messages for extensions, and they are internally marked as such. The syntax is very simple:

function addMessages( $messages )

Where $messages is an array that looks like:

array (
    'key1' => 'Value 1',
    'key2' => 'Value 2'
)

Whatever the key was, its value can be retrieved using wfMsg('key'). This allows MediaWiki to pass a customized string from a page in the MediaWiki database, specifically MediaWiki:Key.

WebRequest.php[edit]

The WebRequest class is used to obtain information from the GET and POST arrays. Using this is recommended over directly accessing the superglobals, since the object does fun stuff like magic_quotes cleaning. The WebRequest object is accessible from extensions by including the global $wgRequest in the code.

WebRequest->getVal($key)[edit]

Returns a string that corresponds to the form input with the name $key.

WebRequest->get*()[edit]

Returns an int, bool, etc depending on the function called. For checkboxes for example, the function getBool is useful.

WebRequest->wasPosted()[edit]

Returns true if a form was posted.

Database.php[edit]

MediaWiki has a load of convenience functions and wrappers for interacting with the database. It also has an interesting load balancing scheme in place. It's recommended you use these wrappers. Check out Database.php for a complete listing of all the convenience functions, because these docs will only tell you about the non-obvious caveats. See Manual:Database access.

wfGetDB()[edit]

As this name suggests, this function gets you a reference of the database. There is no global that contains a database object.

When you call the function, you should pass it a parameter, the constant DB_MASTER or DB_SLAVE. Generally, you interact with the slave database when you're only performing read operations, and interact with the master when you're writing to the database. It's real easy to do, so do it, even if you only have one database.

User.php[edit]

The User class is used to represent users on the system. The global $wgUser represents the currently logged in user, and is usually what you will deal with when manipulating users.

User->isAllowed($right)[edit]

Returns true or false depending on whether the user is allowed to do $right.

User->isBlocked()[edit]

Returns true if a user is blocked.

Title.php[edit]

Title represents the name of a page in the wiki. This is useful because MediaWiki does all sorts of fun escaping and special case logic to page names, so instead of rolling your own convert title to URL function, you create a Title object with your page name, and then use escapeLocalURL() to get a URL to that page.

Title::makeTitle()[edit]

Title->escapeLocalURL()[edit]

FAQ[edit]

Setting an Extension Title[edit]

MediaWiki does not set the title of the extension, which is the developer's job. It will look for the name of the extension when Special:Specialpages is called or the special page is loaded (specifically right before the registered wfSpecial*() function is called). Use $wgOut to title the extension like: $wgOut->setPagetitle("your title");

The place where the extension can be found (as specified by what is passed into the SpecialPage constructor) is the key--except that it is not capitalized because of getDescription(), the internally used function that finds out the title (or, what they call description) of the special page, strtolower the name. "ThisIsACoolSpecialPage"'s key would be "thisisacoolspecialpage."

Theoretically, getDescription can be overloaded in order to avoid interacting with the message cache but, as the source code states: "Derived classes can override this, but usually it is easier to keep the default behavior. Messages can be added at run-time--see MessageCache.php". Furthermore, this prevents the MediaWiki namespace from overloading the message, as below.

Localizing the Extension Name[edit]

So you've just installed a shiny new MediaWiki extension and realize: "Oh no, my wiki is in French, but the page is showing up as English!" Most people wouldn't care, but it's actually a quite simple task to fix (as long as the developer used the method explained on this page). No noodling around in source code. Let's say the name of the page is DirtyPages and the name comes out to "List of Dirty Pages" but you want it to be (and excuse my poor French) "Liste de Pages Sales". Well, it's as simple as this:

  1. Navigate to MediaWiki:DirtyPages, this page may not exist, but edit it anyway
  2. Insert "Liste de Pages Sales" and save

And voilà (pardon the pun), the change is applied.

This is also useful for customizing the title for your wiki within your language: for instance, the developer called it "List of Dirty Pages" but you don't like that name, so you rename it "List of Pages needing Cleanup". Check out Special:Allmessages to learn more.

Also, if your extension has a large block of text that does change, like a warning, don't directly output the text. Instead, add it to the message cache and when the time comes to output the text in your code, do this:

$wgOut->addWikiText( wfMsg( 'dirtypageshelp' ) );

Then this message too can be customized at MediaWiki:Dirtypageshelp.

See also Help:System message.

Restricting the page to sysops or other users with special rights[edit]

Some special pages are omitted from the special page list unless the user has particular rights, such as being a sysop. To restrict your special page similarly, set the restriction parameter in the constructor. A typical sysop right is editinterface:

function __construct() {
  parent::__construct( 'MyExtension', 'editinterface' ); // restrict to sysops
}

Or you can create your own right in the setup file and assign it to sysops, e.g.:

$wgGroupPermissions['sysop']['myright'] = true;
$wgAvailableRights[] = 'myright';

and then call the constructor with your right:

function __construct() {
  parent::__construct( 'MyExtension', 'myright' );
}

Even if you restrict your page, your extension should check that the proper right is present, in case a user can somehow access it directly:

function execute( $par ) {
  // ...
  global $wgUser;
  if ( !$this->userCanExecute($wgUser) ) {
    $this->displayRestrictionError();
    return;
  }
  // ...

См. также mailarchive:mediawiki-l/2009-June/031231.html.

Язык:Project:Language policy English  • Deutsch • Bahasa Indonesia • 日本語 • русский • 中文