From: Yuri Astrakhan Date: Wed, 27 Sep 2006 05:13:48 +0000 (+0000) Subject: * API: Refactored per brion's suggestions X-Git-Tag: 1.31.0-rc.0~55710 X-Git-Url: http://git.cyclocoop.org/fichier?a=commitdiff_plain;h=5c1ca0fc833201ab78ebef8a4140d1f53b8fbfbf;p=lhc%2Fweb%2Fwiklou.git * API: Refactored per brion's suggestions * API: began query revisions implementation (incomplete) --- diff --git a/api.php b/api.php index d862d6c1ae..d75ef100ab 100644 --- a/api.php +++ b/api.php @@ -29,11 +29,6 @@ $wgApiStartTime = microtime(true); */ define('API_DEFAULT_FORMAT', 'xmlfm'); -/** - * All API classes reside in this directory - */ -$wgApiDirectory = 'includes/api/'; - /** * List of classes and containing files. */ @@ -89,7 +84,7 @@ $wgApiFormats = array ( ); // Initialise common code -require_once ('./includes/WebStart.php'); +require (dirname(__FILE__) . "/includes/WebStart.php"); wfProfileIn('api.php'); // Verify that the API has not been disabled @@ -102,23 +97,20 @@ if (!isset ($wgEnableAPI) || !$wgEnableAPI) { die(-1); } -ApiInitAutoloadClasses($wgApiAutoloadClasses, $wgApiDirectory); +apiInitAutoloadClasses($wgApiAutoloadClasses, "$IP/includes/api/"); $processor = new ApiMain($wgApiStartTime, $wgApiModules, $wgApiFormats); -$processor->Execute(); +$processor->execute(); wfProfileOut('api.php'); wfLogProfilingData(); exit; // Done! -function ApiInitAutoloadClasses($apiAutoloadClasses, $apiDirectory) { +function apiInitAutoloadClasses($apiAutoloadClasses, $apiDirectory) { // Prefix each api class with the proper prefix, // and append them to $wgAutoloadClasses global $wgAutoloadClasses; - if (!isset ($wgAutoloadClasses)) - $wgAutoloadClasses = array (); - foreach ($apiAutoloadClasses as $className => $classFile) $wgAutoloadClasses[$className] = $apiDirectory . $classFile; } diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 649ae5112c..1f87592ce9 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -46,42 +46,42 @@ abstract class ApiBase { /** * Executes this module */ - abstract function Execute(); + abstract function execute(); /** * Get main module */ - public function GetMain() { + public function getMain() { return $this->mMainModule; } /** * If this module's $this is the same as $this->mMainModule, its the root, otherwise no */ - public function IsMain() { + public function isMain() { return $this === $this->mMainModule; } /** * Get result object */ - public function GetResult() { - // Main module has GetResult() method overriden + public function getResult() { + // Main module has getResult() method overriden // Safety - avoid infinite loop: - if ($this->IsMain()) - $this->DieDebug(__METHOD__ . + if ($this->isMain()) + $this->dieDebug(__METHOD__ . ' base method was called on main module. '); - return $this->GetMain()->GetResult(); + return $this->getMain()->getResult(); } /** * Generates help message for this module, or false if there is no description */ - public function MakeHelpMsg() { + public function makeHelpMsg() { static $lnPrfx = "\n "; - $msg = $this->GetDescription(); + $msg = $this->getDescription(); if ($msg !== false) { @@ -92,9 +92,9 @@ abstract class ApiBase { $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n"; // Parameters - $params = $this->GetAllowedParams(); + $params = $this->getAllowedParams(); if ($params !== false) { - $paramsDescription = $this->GetParamDescription(); + $paramsDescription = $this->getParamDescription(); $msg .= "Parameters:\n"; foreach (array_keys($params) as $paramName) { $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : ''; @@ -105,7 +105,7 @@ abstract class ApiBase { } // Examples - $examples = $this->GetExamples(); + $examples = $this->getExamples(); if ($examples !== false) { if (!is_array($examples)) $examples = array ( @@ -122,40 +122,40 @@ abstract class ApiBase { /** * Returns the description string for this module */ - protected function GetDescription() { + protected function getDescription() { return false; } /** * Returns usage examples for this module. Return null if no examples are available. */ - protected function GetExamples() { + protected function getExamples() { return false; } /** * Returns an array of allowed parameters (keys) => default value for that parameter */ - protected function GetAllowedParams() { + protected function getAllowedParams() { return false; } /** * Returns the description string for the given parameter. */ - protected function GetParamDescription() { + protected function getParamDescription() { return false; } /** - * Using GetAllowedParams(), makes an array of the values provided by the user, + * Using getAllowedParams(), makes an array of the values provided by the user, * with key being the name of the variable, and value - validated value from user or default. * This method can be used to generate local variables using extract(). */ - public function ExtractRequestParams() { + public function extractRequestParams() { global $wgRequest; - $params = $this->GetAllowedParams(); + $params = $this->getAllowedParams(); $results = array (); foreach ($params as $param => $enumParams) { @@ -184,17 +184,17 @@ abstract class ApiBase { if ($default !== false) { // Having a default value of anything other than 'false' is pointless - $this->DieDebug("Boolean param $param's default is set to '$default'"); + $this->dieDebug("Boolean param $param's default is set to '$default'"); } } $value = $wgRequest->getVal($param, $default); if (isset ($value) && ($multi || is_array($type))) - $value = $this->ParseMultiValue($param, $value, $multi, is_array($type) ? $type : null); + $value = $this->parseMultiValue($param, $value, $multi, is_array($type) ? $type : null); // More validation only when choices were not given - // choices were validated in ParseMultiValue() + // choices were validated in parseMultiValue() if (!is_array($type) && isset ($value)) { switch ($type) { @@ -207,25 +207,25 @@ abstract class ApiBase { break; case 'limit' : if (!isset ($enumParams[GN_ENUM_MAX1]) || !isset ($enumParams[GN_ENUM_MAX2])) - $this->DieDebug("MAX1 or MAX2 are not defined for the limit $param"); + $this->dieDebug("MAX1 or MAX2 are not defined for the limit $param"); if ($multi) - $this->DieDebug("Multi-values not supported for $param"); + $this->dieDebug("Multi-values not supported for $param"); $min = isset ($enumParams[GN_ENUM_MIN]) ? $enumParams[GN_ENUM_MIN] : 0; $value = intval($value); - $this->ValidateLimit($param, $value, $min, $enumParams[GN_ENUM_MAX1], $enumParams[GN_ENUM_MAX2]); + $this->validateLimit($param, $value, $min, $enumParams[GN_ENUM_MAX1], $enumParams[GN_ENUM_MAX2]); break; case 'boolean' : if ($multi) - $this->DieDebug("Multi-values not supported for $param"); + $this->dieDebug("Multi-values not supported for $param"); $value = isset ($value); break; case 'timestamp' : if ($multi) - $this->DieDebug("Multi-values not supported for $param"); + $this->dieDebug("Multi-values not supported for $param"); $value = $this->prepareTimestamp($value); // Adds quotes around timestamp break; default : - $this->DieDebug("Param $param's type is unknown - $type"); + $this->dieDebug("Param $param's type is unknown - $type"); } } @@ -246,16 +246,16 @@ abstract class ApiBase { * @param allowedValues - An array of values to check against. If null, all values are accepted. * @return (allowMultiple ? an_array_of_values : a_single_value) */ - protected function ParseMultiValue($valueName, $value, $allowMultiple, $allowedValues) { + protected function parseMultiValue($valueName, $value, $allowMultiple, $allowedValues) { $valuesList = explode('|', $value); if (!$allowMultiple && count($valuesList) != 1) { $possibleValues = is_array($allowedValues) ? "of '" . implode("', '", $allowedValues) . "'" : ''; - $this->DieUsage("Only one $possibleValues is allowed for parameter '$valueName'", "multival_$valueName"); + $this->dieUsage("Only one $possibleValues is allowed for parameter '$valueName'", "multival_$valueName"); } if (is_array($allowedValues)) { $unknownValues = array_diff($valuesList, $allowedValues); if ($unknownValues) { - $this->DieUsage("Unrecognised value" . (count($unknownValues) > 1 ? "s '" : " '") . implode("', '", $unknownValues) . "' for parameter '$valueName'", "unknown_$valueName"); + $this->dieUsage("Unrecognised value" . (count($unknownValues) > 1 ? "s '" : " '") . implode("', '", $unknownValues) . "' for parameter '$valueName'", "unknown_$valueName"); } } @@ -276,14 +276,14 @@ abstract class ApiBase { /** * Validate the value against the minimum and user/bot maximum limits. Prints usage info on failure. */ - function ValidateLimit($varname, $value, $min, $max, $botMax) { + function validateLimit($varname, $value, $min, $max, $botMax) { global $wgUser; if ($value < $min) { $this->dieUsage("$varname may not be less than $min (set to $value)", $varname); } - if ($this->GetMain()->IsBot()) { + if ($this->getMain()->isBot()) { if ($value > $botMax) { $this->dieUsage("$varname may not be over $botMax (set to $value) for bots", $varname); } @@ -297,12 +297,98 @@ abstract class ApiBase { /** * Call main module's error handler */ - public function DieUsage($description, $errorCode, $httpRespCode = 0) { - $this->GetMain()->MainDieUsage($description, $errorCode, $httpRespCode); + public function dieUsage($description, $errorCode, $httpRespCode = 0) { + $this->getMain()->mainDieUsage($description, $errorCode, $httpRespCode); } - protected function DieDebug($message) { + /** + * Internal code errors should be reported with this method + */ + protected function dieDebug($message) { wfDebugDieBacktrace("Internal error in '{get_class($this)}': $message"); } + + /** + * Profiling: total module execution time + */ + private $mTimeIn = 0, $mModuleTime = 0; + + /** + * Start module profiling + */ + public function profileIn() + { + if ($this->mTimeIn !== 0) + $this->dieDebug(__FUNCTION__ . ' called twice without calling profileOut()'); + $this->mTimeIn = microtime(true); + } + + /** + * End module profiling + */ + public function profileOut() + { + if ($this->mTimeIn === 0) + $this->dieDebug(__FUNCTION__ . ' called without calling profileIn() first'); + if ($this->mDBTimeIn !== 0) + $this->dieDebug(__FUNCTION__ . ' must be called after database profiling is done with profileDBOut()'); + + $this->mModuleTime += microtime(true) - $this->mTimeIn; + $this->mTimeIn = 0; + } + + /** + * Total time the module was executed + */ + public function getProfileTime() + { + if ($this->mTimeIn !== 0) + $this->dieDebug(__FUNCTION__ . ' called without calling profileOut() first'); + return $this->mModuleTime; + } + + /** + * Profiling: database execution time + */ + private $mDBTimeIn = 0, $mDBTime = 0; + + /** + * Start module profiling + */ + public function profileDBIn() + { + if ($this->mTimeIn === 0) + $this->dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()'); + if ($this->mDBTimeIn !== 0) + $this->dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()'); + $this->mDBTimeIn = microtime(true); + } + + /** + * End database profiling + */ + public function profileDBOut() + { + if ($this->mTimeIn === 0) + $this->dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()'); + if ($this->mDBTimeIn === 0) + $this->dieDebug(__FUNCTION__ . ' called without calling profileDBIn() first'); + + $time = microtime(true) - $this->mDBTimeIn; + $this->mDBTimeIn = 0; + + $this->mDBTime += $time; + $this->getMain()->mDBTime += $time; + } + + /** + * Total time the module used the database + */ + public function getProfileDBTime() + { + if ($this->mDBTimeIn !== 0) + $this->dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first'); + return $this->mDBTime; + } } ?> \ No newline at end of file diff --git a/includes/api/ApiFormatBase.php b/includes/api/ApiFormatBase.php index 716201f853..f0e9921806 100644 --- a/includes/api/ApiFormatBase.php +++ b/includes/api/ApiFormatBase.php @@ -50,12 +50,12 @@ abstract class ApiFormatBase extends ApiBase { /** * Overriding class returns the mime type that should be sent to the client. - * This method is not called if GetIsHtml() returns true. + * This method is not called if getIsHtml() returns true. * @return string */ - public abstract function GetMimeType(); + public abstract function getMimeType(); - public function GetNeedsRawData() { + public function getNeedsRawData() { return false; } @@ -64,7 +64,7 @@ abstract class ApiFormatBase extends ApiBase { * The default implementation assumes that formats ending with 'fm' * should be formatted in HTML. */ - public function GetIsHtml() { + public function getIsHtml() { return $this->mIsHtml; } @@ -73,9 +73,9 @@ abstract class ApiFormatBase extends ApiBase { * This method must be the first outputing method during execution. * A help screen's header is printed for the HTML-based output */ - function InitPrinter($isError) { - $isHtml = $this->GetIsHtml(); - $mime = $isHtml ? 'text/html' : $this->GetMimeType(); + function initPrinter($isError) { + $isHtml = $this->getIsHtml(); + $mime = $isHtml ? 'text/html' : $this->getMimeType(); header("Content-Type: $mime; charset=utf-8;"); if ($isHtml) { @@ -111,8 +111,8 @@ abstract class ApiFormatBase extends ApiBase { /** * Finish printing. Closes HTML tags. */ - public function ClosePrinter() { - if ($this->GetIsHtml()) { + public function closePrinter() { + if ($this->getIsHtml()) { ?> @@ -122,9 +122,9 @@ abstract class ApiFormatBase extends ApiBase { } } - public function PrintText($text) { - if ($this->GetIsHtml()) - echo $this->FormatHTML($text); + public function printText($text) { + if ($this->getIsHtml()) + echo $this->formatHTML($text); else echo $text; } @@ -133,7 +133,7 @@ abstract class ApiFormatBase extends ApiBase { * Prety-print various elements in HTML format, such as xml tags and URLs. * This method also replaces any "<" with < */ - protected function FormatHTML($text) { + protected function formatHTML($text) { // encode all tags as safe blue strings $text = ereg_replace('\<([^>]+)\>', '<\1>', $text); // identify URLs @@ -149,7 +149,7 @@ abstract class ApiFormatBase extends ApiBase { /** * Returns usage examples for this format. */ - protected function GetExamples() { + protected function getExamples() { return 'api.php?action=query&meta=siteinfo&si=namespaces&format=' . $this->mOriginalFormat; } } diff --git a/includes/api/ApiFormatJson.php b/includes/api/ApiFormatJson.php index 3563de3445..b24abfd80b 100644 --- a/includes/api/ApiFormatJson.php +++ b/includes/api/ApiFormatJson.php @@ -35,17 +35,17 @@ class ApiFormatJson extends ApiFormatBase { parent :: __construct($main, $format); } - public function GetMimeType() { + public function getMimeType() { return 'application/json'; } - public function Execute() { - require_once ('ApiFormatJson_json.php'); + public function execute() { + require ('ApiFormatJson_json.php'); $json = new Services_JSON(); - $this->PrintText($json->encode($this->GetResult()->GetData(), true)); + $this->printText($json->encode($this->getResult()->getData(), true)); } - protected function GetDescription() { + protected function getDescription() { return 'Output data in JSON format'; } } diff --git a/includes/api/ApiFormatXml.php b/includes/api/ApiFormatXml.php index b27763b6ad..06b93a0724 100644 --- a/includes/api/ApiFormatXml.php +++ b/includes/api/ApiFormatXml.php @@ -35,25 +35,25 @@ class ApiFormatXml extends ApiFormatBase { parent :: __construct($main, $format); } - public function GetMimeType() { + public function getMimeType() { return 'text/xml'; } - public function GetNeedsRawData() { + public function getNeedsRawData() { return true; } - public function Execute() { + public function execute() { $xmlindent = null; - extract($this->ExtractRequestParams()); + extract($this->extractRequestParams()); - if ($xmlindent || $this->GetIsHtml()) + if ($xmlindent || $this->getIsHtml()) $xmlindent = -2; else $xmlindent = null; - $this->PrintText(''); - $this->recXmlPrint('api', $this->GetResult()->GetData(), $xmlindent); + $this->printText(''); + $this->recXmlPrint('api', $this->getResult()->getData(), $xmlindent); } /** @@ -82,14 +82,14 @@ class ApiFormatXml extends ApiFormatBase { $subElemContent = $elemValue['*']; unset ($elemValue['*']); if (gettype($subElemContent) === 'array') { - $this->PrintText($indstr . wfElement($elemName, $elemValue, null)); + $this->printText($indstr . wfElement($elemName, $elemValue, null)); $this->recXmlPrint($elemName, $subElemContent, $indent); - $this->PrintText($indstr . ""); + $this->printText($indstr . ""); } else { - $this->PrintText($indstr . wfElement($elemName, $elemValue, $subElemContent)); + $this->printText($indstr . wfElement($elemName, $elemValue, $subElemContent)); } } else { - $this->PrintText($indstr . wfElement($elemName, null, null)); + $this->printText($indstr . wfElement($elemName, null, null)); if (array_key_exists('_element', $elemValue)) { $subElemName = $elemValue['_element']; foreach ($elemValue as $subElemId => & $subElemValue) { @@ -102,28 +102,28 @@ class ApiFormatXml extends ApiFormatBase { $this->recXmlPrint($subElemName, $subElemValue, $indent); } } - $this->PrintText($indstr . ""); + $this->printText($indstr . ""); } break; case 'object' : // ignore break; default : - $this->PrintText($indstr . wfElement($elemName, null, $elemValue)); + $this->printText($indstr . wfElement($elemName, null, $elemValue)); break; } } - protected function GetDescription() { + protected function getDescription() { return 'Output data in XML format'; } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( 'xmlindent' => false ); } - protected function GetParamDescription() { + protected function getParamDescription() { return array ( 'xmlindent' => 'Enable XML indentation' ); diff --git a/includes/api/ApiFormatYaml.php b/includes/api/ApiFormatYaml.php index 1311c90841..40b8375c93 100644 --- a/includes/api/ApiFormatYaml.php +++ b/includes/api/ApiFormatYaml.php @@ -35,16 +35,16 @@ class ApiFormatYaml extends ApiFormatBase { parent :: __construct($main, $format); } - public function GetMimeType() { + public function getMimeType() { return 'application/yaml'; } - public function Execute() { - require_once ('ApiFormatYaml_spyc.php'); - $this->PrintText(Spyc :: YAMLDump($this->GetResult()->GetData())); + public function execute() { + require ('ApiFormatYaml_spyc.php'); + $this->printText(Spyc :: YAMLDump($this->getResult()->getData())); } - protected function GetDescription() { + protected function getDescription() { return 'Output data in YAML format'; } } diff --git a/includes/api/ApiHelp.php b/includes/api/ApiHelp.php index 907fc2fe9d..bc8aca2bd9 100644 --- a/includes/api/ApiHelp.php +++ b/includes/api/ApiHelp.php @@ -38,11 +38,11 @@ class ApiHelp extends ApiBase { /** * Stub module for displaying help when no parameters are given */ - public function Execute() { - $this->DieUsage('', 'help'); + public function execute() { + $this->dieUsage('', 'help'); } - protected function GetDescription() { + protected function getDescription() { return array ( 'Display this help screen.' ); diff --git a/includes/api/ApiLogin.php b/includes/api/ApiLogin.php index ca5a5c72de..4a245451c7 100644 --- a/includes/api/ApiLogin.php +++ b/includes/api/ApiLogin.php @@ -35,9 +35,9 @@ class ApiLogin extends ApiBase { parent :: __construct($main); } - public function Execute() { + public function execute() { $lgname = $lgpassword = $lgdomain = null; - extract($this->ExtractRequestParams()); + extract($this->extractRequestParams()); $params = new FauxRequest(array ( 'wpName' => $lgname, @@ -76,13 +76,13 @@ class ApiLogin extends ApiBase { $result['result'] = 'AuthEmptyPass'; break; default : - $this->DieDebug("Unhandled case value"); + $this->dieDebug("Unhandled case value"); } - $this->GetResult()->AddMessage('login', null, $result); + $this->getResult()->addMessage('login', null, $result); } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( 'lgname' => '', 'lgpassword' => '', @@ -90,7 +90,7 @@ class ApiLogin extends ApiBase { ); } - protected function GetParamDescription() { + protected function getParamDescription() { return array ( 'lgname' => 'User Name', 'lgpassword' => 'Password', @@ -98,7 +98,7 @@ class ApiLogin extends ApiBase { ); } - protected function GetDescription() { + protected function getDescription() { return array ( 'This module is used to login and get the authentication tokens.' ); diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index e31c879e1b..2f2c12a7f6 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -29,22 +29,6 @@ if (!defined('MEDIAWIKI')) { require_once ("ApiBase.php"); } -/** -* @desc This exception will be thrown when DieUsage is called to stop module execution. -*/ -class UsageException extends Exception { - - private $codestr; - - public function __construct($message, $codestr) { - parent :: __construct($message); - $this->codestr = $codestr; - } - public function __toString() { - return "{$this->codestr}: {$this->message}"; - } -} - class ApiMain extends ApiBase { private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames, $mApiStartTime, $mResult; @@ -66,11 +50,11 @@ class ApiMain extends ApiBase { $this->mResult = new ApiResult($this); } - public function GetResult() { + public function getResult() { return $this->mResult; } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( 'format' => array ( GN_ENUM_DFLT => API_DEFAULT_FORMAT, @@ -83,53 +67,61 @@ class ApiMain extends ApiBase { ); } - protected function GetParamDescription() { + protected function getParamDescription() { return array ( 'format' => 'The format of the output', 'action' => 'What action you would like to perform' ); } - public function Execute() { + public function execute() { + $this->profileIn(); $action = $format = null; try { - extract($this->ExtractRequestParams()); + extract($this->extractRequestParams()); // Create an appropriate printer $this->mPrinter = new $this->mFormats[$format] ($this, $format); // Instantiate and execute module requested by the user $module = new $this->mModules[$action] ($this, $action); - $module->Execute(); - $this->PrintResult(false); + $module->profileIn(); + $module->execute(); + $module->profileOut(); + $this->printResult(false); } catch (UsageException $e) { - // Printer may not be initialized if the ExtractRequestParams() fails for the main module + // Printer may not be initialized if the extractRequestParams() fails for the main module if (!isset ($this->mPrinter)) $this->mPrinter = new $this->mFormats[API_DEFAULT_FORMAT] ($this, API_DEFAULT_FORMAT); - $this->PrintResult(true); + $this->printResult(true); } + $this->profileOut(); } /** * Internal printer */ - private function PrintResult($isError) { - $this->mPrinter->InitPrinter($isError); - if (!$this->mPrinter->GetNeedsRawData()) - $this->GetResult()->SanitizeData(); - $this->mPrinter->Execute(); - $this->mPrinter->ClosePrinter(); + private function printResult($isError) { + $printer = $this->mPrinter; + $printer->profileIn(); + $printer->initPrinter($isError); + if (!$printer->getNeedsRawData()) + $this->getResult()->SanitizeData(); + $printer->execute(); + $printer->closePrinter(); + $printer->profileOut(); } - protected function GetDescription() { + protected function getDescription() { return array ( '', 'This API allows programs to access various functions of MediaWiki software.', + 'For more details see API Home Page @ http://meta.wikimedia.org/wiki/API', '' ); } - public function MainDieUsage($description, $errorCode, $httpRespCode = 0) { + public function mainDieUsage($description, $errorCode, $httpRespCode = 0) { $this->mResult->Reset(); $this->mResult->addMessage('error', null, $errorCode); if ($httpRespCode === 0) @@ -137,7 +129,7 @@ class ApiMain extends ApiBase { else header($errorCode, true, $httpRespCode); - $this->mResult->addMessage('usage', null, $this->MakeHelpMsg()); + $this->mResult->addMessage('usage', null, $this->makeHelpMsg()); throw new UsageException($description, $errorCode); } @@ -145,17 +137,17 @@ class ApiMain extends ApiBase { /** * Override the parent to generate help messages for all available modules. */ - public function MakeHelpMsg() { + public function makeHelpMsg() { // Use parent to make default message for the main module - $msg = parent :: MakeHelpMsg(); + $msg = parent :: makeHelpMsg(); $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(); + $msg2 = $module->makeHelpMsg(); if ($msg2 !== false) $msg .= $msg2; $msg .= "\n"; @@ -165,7 +157,7 @@ class ApiMain extends ApiBase { foreach ($this->mFormats as $moduleName => $moduleClass) { $msg .= "* format=$moduleName *"; $module = new $this->mFormats[$moduleName] ($this, $moduleName); - $msg2 = $module->MakeHelpMsg(); + $msg2 = $module->makeHelpMsg(); if ($msg2 !== false) $msg .= $msg2; $msg .= "\n"; @@ -175,7 +167,7 @@ class ApiMain extends ApiBase { } private $mIsBot = null; - public function IsBot() { + public function isBot() { if (!isset ($this->mIsBot)) { global $wgUser; $this->mIsBot = $wgUser->isAllowed('bot'); @@ -183,4 +175,21 @@ class ApiMain extends ApiBase { return $this->mIsBot; } } + +/** +* @desc This exception will be thrown when dieUsage is called to stop module execution. +*/ +class UsageException extends Exception { + + private $codestr; + + public function __construct($message, $codestr) { + parent :: __construct($message); + $this->codestr = $codestr; + } + public function __toString() { + return "{$this->codestr}: {$this->message}"; + } +} + ?> \ No newline at end of file diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php index 4d779789ee..0a32b9a06d 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -31,43 +31,43 @@ if (!defined('MEDIAWIKI')) { class ApiPageSet extends ApiQueryBase { - private $allPages; // [ns][dbkey] => page_id or 0 when missing - private $resolveRedirs; - private $goodTitles, $missingTitles, $redirectTitles, $normalizedTitles; + private $mAllPages; // [ns][dbkey] => page_id or 0 when missing + private $mResolveRedirs; + private $mGoodTitles, $mMissingTitles, $mRedirectTitles, $mNormalizedTitles; public function __construct($query, $resolveRedirs) { parent :: __construct($query, __CLASS__); - $this->resolveRedirs = $resolveRedirs; + $this->mResolveRedirs = $resolveRedirs; - $this->allPages = array (); - $this->goodTitles = array (); - $this->missingTitles = array (); - $this->redirectTitles = array (); - $this->normalizedTitles = array (); + $this->mAllPages = array (); + $this->mGoodTitles = array (); + $this->mMissingTitles = array (); + $this->mRedirectTitles = array (); + $this->mNormalizedTitles = array (); } /** * Title objects that were found in the database. * @return array page_id (int) => Title (obj) */ - public function GetGoodTitles() { - return $this->goodTitles; + public function getGoodTitles() { + return $this->mGoodTitles; } /** * Title objects that were NOT found in the database. * @return array of Title objects */ - public function GetMissingTitles() { - return $this->missingTitles; + public function getMissingTitles() { + return $this->mMissingTitles; } /** * Get a list of redirects when doing redirect resolution * @return array prefixed_title (string) => prefixed_title (string) */ - public function GetRedirectTitles() { - return $this->redirectTitles; + public function getRedirectTitles() { + return $this->mRedirectTitles; } /** @@ -75,43 +75,15 @@ class ApiPageSet extends ApiQueryBase { * with its normalized version. * @return array raw_prefixed_title (string) => prefixed_title (string) */ - public function GetNormalizedTitles() { - return $this->normalizedTitles; + public function getNormalizedTitles() { + return $this->mNormalizedTitles; } /** - * Given an array of title strings, convert them into Title objects. - * This method validates access rights for the title, - * and appends normalization values to the output. - * - * @return LinkBatch of title objects. + * Returns the number of unique pages (not revisions) in the set. */ - private function ProcessTitlesStrings($titles) { - - $linkBatch = new LinkBatch(); - - foreach ($titles as $titleString) { - $titleObj = Title :: newFromText($titleString); - - // Validation - if (!$titleObj) - $this->dieUsage("bad title $titleString", 'invalidtitle'); - if ($titleObj->getNamespace() < 0) - $this->dieUsage("No support for special page $titleString has been implemented", 'unsupportednamespace'); - if (!$titleObj->userCanRead()) - $this->dieUsage("No read permission for $titleString", '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 is different - if ($titleString !== $titleObj->getPrefixedText()) { - $this->normalizedTitles[$titleString] = $titleObj->getPrefixedText(); - } - } - - return $linkBatch; + public function getPageCount() { + return count($this->getGoodTitles()); } /** @@ -128,27 +100,28 @@ class ApiPageSet extends ApiQueryBase { * #5 Substitute the original LinkBatch object with the new list * #6 Repeat from step #1 */ - public function PopulateTitles($titles) { + public function populateTitles($titles) { + $this->profileIn(); $pageFlds = array ( 'page_id', 'page_namespace', 'page_title' ); - if ($this->resolveRedirs) { + if ($this->mResolveRedirs) { $pageFlds[] = 'page_is_redirect'; } // Get validated and normalized title objects - $linkBatch = $this->ProcessTitlesStrings($titles); + $linkBatch = $this->processTitlesStrings($titles); - $db = $this->GetDB(); + $db = $this->getDB(); // // Repeat until all redirects have been resolved // while (false !== ($set = $linkBatch->constructSet('page', $db))) { - // Hack: Get the ns:titles stored in array(ns => array(titles)) format + // Hack: get the ns:titles stored in array(ns => array(titles)) format $remaining = $linkBatch->data; $redirectIds = array (); @@ -156,17 +129,19 @@ class ApiPageSet extends ApiQueryBase { // // Get data about $linkBatch from `page` table // + $this->profileDBIn(); $res = $db->select('page', $pageFlds, $set, __CLASS__ . '::' . __FUNCTION__); + $this->profileDBOut(); while ($row = $db->fetchObject($res)) { unset ($remaining[$row->page_namespace][$row->page_title]); $title = Title :: makeTitle($row->page_namespace, $row->page_title); - $this->allPages[$row->page_namespace][$row->page_title] = $row->page_id; + $this->mAllPages[$row->page_namespace][$row->page_title] = $row->page_id; - if ($this->resolveRedirs && $row->page_is_redirect == '1') { + if ($this->mResolveRedirs && $row->page_is_redirect == '1') { $redirectIds[$row->page_id] = $title; } else { - $this->goodTitles[$row->page_id] = $title; + $this->mGoodTitles[$row->page_id] = $title; } } $db->freeResult($res); @@ -176,12 +151,12 @@ class ApiPageSet extends ApiQueryBase { // foreach ($remaining as $ns => $dbkeys) { foreach ($dbkeys as $dbkey => $nothing) { - $this->missingTitles[] = Title :: makeTitle($ns, $dbkey); - $this->allPages[$ns][$dbkey] = 0; + $this->mMissingTitles[] = Title :: makeTitle($ns, $dbkey); + $this->mAllPages[$ns][$dbkey] = 0; } } - if (!$this->resolveRedirs || empty ($redirectIds)) + if (!$this->mResolveRedirs || empty ($redirectIds)) break; // @@ -192,6 +167,7 @@ class ApiPageSet extends ApiQueryBase { $linkBatch = new LinkBatch(); // find redirect targets for all redirect pages + $this->profileDBIn(); $res = $db->select('pagelinks', array ( 'pl_from', 'pl_namespace', @@ -199,7 +175,8 @@ class ApiPageSet extends ApiQueryBase { ), array ( 'pl_from' => array_keys($redirectIds )), __CLASS__ . '::' . __FUNCTION__); - + $this->profileDBOut(); + while ($row = $db->fetchObject($res)) { // Bug 7304 workaround @@ -210,22 +187,58 @@ class ApiPageSet extends ApiQueryBase { $titleStrFrom = $redirectIds[$row->pl_from]->getPrefixedText(); $titleStrTo = Title :: makeTitle($row->pl_namespace, $row->pl_title)->getPrefixedText(); - $this->redirectTitles[$titleStrFrom] = $titleStrTo; + $this->mRedirectTitles[$titleStrFrom] = $titleStrTo; unset ($redirectIds[$row->pl_from]); // remove line when 7304 is fixed // Avoid an infinite loop by checking if we have already processed this target - if (!isset ($this->allPages[$row->pl_namespace][$row->pl_title])) { + if (!isset ($this->mAllPages[$row->pl_namespace][$row->pl_title])) { $linkBatch->add($row->pl_namespace, $row->pl_title); } } } $db->freeResult($res); } + $this->profileOut(); + } + + /** + * Given an array of title strings, convert them into Title objects. + * This method validates access rights for the title, + * and appends normalization values to the output. + * + * @return LinkBatch of title objects. + */ + private function processTitlesStrings($titles) { + + $linkBatch = new LinkBatch(); + + foreach ($titles as $titleString) { + $titleObj = Title :: newFromText($titleString); + + // Validation + if (!$titleObj) + $this->dieUsage("bad title $titleString", 'invalidtitle'); + if ($titleObj->getNamespace() < 0) + $this->dieUsage("No support for special page $titleString has been implemented", 'unsupportednamespace'); + if (!$titleObj->userCanRead()) + $this->dieUsage("No read permission for $titleString", '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 is different + if ($titleString !== $titleObj->getPrefixedText()) { + $this->mNormalizedTitles[$titleString] = $titleObj->getPrefixedText(); + } + } + + return $linkBatch; } - public function Execute() { - $this->DieDebug("Execute() is not supported on this object"); + public function execute() { + $this->dieDebug("execute() is not supported on this object"); } } ?> \ No newline at end of file diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index f1220898f3..20ec0e8cba 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -75,13 +75,13 @@ class ApiQuery extends ApiBase { $this->mAllowedGenerators = array_merge($this->mListModuleNames, $this->mPropModuleNames); } - public function GetDB() { + public function getDB() { if (!isset ($this->mSlaveDB)) $this->mSlaveDB = & wfGetDB(DB_SLAVE); return $this->mSlaveDB; } - public function GetData() { + public function getData() { return $this->mData; } @@ -95,10 +95,10 @@ class ApiQuery extends ApiBase { * #4 Output all normalization and redirect resolution information * #5 Execute all requested modules */ - public function Execute() { + public function execute() { $meta = $prop = $list = $generator = $titles = $pageids = $revids = null; $redirects = null; - extract($this->ExtractRequestParams()); + extract($this->extractRequestParams()); // // Create and initialize PageSet @@ -109,12 +109,12 @@ class ApiQuery extends ApiBase { $dataSource = 'titles'; if (isset ($pageids)) { if (isset ($dataSource)) - $this->DieUsage("Cannot use 'pageids' at the same time as '$dataSource'", 'multisource'); + $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'); + $this->dieUsage("Cannot use 'revids' at the same time as '$dataSource'", 'multisource'); $dataSource = 'revids'; } @@ -122,13 +122,13 @@ class ApiQuery extends ApiBase { switch ($dataSource) { case 'titles' : - $this->mData->PopulateTitles($titles); + $this->mData->populateTitles($titles); break; case 'pageids' : - $this->mData->PopulatePageIDs($pageids); + $this->mData->populatePageIDs($pageids); break; case 'titles' : - $this->mData->PopulateRevIDs($revids); + $this->mData->populateRevIDs($revids); break; default : // Do nothing - some queries do not need any of the data sources. @@ -139,7 +139,7 @@ class ApiQuery extends ApiBase { // If generator is provided, get a new dataset to work on // if (isset ($generator)) - $this->ExecuteGenerator($generator, $redirects); + $this->executeGenerator($generator, $redirects); // Instantiate required modules // During instantiation, modules may optimize data requests through the $this->mData object @@ -156,8 +156,8 @@ class ApiQuery extends ApiBase { $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName); // Title normalizations - foreach ($this->mData->GetNormalizedTitles() as $rawTitleStr => $titleStr) { - $this->GetResult()->AddMessage('query', 'normalized', array ( + foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) { + $this->getResult()->addMessage('query', 'normalized', array ( 'from' => $rawTitleStr, 'to' => $titleStr ), 'n'); @@ -165,8 +165,8 @@ class ApiQuery extends ApiBase { // Show redirect information if ($redirects) { - foreach ($this->mData->GetRedirectTitles() as $titleStrFrom => $titleStrTo) { - $this->GetResult()->AddMessage('query', 'redirects', array ( + foreach ($this->mData->getRedirectTitles() as $titleStrFrom => $titleStrTo) { + $this->getResult()->addMessage('query', 'redirects', array ( 'from' => $titleStrFrom, 'to' => $titleStrTo ), 'r'); @@ -174,11 +174,14 @@ class ApiQuery extends ApiBase { } // Execute all requested modules. - foreach ($modules as $module) - $module->Execute(); + foreach ($modules as $module) { + $module->profileIn(); + $module->execute(); + $module->profileOut(); + } } - protected function ExecuteGenerator($generator, $redirects) { + protected function executeGenerator($generator, $redirects) { // Find class that implements requested generator if (isset ($this->mQueryListModules[$generator])) @@ -187,17 +190,17 @@ class ApiQuery extends ApiBase { if (isset ($this->mQueryPropModules[$generator])) $className = $this->mQueryPropModules[$generator]; else - $this->DieDebug("Unknown generator=$generator"); + $this->dieDebug("Unknown generator=$generator"); $module = new $className ($this, $generator, true); // change $this->mData // TODO: implement - $this->DieUsage("Generator execution has not been implemented", 'notimplemented'); + $this->dieUsage("Generator execution has not been implemented", 'notimplemented'); } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( 'meta' => array ( GN_ENUM_ISMULTI => true, @@ -232,10 +235,10 @@ class ApiQuery extends ApiBase { /** * Override the parent to generate help messages for all available query modules. */ - public function MakeHelpMsg() { + public function makeHelpMsg() { // Use parent to make default message for the query module - $msg = parent :: MakeHelpMsg(); + $msg = parent :: makeHelpMsg(); // Make sure the internal object is empty // (just in case a sub-module decides to optimize during instantiation) @@ -243,33 +246,33 @@ class ApiQuery extends ApiBase { $astriks = str_repeat('--- ', 8); $msg .= "\n$astriks Query: Meta $astriks\n\n"; - $msg .= $this->MakeHelpMsgHelper($this->mQueryMetaModules, 'meta'); + $msg .= $this->makeHelpMsgHelper($this->mQueryMetaModules, 'meta'); $msg .= "\n$astriks Query: Prop $astriks\n\n"; - $msg .= $this->MakeHelpMsgHelper($this->mQueryPropModules, 'prop'); + $msg .= $this->makeHelpMsgHelper($this->mQueryPropModules, 'prop'); $msg .= "\n$astriks Query: List $astriks\n\n"; - $msg .= $this->MakeHelpMsgHelper($this->mQueryListModules, 'list'); + $msg .= $this->makeHelpMsgHelper($this->mQueryListModules, 'list'); return $msg; } - private function MakeHelpMsgHelper($moduleList, $paramName) { + private function makeHelpMsgHelper($moduleList, $paramName) { $msg = ''; foreach ($moduleList as $moduleName => $moduleClass) { $msg .= "* $paramName=$moduleName *"; - $module = new $moduleClass ($this, $moduleName); - $msg2 = $module->MakeHelpMsg(); + $module = new $moduleClass ($this, $moduleName, null); + $msg2 = $module->makeHelpMsg(); if ($msg2 !== false) $msg .= $msg2; $msg .= "\n"; - if ($module->GetCanGenerate()) + if ($module->getCanGenerate()) $msg .= " * Can be used as a generator\n"; } return $msg; } - protected function GetParamDescription() { + protected function getParamDescription() { return array ( 'meta' => 'Which meta data to get about the site', 'prop' => 'Which properties to get for the titles/revisions/pageids', @@ -282,7 +285,7 @@ class ApiQuery extends ApiBase { ); } - protected function GetDescription() { + protected function getDescription() { 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.', @@ -290,7 +293,7 @@ class ApiQuery extends ApiBase { ); } - protected function GetExamples() { + protected function getExamples() { return array ( 'api.php?action=query&what=content&titles=ArticleA|ArticleB' ); diff --git a/includes/api/ApiQueryAllpages.php b/includes/api/ApiQueryAllpages.php index a69ad438bb..0a715eb818 100644 --- a/includes/api/ApiQueryAllpages.php +++ b/includes/api/ApiQueryAllpages.php @@ -35,16 +35,16 @@ class ApiQueryAllpages extends ApiQueryBase { parent :: __construct($query, $moduleName, $generator); } - public function Execute() { + public function execute() { $aplimit = $apfrom = $apnamespace = $apfilterredir = null; - extract($this->ExtractRequestParams()); + extract($this->extractRequestParams()); - $db = $this->GetDB(); + $db = $this->getDB(); $where = array ( 'page_namespace' => $apnamespace ); if (isset ($apfrom)) - $where[] = 'page_title>=' . $db->addQuotes(ApiQueryBase :: TitleToKey($apfrom)); + $where[] = 'page_title>=' . $db->addQuotes(ApiQueryBase :: titleToKey($apfrom)); if ($apfilterredir === 'redirects') $where['page_is_redirect'] = 1; @@ -52,6 +52,7 @@ class ApiQueryAllpages extends ApiQueryBase { if ($apfilterredir === 'nonredirects') $where['page_is_redirect'] = 0; + $this->profileDBIn(); $res = $db->select('page', array ( 'page_id', 'page_namespace', @@ -61,7 +62,8 @@ class ApiQueryAllpages extends ApiQueryBase { 'LIMIT' => $aplimit +1, 'ORDER BY' => 'page_namespace, page_title' )); - + $this->profileDBOut(); + $data = array (); $data['_element'] = 'p'; $count = 0; @@ -69,9 +71,9 @@ class ApiQueryAllpages extends ApiQueryBase { if (++ $count > $aplimit) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $msg = array ( - 'continue' => 'apfrom=' . ApiQueryBase :: KeyToTitle($row->page_title + 'continue' => 'apfrom=' . ApiQueryBase :: keyToTitle($row->page_title )); - $this->GetResult()->AddMessage('query-status', 'allpages', $msg); + $this->getResult()->addMessage('query-status', 'allpages', $msg); break; } @@ -91,10 +93,10 @@ class ApiQueryAllpages extends ApiQueryBase { } } $db->freeResult($res); - $this->GetResult()->AddMessage('query', 'allpages', $data); + $this->getResult()->addMessage('query', 'allpages', $data); } - protected function GetAllowedParams() { + protected function getAllowedParams() { global $wgContLang; $validNamespaces = array (); @@ -127,21 +129,21 @@ class ApiQueryAllpages extends ApiQueryBase { ); } - protected function GetParamDescription() { + protected function getParamDescription() { return array (); } - protected function GetDescription() { + protected function getDescription() { return 'Enumerate all pages sequentially in a given namespace'; } - protected function GetExamples() { + protected function getExamples() { return array ( 'api.php?action=query&list=allpages', 'api.php?action=query&list=allpages&apfrom=B&aplimit=5' ); } - public function GetCanGenerate() { + public function getCanGenerate() { return true; } } diff --git a/includes/api/ApiQueryBase.php b/includes/api/ApiQueryBase.php index f64acfb6bd..771c3edcc4 100644 --- a/includes/api/ApiQueryBase.php +++ b/includes/api/ApiQueryBase.php @@ -34,7 +34,7 @@ abstract class ApiQueryBase extends ApiBase { private $mQueryModule, $mModuleName, $mGenerator; public function __construct($query, $moduleName, $generator = false) { - parent :: __construct($query->GetMain()); + parent :: __construct($query->getMain()); $this->mQueryModule = $query; $this->mModuleName = $moduleName; $this->mGenerator = $generator; @@ -43,49 +43,50 @@ abstract class ApiQueryBase extends ApiBase { /** * Get the main Query module */ - public function GetQuery() { + public function getQuery() { return $this->mQueryModule; } /** * Get the name of the query being executed by this instance */ - public function GetModuleName() { + public function getModuleName() { return $this->mModuleName; } /** * Get the Query database connection (readonly) */ - protected function GetDB() { - return $this->GetQuery()->GetDB(); + protected function getDB() { + return $this->getQuery()->getDB(); } /** * Get the PageSet object to work on + * @return ApiPageSet data */ - protected function GetData() { - return $this->mQueryModule->GetData(); + protected function getData() { + return $this->mQueryModule->getData(); } /** * Return true if this instance is being used as a generator. */ - protected function GetIsGenerator() { + protected function getIsGenerator() { return $this->mGenerator; } /** * Derived classes return true when they can be used as title generators for other query modules. */ - public function GetCanGenerate() { + public function getCanGenerate() { return false; } - public static function TitleToKey($title) { + public static function titleToKey($title) { return str_replace(' ', '_', $title); } - public static function KeyToTitle($key) { + public static function keyToTitle($key) { return str_replace('_', ' ', $key); } } diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index 2cddeb8386..2387189d1d 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -31,15 +31,15 @@ if (!defined('MEDIAWIKI')) { class ApiQueryInfo extends ApiQueryBase { - public function __construct($main, $moduleName, $query) { - parent :: __construct($main, $moduleName, $query); + public function __construct($query, $moduleName, $generator = false) { + parent :: __construct($query, $moduleName, $generator); } - public function Execute() { + public function execute() { } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( 'param' => 'default', 'enumparam' => array ( @@ -53,15 +53,15 @@ class ApiQueryInfo extends ApiQueryBase { ); } - protected function GetParamDescription() { + protected function getParamDescription() { return array (); } - protected function GetDescription() { + protected function getDescription() { return 'module a'; } - protected function GetExamples() { + protected function getExamples() { return array ( 'http://...' ); diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index 5e25c22a7b..d3129b0646 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -35,13 +35,160 @@ class ApiQueryRevisions extends ApiQueryBase { parent :: __construct($query, $moduleName, $generator); } - public function Execute() { + public function execute() { + $rvlimit = $rvstartid = $rvendid = $rvstart = $rvend = $rvdir = $rvprop = null; + extract($this->extractRequestParams()); + // + // Parameter validation + // + + // true when ordered by timestamp from older to newer, false otherwise + $dirNewer = ($rvdir === 'newer'); + + // If any of those parameters are used, we work with single page only + $singePageMode = ($rvlimit !== 0 || $rvstartid !== 0 || $rvendid !== 0 || $dirNewer || isset ($rvstart) || isset ($rvend)); + + if ($rvstartid !== 0 || $rvendid !== 0) + $this->dieUsage('rvstartid/rvendid not implemented', 'notimplemented'); + + $data = $this->getData(); + $pageCount = $data->getPageCount(); + if ($singePageMode && $pageCount > 1) + $this->dieUsage('You have supplied multiple pages, but the specified revisions parameters may only be used with one page.', 'rv_multpages'); + + $tables = array ( + 'revision' + ); + $fields = array ( + 'rev_id', + 'rev_page', + 'rev_text_id', + 'rev_minor_edit' + ); + $conds = array ( + 'rev_deleted' => 0 + ); + $options = array (); + + $showTimestamp = $showUser = $showComment = $showContent = false; + if (isset ($rvprop)) { + foreach ($rvprop as $prop) { + switch ($prop) { + case 'timestamp' : + $fields[] = 'rev_timestamp'; + $showTimestamp = true; + break; + case 'user' : + $fields[] = 'rev_user'; + $fields[] = 'rev_user_text'; + $showUser = true; + break; + case 'comment' : + $fields[] = 'rev_comment'; + $showComment = true; + break; + case 'content' : + // todo: check the page count/limit when requesting content + //$this->validateLimit( 'content: (rvlimit*pages)+revids', + //$rvlimit * count($this->existingPageIds) + count($this->revIdsArray), 50, 200 ); + $tables[] = 'text'; + $conds[] = 'rev_text_id=old_id'; + $fields[] = 'old_id'; + $fields[] = 'old_text'; + $fields[] = 'old_flags'; + break; + default : + $this->dieDebug("unknown rvprop $prop"); + } + } + } + + if (isset ($rvstart)) + $conds[] = 'rev_timestamp >= ' . $this->prepareTimestamp($rvstart); + if (isset ($rvend)) + $conds[] = 'rev_timestamp <= ' . $this->prepareTimestamp($rvend); + + if ($singePageMode) { + if (!isset ($rvlimit)) + $rvlimit = 10; + + $options['LIMIT'] = $rvlimit + 1; + $options['ORDER BY'] = 'rev_timestamp' . ($dirNewer ? '' : ' DESC'); + + // get the first (and only) pageid => title pair + foreach($data->getGoodTitles() as $pageId => $titleObj) { + $conds['rev_page'] = $pageId; + break; + } + } + + $db = $this->getDB(); + $this->profileDBIn(); + $res = $db->select($tables, $fields, $conds, __CLASS__ . '::' . __FUNCTION__, $options); + $this->profileDBOut(); + + $data = array (); + $count = 0; + while ($row = $db->fetchObject($res)) { + + if (++ $count > $rvlimit) { + // We've reached the one extra which shows that there are additional pages to be had. Stop here... + $startStr = 'rvstartid=' . $row->rev_id; + $msg = array ('continue' => $startStr ); + $this->getResult()->addMessage('query-status', 'revisions', $msg); + break; + } + + + $revid = intval($row->rev_id); + $pageid = intval($row->rev_page); + + $vals = array ( + 'revid' => $revid, + 'oldid' => intval($row->rev_text_id + )); + + if( $row->rev_minor_edit ) { + $vals['minor'] = ''; + } + + if ($showTimestamp) + $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rev_timestamp); + + if ($showUser) { + $vals['user'] = $row->rev_user_text; + if( !$row->rev_user ) + $vals['anon'] = ''; + } + + if ($showComment) + $vals['comment'] = $row->rev_comment; + + if ($showContent) { + $vals['xml:space'] = 'preserve'; + $vals['*'] = Revision::getRevisionText( $row ); + } else { + $vals['*'] = ''; // Force all elements to be attributes + } + + $data[$pageid]['revisions']['_element'] = 'rv'; + $data[$pageid]['revisions'][$revid] = $vals; + } + $db->freeResult($res); + + $this->getResult()->addMessage('query', 'allpages', $data); } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( - 'rvlimit' => 0, + 'rvlimit' => array ( + GN_ENUM_DFLT => 0, + GN_ENUM_TYPE => 'limit', + GN_ENUM_MIN => 0, + GN_ENUM_MAX1 => 50, + GN_ENUM_MAX2 => 500 + ), 'rvstartid' => 0, 'rvendid' => 0, 'rvstart' => array ( @@ -51,7 +198,7 @@ class ApiQueryRevisions extends ApiQueryBase { GN_ENUM_TYPE => 'timestamp' ), 'rvdir' => array ( - GN_ENUM_DFLT => 'newer', + GN_ENUM_DFLT => 'older', GN_ENUM_TYPE => array ( 'newer', 'older' @@ -69,13 +216,13 @@ class ApiQueryRevisions extends ApiQueryBase { ); } - protected function GetDescription() { + protected function getDescription() { return 'module a'; } - protected function GetExamples() { + protected function getExamples() { return array ( - 'http://...' + 'api.php?action=query&prop=revisions&titles=ArticleA&rvprop=timestamp|user|comment|content' ); } } diff --git a/includes/api/ApiQuerySiteinfo.php b/includes/api/ApiQuerySiteinfo.php index 2d52e5a509..c561f50605 100644 --- a/includes/api/ApiQuerySiteinfo.php +++ b/includes/api/ApiQuerySiteinfo.php @@ -35,9 +35,9 @@ class ApiQuerySiteinfo extends ApiQueryBase { parent :: __construct($query, $moduleName); } - public function Execute() { + public function execute() { $siprop = null; - extract($this->ExtractRequestParams()); + extract($this->extractRequestParams()); foreach ($siprop as $prop) { switch ($prop) { @@ -52,7 +52,7 @@ class ApiQuerySiteinfo extends ApiQueryBase { $data['sitename'] = $wgSitename; $data['generator'] = "MediaWiki $wgVersion"; $data['case'] = $wgCapitalLinks ? 'first-letter' : 'case-sensitive'; // "case-insensitive" option is reserved for future - $this->GetResult()->AddMessage('query', $prop, $data); + $this->getResult()->addMessage('query', $prop, $data); break; case 'namespaces' : @@ -65,16 +65,16 @@ class ApiQuerySiteinfo extends ApiQueryBase { 'id' => $ns, '*' => $title ); - $this->GetResult()->AddMessage('query', $prop, $data); + $this->getResult()->addMessage('query', $prop, $data); break; default : - $this->DieDebug("Unknown siprop=$prop"); + $this->dieDebug("Unknown siprop=$prop"); } } } - protected function GetAllowedParams() { + protected function getAllowedParams() { return array ( 'siprop' => array ( GN_ENUM_DFLT => 'general', @@ -87,7 +87,7 @@ class ApiQuerySiteinfo extends ApiQueryBase { ); } - protected function GetParamDescription() { + protected function getParamDescription() { return array ( 'siprop' => array ( 'Which sysinfo properties to get:', @@ -97,11 +97,11 @@ class ApiQuerySiteinfo extends ApiQueryBase { ); } - protected function GetDescription() { + protected function getDescription() { return 'Return general information about the site.'; } - protected function GetExamples() { + protected function getExamples() { return 'api.php?action=query&meta=siteinfo&siprop=general|namespaces'; } } diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php index 43eaaf19d5..b35aed2f28 100644 --- a/includes/api/ApiResult.php +++ b/includes/api/ApiResult.php @@ -45,11 +45,11 @@ class ApiResult extends ApiBase { $this->mData = array (); } - function GetData() { + function getData() { return $this->mData; } - function AddMessage($mainSection, $subSection, $value, $multiitem = false, $preserveXmlSpacing = false) { + function addMessage($mainSection, $subSection, $value, $multiitem = false, $preserveXmlSpacing = false) { if (!array_key_exists($mainSection, $this->mData)) { $this->mData[$mainSection] = array (); } @@ -103,8 +103,8 @@ class ApiResult extends ApiBase { } } - public function Execute() { - $this->DieDebug("Execute() is not supported on Result object"); + public function execute() { + $this->dieDebug("execute() is not supported on Result object"); } } ?>