API:Extensions

From MediaWiki.org
Jump to: navigation, search
Language: English  • Deutsch • 日本語
Gnome-preferences-other.svg Extensions: Development Tag extensions Parser functions Hooks Special pages Skins Magic words API
Tools clipart.png This page is part of the MediaWiki API documentation.
MediaWiki API

Quick overview:

v · d · e

Creating API modules in extensions[edit | edit source]

Extensions can add API modules. Create a new class that inherits ApiBase (for a top-level module), ApiQueryBase (for a non-generator submodule of action=query) or ApiQueryGeneratorBase (for a submodule of action=query with generator functionality) and implement at a minimum the methods execute(), getAllowedParams(), getParamDescription(), and getDescription(). (In recent MediaWiki versions, the last three can omitted if you follow naming conventions; see API:Localisation#Help messages.)

Prefix[edit | edit source]

In the constructor of your API module, when you call parent::__construct() you can specify an optional prefix for your module's parameters. (In the generated documentation for a module this prefix, if any, appears in parentheses in the heading for the module.) If your module is a query submodule then you should give it a prefix, since a client can invoke multiple submodules each with its own parameters in a single request. If your module is a top-level action, then you may want to forgo a prefix.TODO: action=login is a counter-example, it uses the prefix lg for its parameters.

Registration[edit | edit source]

When you've created your new class, you need to register it with the API by adding it to one of $wgAPIModules (top-level modules, selected using action=), $wgAPIPropModules (prop= modules), $wgAPIMetaModules (meta= modules) or $wgAPIListModules (list= modules), like this:

 // Register the ApiMyExt class as handler for action=myext
$wgAPIModules['myext'] = 'ApiMyExt';

The key you use in the wgApiXxModules array should be unique and is available to your code via $this->getModuleName() to pass back unique values in the API results structure.


<translate>

MediaWiki version:</translate>

X.X

In MediaWiki 1.25 you can instead mention your API modules in extension.json, for example:

{
    "name": "MassMessage",
    ...
    "APIModules": {
        "massmessage": "ApiMassMessage",
        "editmassmessagelist": "ApiEditMassMessageList"
    },
    "APIListModules": {
        "mmsites": "ApiQueryMMSites"
    },
...
}

It's possible to override core modules.

Generator modules[edit | edit source]

A generator module is somewhat like UNIX piping, where the output of one module is the input of another. For example: You can ask for a list of all pages with list=allpages, and you can enumerate images on specific pages (by specifying page titles) with prop=images. allpages can also act as a generator, so you can "pipe" it to prop=images. By convention when a module acts as a generator its parameters, often the same as in its regular mode, are prefixed with 'g'. Thus api.php?action=query&generator=allpages&gaplimit=8&prop=images&imlimit=15 generates a list of the first 8 wiki pages, and from them shows up to 12 images in total. Generator modules also need to implement executeGenerator().

Extending core modules[edit | edit source]

Since MediaWiki 1.14, it's possible to extend core modules' functionality using the following hooks:

List of extensions with API functionality[edit | edit source]

See API extensions for examples of extensions that add or extend to the API.

Caching[edit | edit source]

By default ApiMain leaves caching of API calls up to the callee ('Cache-Control: private')! To modify this behavior for high volume requests add the following somewhere in your execute() method:

// Tell squids to cache
$this->getMain()->setCacheMode( 'public' );
// Set the squid & private cache time in seconds
$this->getMain()->setCacheMaxAge( 300 );

For query submodules (subclasses of ApiQueryBase or ApiQueryGeneratorBase), instead override getCacheMode() to allow ApiQuery to properly consider the needs of all executed submodules.

Returning errors[edit | edit source]

Some errors will be automatically generated if certain conditions that you set up are not met; for example, if the user fails to provide a title, then the "missingparam" error will be thrown if you have set getAllowedParams as follows:

// Title parameter.
public function getAllowedParams() {
	return array(
		'title' => array (
			ApiBase::PARAM_TYPE => 'string',
			ApiBase::PARAM_REQUIRED => true
		),
	);
}

Sometimes the types of error conditions set up by the methods supplied by ApiBase will not suffice and you will have to set up your own conditions. E.g., if you wanted to prevent the client from using interwiki links (e.g. wikiquote:MediaWiki) as titles, you might use:

$pageObj = $this->getTitleOrPageId( $params );
$titleObj = $pageObj->getTitle();
if ( $titleObj->isExternal() ) {
	$this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) );
}

That would throw the error defined in messageMap. See documentation for ApiBase::dieUsage, ApiBase::dieUsageMsg, and ApiBase::getPossibleErrors. For an example of how the latter is done, see ApiEditPage::getPossibleErrors.

Token handling[edit | edit source]

If your API module changes the wiki in any way, it should require a token of some kind. To have this handled automatically, implement the needsToken() method, returning the token that your module requires (probably the 'csrf' edit token, but there are other tokens such as 'userrights'). The API base code will then automatically validate the token that clients provide in API requests in a (prefix-less) token parameter.

TODO there used to be getTokenSalt() to return the token salt, now there's a rarely-overridden getWebUITokenSalt() method.

Returning results[edit | edit source]

Use $this->getResult()->addValue() to return an array of information to the API caller. See the example at Manual:ApiResult.php#Example. Pass your API module's name (available as $this->getModuleName()) as the second parameter so API results don't overlap.

Conventions[edit | edit source]

enabled

The presence of a key enabled (e.g. with value '') means true, absence means false.

Testing your extension[edit | edit source]

  • Visit api.php and navigate to the generated help for your module or query submodule. Your extension's help information should be correct.
    • The example URLs you provided in getExamplesMessages() should appear under "Examples", try clicking them.
    • Omit and mangle URL parameters in the query string, check your extension's response.
  • Install Extension:ApiSandbox and interactively explore your API.
  • Visit

to see additional information about your extension.

Sample API extension[edit | edit source]

An extension providing an API shares much setup code with other kinds of extensions; see Manual:Developing extensions for general information.

This is an example API extension that receives face (i.e. an emoticon) as a parameter and outputs various data (viz. reply emoticons and predictions) in response. For example:

to generate:

<api>
  <apisampleoutput apiresponses="are as follows">
    <nonverbalresponse emoticon="o_O"/>
    <predictions yourweek="You will learn something interesting and useful about API extensions this week"
      yourlife="You will become a successful MediaWiki hacker, which will serve you well in your life"
      eternity="Eventually all life will be destroyed in the heat death"/>
  </apisampleoutput>
</api>

To install it requires the usual procedure, i.e. copying the following three files into $IP/extensions/SampleApiExtension and adding to the end of LocalSettings.php:

require_once "$IP/extensions/SampleApiExtension/SampleApiExtension.php";

SampleApiExtension.php[edit | edit source]

Starting with MediaWiki 1.25, you can instead register your API modules in extension.json under the keys 'APIModules', 'APIFormatModules', 'APIListModules', 'APIMetaModules', and 'APIPropModules'.
<?php

// Take credit for your work, in the "api" category.
$wgExtensionCredits['api'][] = array(

	'path' => __FILE__,

	// The name of the extension, which will appear on Special:Version.
	'name' => 'Sample API Function',

	// A description of the extension, which will appear on Special:Version.
	'description' => 'A simple sample API extension',

	// Alternatively, you can specify a message key for the description.
	'descriptionmsg' => 'sampleapiextension-desc',

	// The version of the extension, which will appear on Special:Version.
	// This can be a number or a string.
	'version' => 1, 

	// Your name, which will appear on Special:Version.
	'author' => 'Me',

	// The URL to a wiki page/web page with information about the extension,
	// which will appear on Special:Version.
	'url' => 'https://www.mediawiki.org/wiki/API:Extensions',

);

// Map class name to filename for autoloading
$wgAutoloadClasses['ApiSample'] = __DIR__ . '/ApiSampleApiExtension.php';

// Map module name to class name
$wgAPIModules['apisampleoutput'] = 'ApiSample';

// Load the internationalization file
$wgExtensionMessagesFiles['myextension'] = __DIR__ . '/SampleApiExtension.i18n.php';

// Return true so that MediaWiki continues to load extensions.
return true;

ApiSampleApiExtension.php[edit | edit source]

<?php
class ApiSample extends ApiBase {
	public function execute() {
		// Get specific parameters
		// Using ApiMain::getVal makes a record of the fact that we've
		// used all the allowed parameters. Not doing this would add a
		// warning ("Unrecognized parameter") to the returned data.
		// If the warning doesn't bother you, you can use 
		// $params = $this->extractRequestParams();
		// to get all parameters as an associative array (e. g. $params[ 'face' ])
		$face = $this->getMain()->getVal( 'face' );

		// Default response is a wink ;)
		$emoticon = ';)';
		$result = $this->getResult();
		// Other responses depend on the value of the face parameter
		switch ( $face ) {
			case 'O_o':
				$emoticon = 'o_O';
				break;
			case 'o_O':
				$emoticon = 'O_o';
				break;
		}
		// Top level
		$this->getResult()->addValue( null, $this->getModuleName(), array ( 'apiresponses' => 'are as follows' ) );
		// Deliver a facial expression in reply
		$this->getResult()->addValue( null, $this->getModuleName()
			, array ( 'nonverbalresponse' => array ( 'emoticon' => $emoticon ) ) );
		// Offer a few predictions about the user's future
		$this->getResult()->addValue( null, $this->getModuleName()
			, array ( 'predictions' => array (
				'yourweek' => 'You will learn something interesting and useful about API extensions '
					.'this week' ,
				'yourlife' => 'You will become a successful MediaWiki hacker, which will serve you well '
					.'in your life' ,
				'eternity' => 'Eventually all life will be destroyed in the heat death' ) ) );
		return true;
	}

	// Description
	public function getDescription() {
		return 'Get both nonverbal and verbal responses to your input.';
	}

	// Face parameter.
	public function getAllowedParams() {
		return array_merge( parent::getAllowedParams(), array(
			'face' => array (
				ApiBase::PARAM_TYPE => 'string',
				ApiBase::PARAM_REQUIRED => true
			),
		) );
	}

	// Describe the parameter
	public function getParamDescription() {
		return array_merge( parent::getParamDescription(), array(
			'face' => 'The face you want to make to the API (e.g. o_O)'
		) );
	}

	// Get examples
	public function getExamplesMessages() {
		return array(
                        // apisampleoutput-face-1 is the key to an i18n message explaining the example
			'api.php?action=apisampleoutput&face=O_o&format=xml'
			=> 'apisampleoutput-face-1'
		);
	}
}

You can provide more information about your API by implementing the functions getResultProperties(), getPossibleErrors(), and getHelpUrls(). Clients can make an API call to api.php?action=paraminfo&module=apisampleoutput to retrieve this information.

SampleApiExtension.i18n.php[edit | edit source]

since MediaWiki 1.23 the preferred Localisation file format is i18n/lang_code.json, and from MediaWiki 1.25 it is recommended to instead use messages for ApiBase::PARAM_HELP_MSG in getAllowedParams() and in getExamplesMessages()
<?php
$messages = array();
$messages['en'] = array(
	'sampleapiextension-desc' => "This extension implements an apisampleoutput API module to provide, in response to "
	."input the user provides in the 'face' field, an emoticon and some plausible predictions. For example, try "
	."api.php?action=apisampleoutput&face=O_o&format=xml . For more information, see api.php",
);