*/\r
\r
// Multi-valued enums, limit the values user can supply for the parameter\r
-define('GN_ENUM_DFLT', 0);\r
-define('GN_ENUM_ISMULTI', 1);\r
-define('GN_ENUM_CHOICES', 2);\r
+define('GN_ENUM_DFLT', 'dflt');\r
+define('GN_ENUM_ISMULTI', 'multi');\r
+define('GN_ENUM_CHOICES', 'choices');\r
+define('GN_ENUM_TYPE', 'type');\r
\r
abstract class ApiBase {\r
\r
*/\r
public function MakeHelpMsg() {\r
\r
+ static $lnPrfx = "\n ";\r
+\r
$msg = $this->GetDescription();\r
\r
if ($msg !== false) {\r
\r
- if (is_array($msg))\r
- $msg = implode("\n", $msg);\r
- $msg .= "\n";\r
+ if (!is_array($msg))\r
+ $msg = array (\r
+ $msg\r
+ );\r
+ $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n";\r
\r
// Parameters\r
$params = $this->GetAllowedParams();\r
if ($params !== false) {\r
$paramsDescription = $this->GetParamDescription();\r
- $msg .= "Supported Parameters:\n";\r
+ $msg .= "Parameters:\n";\r
foreach (array_keys($params) as $paramName) {\r
$desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : '';\r
$msg .= sprintf(" %-14s - %s\n", $paramName, $desc);\r
// Examples\r
$examples = $this->GetExamples();\r
if ($examples !== false) {\r
- if (is_array($examples)) {\r
- $msg .= "Examples:\n";\r
- $msg .= implode("\n ", $examples) . "\n";\r
- } else {\r
- $msg .= "Example: $examples\n";\r
- }\r
+ if (!is_array($examples))\r
+ $examples = array (\r
+ $examples\r
+ );\r
+ $msg .= 'Example' . (count($examples) > 1 ? 's' : '') . ":\n ";\r
+ $msg .= implode($lnPrfx, $examples) . "\n";\r
}\r
}\r
\r
$dflt = isset ($enumParams[GN_ENUM_DFLT]) ? $enumParams[GN_ENUM_DFLT] : null;\r
$multi = isset ($enumParams[GN_ENUM_ISMULTI]) ? $enumParams[GN_ENUM_ISMULTI] : false;\r
$choices = isset ($enumParams[GN_ENUM_CHOICES]) ? $enumParams[GN_ENUM_CHOICES] : null;\r
+ $type = isset ($enumParams[GN_ENUM_TYPE]) ? $enumParams[GN_ENUM_TYPE] : null;\r
+\r
$value = $wgRequest->getVal($param, $dflt);\r
- $result = $this->ParseMultiValue($param, $value, $multi, $choices);\r
+\r
+ // Allow null when default is not set\r
+ if (isset ($dflt) || isset ($value)) {\r
+ $result = $this->ParseMultiValue($param, $value, $multi, $choices);\r
+\r
+ // When choices are not given, and the default is an integer, make sure all values are integers\r
+ if (!isset ($choices) && isset ($dflt) && $type === 'integer') {\r
+ if (is_array($result))\r
+ $result = array_map('intval', $result);\r
+ else\r
+ $result = intval($result);\r
+ }\r
+ } else {\r
+ $result = null;\r
+ }\r
break;\r
default :\r
$this->DieDebug("In '$param', unprocessed type " . gettype($dflt));\r
* @desc This exception will be thrown when DieUsage is called to stop module execution.\r
*/\r
class UsageException extends Exception {\r
- var $codestr;\r
- \r
+ var $codestr;\r
+\r
public function __construct($message, $codestr) {\r
parent :: __construct($message);\r
- $this->codestr = $codestr;\r
+ $this->codestr = $codestr;\r
}\r
public function __toString() {\r
return "{$this->codestr}: {$this->message}";\r
}\r
\r
protected function GetDescription() {\r
- return "This API allows programs to access various functions of MediaWiki software.";\r
+ return array (\r
+ '',\r
+ 'This API allows programs to access various functions of MediaWiki software.',\r
+ ''\r
+ );\r
}\r
\r
public function MainDieUsage($description, $errorCode, $httpRespCode = 0) {\r
* Override the parent to generate help messages for all available modules.\r
*/\r
public function MakeHelpMsg() {\r
- \r
+\r
// Use parent to make default message for the main module\r
$msg = parent :: MakeHelpMsg();\r
- \r
- $msg .= "\n\n*Modules*\n";\r
+\r
+ $astriks = str_repeat('*** ', 10);\r
+ $msg .= "\n\n$astriks Modules $astriks\n\n";\r
foreach ($this->mModules as $moduleName => $moduleClass) {\r
+ $msg .= "* action=$moduleName *";\r
$module = new $this->mModules[$moduleName] ($this, $moduleName);\r
$msg2 = $module->MakeHelpMsg();\r
if ($msg2 !== false)\r
- $msg .= $msg2 . "\n";\r
+ $msg .= $msg2;\r
+ $msg .= "\n";\r
}\r
\r
- $msg .= "\n*Formats*\n";\r
+ $msg .= "\n$astriks Formats $astriks\n\n";\r
foreach ($this->mFormats as $moduleName => $moduleClass) {\r
+ $msg .= "* format=$moduleName *";\r
$module = new $this->mFormats[$moduleName] ($this, $moduleName);\r
$msg2 = $module->MakeHelpMsg();\r
if ($msg2 !== false)\r
- $msg .= $msg2 . "\n";\r
+ $msg .= $msg2;\r
+ $msg .= "\n";\r
}\r
- \r
+\r
return $msg;\r
}\r
}\r
\r
class ApiQuery extends ApiBase {\r
\r
+ var $mMetaModuleNames, $mPropModuleNames, $mListModuleNames;\r
+\r
+ private $mQueryMetaModules = array (\r
+// 'siteinfo' => 'ApiQuerySiteinfo',\r
+// 'userinfo' => 'ApiQueryUserinfo'\r
+ );\r
private $mQueryPropModules = array (\r
+// 'info' => 'ApiQueryInfo',\r
+// 'categories' => 'ApiQueryCategories',\r
+// 'imageinfo' => 'ApiQueryImageinfo',\r
+// 'langlinks' => 'ApiQueryLanglinks',\r
+// 'links' => 'ApiQueryLinks',\r
+// 'templates' => 'ApiQueryTemplates',\r
+// 'revisions' => 'ApiQueryRevisions',\r
+\r
+ // Should be removed\r
'content' => 'ApiQueryContent'\r
);\r
private $mQueryListModules = array (\r
- 'backlinks' => 'ApiQueryBacklinks'\r
+// 'allpages' => 'ApiQueryAllpages',\r
+// 'backlinks' => 'ApiQueryBacklinks',\r
+// 'categorymembers' => 'ApiQueryCategorymembers',\r
+// 'embeddedin' => 'ApiQueryEmbeddedin',\r
+// 'imagelinks' => 'ApiQueryImagelinks',\r
+// 'logevents' => 'ApiQueryLogevents',\r
+// 'recentchanges' => 'ApiQueryRecentchanges',\r
+// 'usercontribs' => 'ApiQueryUsercontribs',\r
+// 'users' => 'ApiQueryUsers',\r
+// 'watchlist' => 'ApiQueryWatchlist',\r
);\r
\r
private $mSlaveDB = null;\r
\r
- /**\r
- * Constructor\r
- */\r
public function __construct($main, $action) {\r
parent :: __construct($main);\r
+ $this->mMetaModuleNames = array_keys($this->mQueryMetaModules);\r
$this->mPropModuleNames = array_keys($this->mQueryPropModules);\r
$this->mListModuleNames = array_keys($this->mQueryListModules);\r
+ \r
+ $this->mAllowedGenerators = array_merge( $this->mListModuleNames, $this->mPropModuleNames);\r
}\r
\r
public function GetDB() {\r
}\r
\r
public function Execute() {\r
+ $meta = $prop = $list = $generator = $titles = $pageids = $revids = null;\r
+ $redirects = null;\r
+ extract($this->ExtractRequestParams());\r
+\r
+ //\r
+ // Only one of the titles/pageids/revids is allowed at the same time\r
+ //\r
+ $dataSource = null;\r
+ if (isset($titles))\r
+ $dataSource = 'titles';\r
+ if (isset($pageids)) {\r
+ if (isset($dataSource))\r
+ $this->DieUsage("Cannot use 'pageids' at the same time as '$dataSource'", 'multisource');\r
+ $dataSource = 'pageids';\r
+ }\r
+ if (isset($revids)) {\r
+ if (isset($dataSource))\r
+ $this->DieUsage("Cannot use 'revids' at the same time as '$dataSource'", 'multisource');\r
+ $dataSource = 'revids';\r
+ }\r
+ \r
+ //\r
+ // Normalize titles\r
+ //\r
+ if ($dataSource === 'titles') {\r
+ $linkBatch = new LinkBatch;\r
+ foreach ( $titles as &$titleString ) {\r
+ $titleObj = &Title::newFromText( $titleString );\r
+\r
+ // Validation\r
+ if (!$titleObj)\r
+ $this->dieUsage( "bad title $titleString", 'pi_invalidtitle' );\r
+ if ($titleObj->getNamespace() < 0)\r
+ $this->dieUsage( "No support for special page $titleString has been implemented", 'pi_unsupportednamespace' );\r
+ if (!$titleObj->userCanRead())\r
+ $this->dieUsage( "No read permission for $titleString", 'pi_titleaccessdenied' );\r
+\r
+ $linkBatch->addObj( $titleObj );\r
\r
+ // Make sure we remember the original title that was given to us\r
+ // This way the caller can correlate new titles with the originally requested, i.e. namespace is localized or capitalization\r
+ if( $titleString !== $titleObj->getPrefixedText() ) {\r
+ $this->GetResult()->AddMessage('query', 'normalized', array($titleString => $titleObj->getPrefixedText()));\r
+ }\r
+ }\r
+ }\r
}\r
\r
- /**\r
- * Returns an array of allowed parameters (keys) => default value for that parameter\r
- */\r
protected function GetAllowedParams() {\r
return array (\r
+ 'meta' => array (\r
+ GN_ENUM_ISMULTI => true,\r
+ GN_ENUM_CHOICES => $this->mMetaModuleNames\r
+ ),\r
+ 'prop' => array (\r
+ GN_ENUM_ISMULTI => true,\r
+ GN_ENUM_CHOICES => $this->mPropModuleNames\r
+ ),\r
+ 'list' => array (\r
+ GN_ENUM_ISMULTI => true,\r
+ GN_ENUM_CHOICES => $this->mListModuleNames\r
+ ),\r
+ 'generator' => array (\r
+ GN_ENUM_CHOICES => $this->mAllowedGenerators\r
+ ),\r
'titles' => array (\r
- GN_ENUM_DFLT => null,\r
GN_ENUM_ISMULTI => true\r
),\r
'pageids' => array (\r
- GN_ENUM_DFLT => 0,\r
+ GN_ENUM_TYPE => 'integer',\r
GN_ENUM_ISMULTI => true\r
),\r
'revids' => array (\r
- GN_ENUM_DFLT => 0,\r
+ GN_ENUM_TYPE => 'integer',\r
GN_ENUM_ISMULTI => true\r
- ),\r
- 'prop' => array (\r
- GN_ENUM_DFLT => null,\r
- GN_ENUM_ISMULTI => true,\r
- GN_ENUM_CHOICES => array_keys($this->mPropModuleNames\r
)\r
- ), 'list' => array (\r
- GN_ENUM_DFLT => null,\r
- GN_ENUM_ISMULTI => true,\r
- GN_ENUM_CHOICES => array_keys($this->mListModuleNames\r
- )));\r
+ );\r
+ }\r
+\r
+ protected function GetParamDescription() {\r
+ return array (\r
+ 'meta' => 'Which meta data to get about the site',\r
+ 'prop' => 'Which properties to get for the titles/revisions/pageids',\r
+ 'list' => 'Which lists to get',\r
+ 'generator' => 'Use the output of a list as the input for other prop/list/meta items',\r
+ 'titles' => 'A list of titles to work on',\r
+ 'pageids' => 'A list of page IDs to work on',\r
+ 'revids' => 'A list of revision IDs to work on'\r
+ );\r
}\r
\r
- /**\r
- * Returns the description string for this module\r
- */\r
protected function GetDescription() {\r
- return 'Query Module';\r
+ return array(\r
+ 'Query API module allows applications to get needed pieces of data from the MediaWiki databases,',\r
+ 'and is loosely based on the Query API interface currently available on all MediaWiki servers.',\r
+ 'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites.');\r
}\r
\r
- /**\r
- * Returns usage examples for this module. Return null if no examples are available.\r
- */\r
protected function GetExamples() {\r
return array (\r
'api.php ? action=query & what=content & titles=ArticleA|ArticleB'\r