From fcfcf6fdf9030696729bf912e3a029a4488547a1 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 23 Sep 2006 23:30:25 +0000 Subject: [PATCH] * API-query: normalization * API: help screen improvements --- includes/api/ApiBase.php | 49 ++++++++---- includes/api/ApiFormatBase.php | 2 +- includes/api/ApiHelp.php | 7 +- includes/api/ApiLogin.php | 18 +---- includes/api/ApiMain.php | 31 +++++--- includes/api/ApiQuery.php | 134 ++++++++++++++++++++++++++------- 6 files changed, 169 insertions(+), 72 deletions(-) diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index fb9395e695..b374d7325f 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -25,9 +25,10 @@ */ // Multi-valued enums, limit the values user can supply for the parameter -define('GN_ENUM_DFLT', 0); -define('GN_ENUM_ISMULTI', 1); -define('GN_ENUM_CHOICES', 2); +define('GN_ENUM_DFLT', 'dflt'); +define('GN_ENUM_ISMULTI', 'multi'); +define('GN_ENUM_CHOICES', 'choices'); +define('GN_ENUM_TYPE', 'type'); abstract class ApiBase { @@ -76,19 +77,23 @@ abstract class ApiBase { */ public function MakeHelpMsg() { + static $lnPrfx = "\n "; + $msg = $this->GetDescription(); if ($msg !== false) { - if (is_array($msg)) - $msg = implode("\n", $msg); - $msg .= "\n"; + if (!is_array($msg)) + $msg = array ( + $msg + ); + $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n"; // Parameters $params = $this->GetAllowedParams(); if ($params !== false) { $paramsDescription = $this->GetParamDescription(); - $msg .= "Supported Parameters:\n"; + $msg .= "Parameters:\n"; foreach (array_keys($params) as $paramName) { $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : ''; $msg .= sprintf(" %-14s - %s\n", $paramName, $desc); @@ -98,12 +103,12 @@ abstract class ApiBase { // Examples $examples = $this->GetExamples(); if ($examples !== false) { - if (is_array($examples)) { - $msg .= "Examples:\n"; - $msg .= implode("\n ", $examples) . "\n"; - } else { - $msg .= "Example: $examples\n"; - } + if (!is_array($examples)) + $examples = array ( + $examples + ); + $msg .= 'Example' . (count($examples) > 1 ? 's' : '') . ":\n "; + $msg .= implode($lnPrfx, $examples) . "\n"; } } @@ -167,8 +172,24 @@ abstract class ApiBase { $dflt = isset ($enumParams[GN_ENUM_DFLT]) ? $enumParams[GN_ENUM_DFLT] : null; $multi = isset ($enumParams[GN_ENUM_ISMULTI]) ? $enumParams[GN_ENUM_ISMULTI] : false; $choices = isset ($enumParams[GN_ENUM_CHOICES]) ? $enumParams[GN_ENUM_CHOICES] : null; + $type = isset ($enumParams[GN_ENUM_TYPE]) ? $enumParams[GN_ENUM_TYPE] : null; + $value = $wgRequest->getVal($param, $dflt); - $result = $this->ParseMultiValue($param, $value, $multi, $choices); + + // Allow null when default is not set + if (isset ($dflt) || isset ($value)) { + $result = $this->ParseMultiValue($param, $value, $multi, $choices); + + // When choices are not given, and the default is an integer, make sure all values are integers + if (!isset ($choices) && isset ($dflt) && $type === 'integer') { + if (is_array($result)) + $result = array_map('intval', $result); + else + $result = intval($result); + } + } else { + $result = null; + } break; default : $this->DieDebug("In '$param', unprocessed type " . gettype($dflt)); diff --git a/includes/api/ApiFormatBase.php b/includes/api/ApiFormatBase.php index b6195f5c3a..a6847e3e4e 100644 --- a/includes/api/ApiFormatBase.php +++ b/includes/api/ApiFormatBase.php @@ -81,12 +81,12 @@ abstract class ApiFormatBase extends ApiBase { MediaWiki API -
+
This result is being shown in mFormat?> format, which might not be suitable for your application.
diff --git a/includes/api/ApiHelp.php b/includes/api/ApiHelp.php index 80c96d6e2f..2eff7f08ca 100644 --- a/includes/api/ApiHelp.php +++ b/includes/api/ApiHelp.php @@ -31,9 +31,6 @@ if (!defined('MEDIAWIKI')) { class ApiHelp extends ApiBase { - /** - * Constructor - */ public function __construct($main, $action) { parent :: __construct($main); } @@ -44,5 +41,9 @@ class ApiHelp extends ApiBase { public function Execute() { $this->DieUsage('', 'help'); } + + protected function GetDescription() { + return array('Display this help screen.'); + } } ?> \ No newline at end of file diff --git a/includes/api/ApiLogin.php b/includes/api/ApiLogin.php index 79b4b7418a..349751e274 100644 --- a/includes/api/ApiLogin.php +++ b/includes/api/ApiLogin.php @@ -31,9 +31,6 @@ if (!defined('MEDIAWIKI')) { class ApiLogin extends ApiBase { - /** - * Constructor - */ public function __construct($main, $action) { parent :: __construct($main); } @@ -86,9 +83,6 @@ class ApiLogin extends ApiBase { $this->GetResult()->AddMessage('login', null, $result); } - /** - * Returns an array of allowed parameters (keys) => default value for that parameter - */ protected function GetAllowedParams() { return array ( 'lgname' => '', @@ -97,24 +91,16 @@ class ApiLogin extends ApiBase { ); } - /** - * Returns the description string for the given parameter. - */ protected function GetParamDescription() { return array ( 'lgname' => 'User Name', 'lgpassword' => 'Password', - 'lgdomain' => 'Domain (optional)', - + 'lgdomain' => 'Domain (optional)' ); } - /** - * Returns the description string for this module - */ protected function GetDescription() { - return array("*Login Module*", - "This module is used to login and get the authentication tokens."); + return array('This module is used to login and get the authentication tokens.'); } } ?> \ No newline at end of file diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index d206017593..2a6da70ca1 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -33,11 +33,11 @@ if (!defined('MEDIAWIKI')) { * @desc This exception will be thrown when DieUsage is called to stop module execution. */ class UsageException extends Exception { - var $codestr; - + var $codestr; + public function __construct($message, $codestr) { parent :: __construct($message); - $this->codestr = $codestr; + $this->codestr = $codestr; } public function __toString() { return "{$this->codestr}: {$this->message}"; @@ -119,7 +119,11 @@ class ApiMain extends ApiBase { } protected function GetDescription() { - return "This API allows programs to access various functions of MediaWiki software."; + return array ( + '', + 'This API allows programs to access various functions of MediaWiki software.', + '' + ); } public function MainDieUsage($description, $errorCode, $httpRespCode = 0) { @@ -139,26 +143,31 @@ class ApiMain extends ApiBase { * Override the parent to generate help messages for all available modules. */ public function MakeHelpMsg() { - + // Use parent to make default message for the main module $msg = parent :: MakeHelpMsg(); - - $msg .= "\n\n*Modules*\n"; + + $astriks = str_repeat('*** ', 10); + $msg .= "\n\n$astriks Modules $astriks\n\n"; foreach ($this->mModules as $moduleName => $moduleClass) { + $msg .= "* action=$moduleName *"; $module = new $this->mModules[$moduleName] ($this, $moduleName); $msg2 = $module->MakeHelpMsg(); if ($msg2 !== false) - $msg .= $msg2 . "\n"; + $msg .= $msg2; + $msg .= "\n"; } - $msg .= "\n*Formats*\n"; + $msg .= "\n$astriks Formats $astriks\n\n"; foreach ($this->mFormats as $moduleName => $moduleClass) { + $msg .= "* format=$moduleName *"; $module = new $this->mFormats[$moduleName] ($this, $moduleName); $msg2 = $module->MakeHelpMsg(); if ($msg2 !== false) - $msg .= $msg2 . "\n"; + $msg .= $msg2; + $msg .= "\n"; } - + return $msg; } } diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index b692a983f0..501ebb0787 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -31,22 +31,46 @@ if (!defined('MEDIAWIKI')) { class ApiQuery extends ApiBase { + var $mMetaModuleNames, $mPropModuleNames, $mListModuleNames; + + private $mQueryMetaModules = array ( +// 'siteinfo' => 'ApiQuerySiteinfo', +// 'userinfo' => 'ApiQueryUserinfo' + ); private $mQueryPropModules = array ( +// 'info' => 'ApiQueryInfo', +// 'categories' => 'ApiQueryCategories', +// 'imageinfo' => 'ApiQueryImageinfo', +// 'langlinks' => 'ApiQueryLanglinks', +// 'links' => 'ApiQueryLinks', +// 'templates' => 'ApiQueryTemplates', +// 'revisions' => 'ApiQueryRevisions', + + // Should be removed 'content' => 'ApiQueryContent' ); private $mQueryListModules = array ( - 'backlinks' => 'ApiQueryBacklinks' +// 'allpages' => 'ApiQueryAllpages', +// 'backlinks' => 'ApiQueryBacklinks', +// 'categorymembers' => 'ApiQueryCategorymembers', +// 'embeddedin' => 'ApiQueryEmbeddedin', +// 'imagelinks' => 'ApiQueryImagelinks', +// 'logevents' => 'ApiQueryLogevents', +// 'recentchanges' => 'ApiQueryRecentchanges', +// 'usercontribs' => 'ApiQueryUsercontribs', +// 'users' => 'ApiQueryUsers', +// 'watchlist' => 'ApiQueryWatchlist', ); private $mSlaveDB = null; - /** - * Constructor - */ public function __construct($main, $action) { parent :: __construct($main); + $this->mMetaModuleNames = array_keys($this->mQueryMetaModules); $this->mPropModuleNames = array_keys($this->mQueryPropModules); $this->mListModuleNames = array_keys($this->mQueryListModules); + + $this->mAllowedGenerators = array_merge( $this->mListModuleNames, $this->mPropModuleNames); } public function GetDB() { @@ -56,48 +80,104 @@ class ApiQuery extends ApiBase { } public function Execute() { + $meta = $prop = $list = $generator = $titles = $pageids = $revids = null; + $redirects = null; + extract($this->ExtractRequestParams()); + + // + // Only one of the titles/pageids/revids is allowed at the same time + // + $dataSource = null; + if (isset($titles)) + $dataSource = 'titles'; + if (isset($pageids)) { + if (isset($dataSource)) + $this->DieUsage("Cannot use 'pageids' at the same time as '$dataSource'", 'multisource'); + $dataSource = 'pageids'; + } + if (isset($revids)) { + if (isset($dataSource)) + $this->DieUsage("Cannot use 'revids' at the same time as '$dataSource'", 'multisource'); + $dataSource = 'revids'; + } + + // + // Normalize titles + // + if ($dataSource === 'titles') { + $linkBatch = new LinkBatch; + foreach ( $titles as &$titleString ) { + $titleObj = &Title::newFromText( $titleString ); + + // Validation + if (!$titleObj) + $this->dieUsage( "bad title $titleString", 'pi_invalidtitle' ); + if ($titleObj->getNamespace() < 0) + $this->dieUsage( "No support for special page $titleString has been implemented", 'pi_unsupportednamespace' ); + if (!$titleObj->userCanRead()) + $this->dieUsage( "No read permission for $titleString", 'pi_titleaccessdenied' ); + + $linkBatch->addObj( $titleObj ); + // Make sure we remember the original title that was given to us + // This way the caller can correlate new titles with the originally requested, i.e. namespace is localized or capitalization + if( $titleString !== $titleObj->getPrefixedText() ) { + $this->GetResult()->AddMessage('query', 'normalized', array($titleString => $titleObj->getPrefixedText())); + } + } + } } - /** - * Returns an array of allowed parameters (keys) => default value for that parameter - */ protected function GetAllowedParams() { return array ( + 'meta' => array ( + GN_ENUM_ISMULTI => true, + GN_ENUM_CHOICES => $this->mMetaModuleNames + ), + 'prop' => array ( + GN_ENUM_ISMULTI => true, + GN_ENUM_CHOICES => $this->mPropModuleNames + ), + 'list' => array ( + GN_ENUM_ISMULTI => true, + GN_ENUM_CHOICES => $this->mListModuleNames + ), + 'generator' => array ( + GN_ENUM_CHOICES => $this->mAllowedGenerators + ), 'titles' => array ( - GN_ENUM_DFLT => null, GN_ENUM_ISMULTI => true ), 'pageids' => array ( - GN_ENUM_DFLT => 0, + GN_ENUM_TYPE => 'integer', GN_ENUM_ISMULTI => true ), 'revids' => array ( - GN_ENUM_DFLT => 0, + GN_ENUM_TYPE => 'integer', GN_ENUM_ISMULTI => true - ), - 'prop' => array ( - GN_ENUM_DFLT => null, - GN_ENUM_ISMULTI => true, - GN_ENUM_CHOICES => array_keys($this->mPropModuleNames ) - ), 'list' => array ( - GN_ENUM_DFLT => null, - GN_ENUM_ISMULTI => true, - GN_ENUM_CHOICES => array_keys($this->mListModuleNames - ))); + ); + } + + protected function GetParamDescription() { + return array ( + 'meta' => 'Which meta data to get about the site', + 'prop' => 'Which properties to get for the titles/revisions/pageids', + 'list' => 'Which lists to get', + 'generator' => 'Use the output of a list as the input for other prop/list/meta items', + 'titles' => 'A list of titles to work on', + 'pageids' => 'A list of page IDs to work on', + 'revids' => 'A list of revision IDs to work on' + ); } - /** - * Returns the description string for this module - */ protected function GetDescription() { - return 'Query Module'; + return array( + 'Query API module allows applications to get needed pieces of data from the MediaWiki databases,', + 'and is loosely based on the Query API interface currently available on all MediaWiki servers.', + 'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites.'); } - /** - * Returns usage examples for this module. Return null if no examples are available. - */ protected function GetExamples() { return array ( 'api.php ? action=query & what=content & titles=ArticleA|ArticleB' -- 2.20.1