From 85de1cb74b52e280939e0b99213916c7faa9cb1d Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 1 Oct 2006 04:38:31 +0000 Subject: [PATCH] * Code cleanup per TimStarling's suggestions --- api.php | 229 ++++---- includes/api/ApiBase.php | 809 +++++++++++++++-------------- includes/api/ApiLogin.php | 31 +- includes/api/ApiMain.php | 392 +++++++------- includes/api/ApiPageSet.php | 44 +- includes/api/ApiQuery.php | 581 +++++++++++---------- includes/api/ApiQueryAllpages.php | 18 +- includes/api/ApiQueryInfo.php | 6 +- includes/api/ApiQueryRevisions.php | 24 +- includes/api/ApiQuerySiteinfo.php | 6 +- includes/api/ApiResult.php | 286 +++++----- 11 files changed, 1225 insertions(+), 1201 deletions(-) diff --git a/api.php b/api.php index c96c6470c2..a2c2c054d3 100644 --- a/api.php +++ b/api.php @@ -1,117 +1,112 @@ - -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* http://www.gnu.org/copyleft/gpl.html -*/ - -$wgApiStartTime = microtime(true); - -/** - * When no format parameter is given, this format will be used - */ -define('API_DEFAULT_FORMAT', 'xmlfm'); - -/** - * List of classes and containing files. - */ -$wgApiAutoloadClasses = array ( - - 'ApiMain' => 'ApiMain.php', - - // Utility classes - 'ApiBase' => 'ApiBase.php', - 'ApiQueryBase' => 'ApiQueryBase.php', - 'ApiResult' => 'ApiResult.php', - 'ApiPageSet' => 'ApiPageSet.php', - - // Formats - 'ApiFormatBase' => 'ApiFormatBase.php', - 'ApiFormatYaml' => 'ApiFormatYaml.php', - 'ApiFormatXml' => 'ApiFormatXml.php', - 'ApiFormatJson' => 'ApiFormatJson.php', - - // Modules (action=...) - should match the $apiModules list - 'ApiHelp' => 'ApiHelp.php', - 'ApiLogin' => 'ApiLogin.php', - 'ApiQuery' => 'ApiQuery.php', - - // Query items (meta/prop/list=...) - 'ApiQuerySiteinfo' => 'ApiQuerySiteinfo.php', - 'ApiQueryInfo' => 'ApiQueryInfo.php', - 'ApiQueryRevisions' => 'ApiQueryRevisions.php', - 'ApiQueryAllpages' => 'ApiQueryAllpages.php' -); - -/** - * List of available modules: action name => module class - * The class must also be listed in the $wgApiAutoloadClasses array. - */ -$wgApiModules = array ( - 'help' => 'ApiHelp', - 'login' => 'ApiLogin', - 'query' => 'ApiQuery' -); - -/** - * List of available formats: format name => format class - * The class must also be listed in the $wgApiAutoloadClasses array. - */ -$wgApiFormats = array ( - 'json' => 'ApiFormatJson', - 'jsonfm' => 'ApiFormatJson', - 'xml' => 'ApiFormatXml', - 'xmlfm' => 'ApiFormatXml', - 'yaml' => 'ApiFormatYaml', - 'yamlfm' => 'ApiFormatYaml' -); - -// Initialise common code -require (dirname(__FILE__) . '/includes/WebStart.php'); -wfProfileIn('api.php'); - -// Verify that the API has not been disabled -// The next line should be -// if (isset ($wgEnableAPI) && !$wgEnableAPI) { -// but will be in a safe mode until api is stabler -if (!isset ($wgEnableAPI) || !$wgEnableAPI) { - echo 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php'; - echo '
$wgEnableAPI=true;
'; - die(-1); -} - -apiInitAutoloadClasses($wgApiAutoloadClasses, "$IP/includes/api/"); -$processor = new ApiMain($wgApiStartTime, $wgApiModules, $wgApiFormats); -$processor->execute(); - -wfProfileOut('api.php'); -wfLogProfilingData(); -exit; // Done! - -function apiInitAutoloadClasses($apiAutoloadClasses, $apiDirectory) { - - // Prefix each api class with the proper prefix, - // and append them to $wgAutoloadClasses - global $wgAutoloadClasses; - - foreach ($apiAutoloadClasses as $className => $classFile) - $wgAutoloadClasses[$className] = $apiDirectory . $classFile; -} -?> + +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* http://www.gnu.org/copyleft/gpl.html +*/ + +$wgApiStartTime = microtime(true); + +/** + * When no format parameter is given, this format will be used + */ +define('API_DEFAULT_FORMAT', 'xmlfm'); + +/** + * Location of all api-related files (must end with a slash '/') + */ +define('API_DIR', 'includes/api/'); + +/** + * List of classes and containing files. + */ +$wgApiAutoloadClasses = array ( + + 'ApiMain' => API_DIR . 'ApiMain.php', + + // Utility classes + 'ApiBase' => API_DIR . 'ApiBase.php', + 'ApiQueryBase' => API_DIR . 'ApiQueryBase.php', + 'ApiResult' => API_DIR . 'ApiResult.php', + 'ApiPageSet' => API_DIR . 'ApiPageSet.php', + + // Formats + 'ApiFormatBase' => API_DIR . 'ApiFormatBase.php', + 'ApiFormatYaml' => API_DIR . 'ApiFormatYaml.php', + 'ApiFormatXml' => API_DIR . 'ApiFormatXml.php', + 'ApiFormatJson' => API_DIR . 'ApiFormatJson.php', + + // Modules (action=...) - should match the $apiModules list + 'ApiHelp' => API_DIR . 'ApiHelp.php', + 'ApiLogin' => API_DIR . 'ApiLogin.php', + 'ApiQuery' => API_DIR . 'ApiQuery.php', + + // Query items (meta/prop/list=...) + 'ApiQuerySiteinfo' => API_DIR . 'ApiQuerySiteinfo.php', + 'ApiQueryInfo' => API_DIR . 'ApiQueryInfo.php', + 'ApiQueryRevisions' => API_DIR . 'ApiQueryRevisions.php', + 'ApiQueryAllpages' => API_DIR . 'ApiQueryAllpages.php' +); + +/** + * List of available modules: action name => module class + * The class must also be listed in the $wgApiAutoloadClasses array. + */ +$wgApiModules = array ( + 'help' => 'ApiHelp', + 'login' => 'ApiLogin', + 'query' => 'ApiQuery' +); + +/** + * List of available formats: format name => format class + * The class must also be listed in the $wgApiAutoloadClasses array. + */ +$wgApiFormats = array ( + 'json' => 'ApiFormatJson', + 'jsonfm' => 'ApiFormatJson', + 'xml' => 'ApiFormatXml', + 'xmlfm' => 'ApiFormatXml', + 'yaml' => 'ApiFormatYaml', + 'yamlfm' => 'ApiFormatYaml' +); + +// Initialise common code +require (dirname(__FILE__) . '/includes/WebStart.php'); +wfProfileIn('api.php'); + +// Verify that the API has not been disabled +// The next line should be +// if (isset ($wgEnableAPI) && !$wgEnableAPI) { +// but will be in a safe mode until api is stabler +if (!isset ($wgEnableAPI) || !$wgEnableAPI) { + echo 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php'; + echo '
$wgEnableAPI=true;
'; + die(-1); +} + +$wgAutoloadClasses = array_merge($wgAutoloadClasses, $wgApiAutoloadClasses); +$processor = new ApiMain($wgApiStartTime, $wgApiModules, $wgApiFormats); +$processor->execute(); + +wfProfileOut('api.php'); +wfLogProfilingData(); +exit; // Done! +?> diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 46aa903a17..d0aab377ca 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -1,405 +1,406 @@ - - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * http://www.gnu.org/copyleft/gpl.html - */ - -// Multi-valued enums, limit the values user can supply for the parameter -define('GN_ENUM_DFLT', 'dflt'); -define('GN_ENUM_ISMULTI', 'multi'); -define('GN_ENUM_TYPE', 'type'); -define('GN_ENUM_MAX1', 'max1'); -define('GN_ENUM_MAX2', 'max2'); -define('GN_ENUM_MIN', 'min'); - -abstract class ApiBase { - - private $mMainModule; - - /** - * Constructor - */ - public function __construct($mainModule) { - $this->mMainModule = $mainModule; - } - - /** - * Executes this module - */ - abstract function execute(); - - /** - * Get main module - */ - 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() { - return $this === $this->mMainModule; - } - - /** - * Get result object - */ - public function getResult() { - // Main module has getResult() method overriden - // Safety - avoid infinite loop: - if ($this->isMain()) - ApiBase :: dieDebug(__METHOD__ . - ' base method was called on main module. '); - return $this->getMain()->getResult(); - } - - /** - * Get the result data array - */ - public function & getResultData() { - return $this->getResult()->getData(); - } - - /** - * Generates help message for this module, or false if there is no description - */ - public function makeHelpMsg() { - - static $lnPrfx = "\n "; - - $msg = $this->getDescription(); - - if ($msg !== false) { - - if (!is_array($msg)) - $msg = array ( - $msg - ); - $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n"; - - // Parameters - $paramsMsg = $this->makeHelpMsgParameters(); - if ($paramsMsg !== false) { - $msg .= "Parameters:\n$paramsMsg"; - } - - // Examples - $examples = $this->getExamples(); - if ($examples !== false) { - if (!is_array($examples)) - $examples = array ( - $examples - ); - $msg .= 'Example' . (count($examples) > 1 ? 's' : '') . ":\n "; - $msg .= implode($lnPrfx, $examples) . "\n"; - } - } - - return $msg; - } - - public function makeHelpMsgParameters() { - $params = $this->getAllowedParams(); - if ($params !== false) { - - $paramsDescription = $this->getParamDescription(); - $msg = ''; - foreach (array_keys($params) as $paramName) { - $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : ''; - if (is_array($desc)) - $desc = implode("\n" . str_repeat(' ', 19), $desc); - $msg .= sprintf(" %-14s - %s\n", $paramName, $desc); - } - return $msg; - - } else - return false; - } - - /** - * Returns the description string for this module - */ - protected function getDescription() { - return false; - } - - /** - * Returns usage examples for this module. Return null if no examples are available. - */ - protected function getExamples() { - return false; - } - - /** - * Returns an array of allowed parameters (keys) => default value for that parameter - */ - protected function getAllowedParams() { - return false; - } - - /** - * Returns the description string for the given parameter. - */ - protected function getParamDescription() { - return false; - } - - /** - * 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() { - $params = $this->getAllowedParams(); - $results = array (); - - foreach ($params as $paramName => $paramSettings) - $results[$paramName] = $this->getParameter($paramName, $paramSettings); - - return $results; - } - - public function getParameter($paramName, $paramSettings) { - global $wgRequest; - - if (!is_array($paramSettings)) { - $default = $paramSettings; - $multi = false; - $type = gettype($paramSettings); - } else { - $default = isset ($paramSettings[GN_ENUM_DFLT]) ? $paramSettings[GN_ENUM_DFLT] : null; - $multi = isset ($paramSettings[GN_ENUM_ISMULTI]) ? $paramSettings[GN_ENUM_ISMULTI] : false; - $type = isset ($paramSettings[GN_ENUM_TYPE]) ? $paramSettings[GN_ENUM_TYPE] : null; - - // When type is not given, and no choices, the type is the same as $default - if (!isset ($type)) { - if (isset ($default)) - $type = gettype($default); - else - $type = 'NULL'; // allow everything - } - } - - if ($type == 'boolean') { - if (isset ($default) && $default !== false) { - // Having a default value of anything other than 'false' is pointless - ApiBase :: dieDebug("Boolean param $paramName's default is set to '$default'"); - } - - $value = $wgRequest->getCheck($paramName); - } else - $value = $wgRequest->getVal($paramName, $default); - - if (isset ($value) && ($multi || is_array($type))) - $value = $this->parseMultiValue($paramName, $value, $multi, is_array($type) ? $type : null); - - // More validation only when choices were not given - // choices were validated in parseMultiValue() - if (!is_array($type) && isset ($value)) { - - switch ($type) { - case 'NULL' : // nothing to do - break; - case 'string' : // nothing to do - break; - case 'integer' : // Force everything using intval() - $value = is_array($value) ? array_map('intval', $value) : intval($value); - break; - case 'limit' : - if (!isset ($paramSettings[GN_ENUM_MAX1]) || !isset ($paramSettings[GN_ENUM_MAX2])) - ApiBase :: dieDebug("MAX1 or MAX2 are not defined for the limit $paramName"); - if ($multi) - ApiBase :: dieDebug("Multi-values not supported for $paramName"); - $min = isset ($paramSettings[GN_ENUM_MIN]) ? $paramSettings[GN_ENUM_MIN] : 0; - $value = intval($value); - $this->validateLimit($paramName, $value, $min, $paramSettings[GN_ENUM_MAX1], $paramSettings[GN_ENUM_MAX2]); - break; - case 'boolean' : - if ($multi) - ApiBase :: dieDebug("Multi-values not supported for $paramName"); - break; - case 'timestamp' : - if ($multi) - ApiBase :: dieDebug("Multi-values not supported for $paramName"); - $value = $this->prepareTimestamp($value); // Adds quotes around timestamp - break; - default : - ApiBase :: dieDebug("Param $paramName's type is unknown - $type"); - - } - } - - return $value; - } - - /** - * Return an array of values that were given in a 'a|b|c' notation, - * after it optionally validates them against the list allowed values. - * - * @param valueName - The name of the parameter (for error reporting) - * @param value - The value being parsed - * @param allowMultiple - Can $value contain more than one value separated by '|'? - * @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) { - $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"); - } - 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"); - } - } - - return $allowMultiple ? $valuesList : $valuesList[0]; - } - - /** - * Validate the proper format of the timestamp string (14 digits), and add quotes to it. - */ - function prepareTimestamp($value) { - if (preg_match('/^[0-9]{14}$/', $value)) { - return $this->db->addQuotes($value); - } else { - $this->dieUsage('Incorrect timestamp format', 'badtimestamp'); - } - } - - /** - * Validate the value against the minimum and user/bot maximum limits. Prints usage info on failure. - */ - 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 ($value > $botMax) { - $this->dieUsage("$varname may not be over $botMax (set to $value) for bots", $varname); - } - } else { - if ($value > $max) { - $this->dieUsage("$varname may not be over $max (set to $value) for users", $varname); - } - } - } - - /** - * Call main module's error handler - */ - public function dieUsage($description, $errorCode, $httpRespCode = 0) { - $this->getMain()->mainDieUsage($description, $errorCode, $httpRespCode); - } - - /** - * Internal code errors should be reported with this method - */ - protected static function dieDebug($message) { - wfDebugDieBacktrace("Internal error: $message"); - } - - /** - * Profiling: total module execution time - */ - private $mTimeIn = 0, $mModuleTime = 0; - - /** - * Start module profiling - */ - public function profileIn() { - if ($this->mTimeIn !== 0) - ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileOut()'); - $this->mTimeIn = microtime(true); - } - - /** - * End module profiling - */ - public function profileOut() { - if ($this->mTimeIn === 0) - ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileIn() first'); - if ($this->mDBTimeIn !== 0) - ApiBase :: 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) - ApiBase :: 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) - ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()'); - if ($this->mDBTimeIn !== 0) - ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()'); - $this->mDBTimeIn = microtime(true); - } - - /** - * End database profiling - */ - public function profileDBOut() { - if ($this->mTimeIn === 0) - ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()'); - if ($this->mDBTimeIn === 0) - ApiBase :: 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) - ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first'); - return $this->mDBTime; - } -} + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +abstract class ApiBase { + + // These constants allow modules to specify exactly how to treat incomming parameters. + + const PARAM_DFLT = 0; + const PARAM_ISMULTI = 1; + const PARAM_TYPE = 2; + const PARAM_MAX1 = 3; + const PARAM_MAX2 = 4; + const PARAM_MIN = 5; + + private $mMainModule; + + /** + * Constructor + */ + public function __construct($mainModule) { + $this->mMainModule = $mainModule; + } + + /** + * Executes this module + */ + abstract function execute(); + + /** + * Get main module + */ + 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() { + return $this === $this->mMainModule; + } + + /** + * Get result object + */ + public function getResult() { + // Main module has getResult() method overriden + // Safety - avoid infinite loop: + if ($this->isMain()) + ApiBase :: dieDebug(__METHOD__ . + ' base method was called on main module. '); + return $this->getMain()->getResult(); + } + + /** + * Get the result data array + */ + public function & getResultData() { + return $this->getResult()->getData(); + } + + /** + * Generates help message for this module, or false if there is no description + */ + public function makeHelpMsg() { + + static $lnPrfx = "\n "; + + $msg = $this->getDescription(); + + if ($msg !== false) { + + if (!is_array($msg)) + $msg = array ( + $msg + ); + $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n"; + + // Parameters + $paramsMsg = $this->makeHelpMsgParameters(); + if ($paramsMsg !== false) { + $msg .= "Parameters:\n$paramsMsg"; + } + + // Examples + $examples = $this->getExamples(); + if ($examples !== false) { + if (!is_array($examples)) + $examples = array ( + $examples + ); + $msg .= 'Example' . (count($examples) > 1 ? 's' : '') . ":\n "; + $msg .= implode($lnPrfx, $examples) . "\n"; + } + } + + return $msg; + } + + public function makeHelpMsgParameters() { + $params = $this->getAllowedParams(); + if ($params !== false) { + + $paramsDescription = $this->getParamDescription(); + $msg = ''; + foreach (array_keys($params) as $paramName) { + $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : ''; + if (is_array($desc)) + $desc = implode("\n" . str_repeat(' ', 19), $desc); + $msg .= sprintf(" %-14s - %s\n", $paramName, $desc); + } + return $msg; + + } else + return false; + } + + /** + * Returns the description string for this module + */ + protected function getDescription() { + return false; + } + + /** + * Returns usage examples for this module. Return null if no examples are available. + */ + protected function getExamples() { + return false; + } + + /** + * Returns an array of allowed parameters (keys) => default value for that parameter + */ + protected function getAllowedParams() { + return false; + } + + /** + * Returns the description string for the given parameter. + */ + protected function getParamDescription() { + return false; + } + + /** + * 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() { + $params = $this->getAllowedParams(); + $results = array (); + + foreach ($params as $paramName => $paramSettings) + $results[$paramName] = $this->getParameter($paramName, $paramSettings); + + return $results; + } + + public function getParameter($paramName, $paramSettings) { + global $wgRequest; + + if (!is_array($paramSettings)) { + $default = $paramSettings; + $multi = false; + $type = gettype($paramSettings); + } else { + $default = isset ($paramSettings[self::PARAM_DFLT]) ? $paramSettings[self::PARAM_DFLT] : null; + $multi = isset ($paramSettings[self::PARAM_ISMULTI]) ? $paramSettings[self::PARAM_ISMULTI] : false; + $type = isset ($paramSettings[self::PARAM_TYPE]) ? $paramSettings[self::PARAM_TYPE] : null; + + // When type is not given, and no choices, the type is the same as $default + if (!isset ($type)) { + if (isset ($default)) + $type = gettype($default); + else + $type = 'NULL'; // allow everything + } + } + + if ($type == 'boolean') { + if (isset ($default) && $default !== false) { + // Having a default value of anything other than 'false' is pointless + ApiBase :: dieDebug("Boolean param $paramName's default is set to '$default'"); + } + + $value = $wgRequest->getCheck($paramName); + } else + $value = $wgRequest->getVal($paramName, $default); + + if (isset ($value) && ($multi || is_array($type))) + $value = $this->parseMultiValue($paramName, $value, $multi, is_array($type) ? $type : null); + + // More validation only when choices were not given + // choices were validated in parseMultiValue() + if (!is_array($type) && isset ($value)) { + + switch ($type) { + case 'NULL' : // nothing to do + break; + case 'string' : // nothing to do + break; + case 'integer' : // Force everything using intval() + $value = is_array($value) ? array_map('intval', $value) : intval($value); + break; + case 'limit' : + if (!isset ($paramSettings[self::PARAM_MAX1]) || !isset ($paramSettings[self::PARAM_MAX2])) + ApiBase :: dieDebug("MAX1 or MAX2 are not defined for the limit $paramName"); + if ($multi) + ApiBase :: dieDebug("Multi-values not supported for $paramName"); + $min = isset ($paramSettings[self::PARAM_MIN]) ? $paramSettings[self::PARAM_MIN] : 0; + $value = intval($value); + $this->validateLimit($paramName, $value, $min, $paramSettings[self::PARAM_MAX1], $paramSettings[self::PARAM_MAX2]); + break; + case 'boolean' : + if ($multi) + ApiBase :: dieDebug("Multi-values not supported for $paramName"); + break; + case 'timestamp' : + if ($multi) + ApiBase :: dieDebug("Multi-values not supported for $paramName"); + $value = $this->prepareTimestamp($value); // Adds quotes around timestamp + break; + default : + ApiBase :: dieDebug("Param $paramName's type is unknown - $type"); + + } + } + + return $value; + } + + /** + * Return an array of values that were given in a 'a|b|c' notation, + * after it optionally validates them against the list allowed values. + * + * @param valueName - The name of the parameter (for error reporting) + * @param value - The value being parsed + * @param allowMultiple - Can $value contain more than one value separated by '|'? + * @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) { + $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"); + } + 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"); + } + } + + return $allowMultiple ? $valuesList : $valuesList[0]; + } + + /** + * Validate the proper format of the timestamp string (14 digits), and add quotes to it. + */ + function prepareTimestamp($value) { + if (preg_match('/^[0-9]{14}$/', $value)) { + return $this->db->addQuotes($value); + } else { + $this->dieUsage('Incorrect timestamp format', 'badtimestamp'); + } + } + + /** + * Validate the value against the minimum and user/bot maximum limits. Prints usage info on failure. + */ + 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 ($value > $botMax) { + $this->dieUsage("$varname may not be over $botMax (set to $value) for bots", $varname); + } + } else { + if ($value > $max) { + $this->dieUsage("$varname may not be over $max (set to $value) for users", $varname); + } + } + } + + /** + * Call main module's error handler + */ + public function dieUsage($description, $errorCode, $httpRespCode = 0) { + $this->getMain()->mainDieUsage($description, $errorCode, $httpRespCode); + } + + /** + * Internal code errors should be reported with this method + */ + protected static function dieDebug($message) { + wfDebugDieBacktrace("Internal error: $message"); + } + + /** + * Profiling: total module execution time + */ + private $mTimeIn = 0, $mModuleTime = 0; + + /** + * Start module profiling + */ + public function profileIn() { + if ($this->mTimeIn !== 0) + ApiBase :: dieDebug(__METHOD__ . ' called twice without calling profileOut()'); + $this->mTimeIn = microtime(true); + } + + /** + * End module profiling + */ + public function profileOut() { + if ($this->mTimeIn === 0) + ApiBase :: dieDebug(__METHOD__ . ' called without calling profileIn() first'); + if ($this->mDBTimeIn !== 0) + ApiBase :: dieDebug(__METHOD__ . ' 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) + ApiBase :: dieDebug(__METHOD__ . ' 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) + ApiBase :: dieDebug(__METHOD__ . ' must be called while profiling the entire module with profileIn()'); + if ($this->mDBTimeIn !== 0) + ApiBase :: dieDebug(__METHOD__ . ' called twice without calling profileDBOut()'); + $this->mDBTimeIn = microtime(true); + } + + /** + * End database profiling + */ + public function profileDBOut() { + if ($this->mTimeIn === 0) + ApiBase :: dieDebug(__METHOD__ . ' must be called while profiling the entire module with profileIn()'); + if ($this->mDBTimeIn === 0) + ApiBase :: dieDebug(__METHOD__ . ' 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) + ApiBase :: dieDebug(__METHOD__ . ' called without calling profileDBOut() first'); + return $this->mDBTime; + } +} ?> \ No newline at end of file diff --git a/includes/api/ApiLogin.php b/includes/api/ApiLogin.php index 5158c35ec1..b01691f708 100644 --- a/includes/api/ApiLogin.php +++ b/includes/api/ApiLogin.php @@ -50,30 +50,35 @@ class ApiLogin extends ApiBase { $loginForm = new LoginForm($params); switch ($loginForm->authenticateUserData()) { - case (AuthSuccess) : + case LoginForm :: SUCCESS : + global $wgUser; + + $wgUser->setOption('rememberpassword', 1); + $wgUser->setCookies(); + $result['result'] = 'Success'; $result['lguserid'] = $_SESSION['wsUserID']; $result['lgusername'] = $_SESSION['wsUserName']; $result['lgtoken'] = $_SESSION['wsToken']; break; - case (AuthNoName) : - $result['result'] = 'AuthNoName'; + case LoginForm :: NO_NAME : + $result['result'] = 'NoName'; break; - case (AuthIllegal) : - $result['result'] = 'AuthIllegal'; + case LoginForm :: ILLEGAL : + $result['result'] = 'Illegal'; break; - case (AuthWrongPluginPass) : - $result['result'] = 'AuthWrongPluginPass'; + case LoginForm :: WRONG_PLUGIN_PASS : + $result['result'] = 'WrongPluginPass'; break; - case (AuthNotExists) : - $result['result'] = 'AuthNotExists'; + case LoginForm :: NOT_EXISTS : + $result['result'] = 'NotExists'; break; - case (AuthWrongPass) : - $result['result'] = 'AuthWrongPass'; + case LoginForm :: WRONG_PASS : + $result['result'] = 'WrongPass'; break; - case (AuthEmptyPass) : - $result['result'] = 'AuthEmptyPass'; + case LoginForm :: EMPTY_PASS : + $result['result'] = 'EmptyPass'; break; default : $this->dieDebug('Unhandled case value'); diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index f831fb5a8b..60e0ff09e8 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -1,197 +1,197 @@ - - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * http://www.gnu.org/copyleft/gpl.html - */ - -if (!defined('MEDIAWIKI')) { - // Eclipse helper - will be ignored in production - require_once ('ApiBase.php'); -} - -class ApiMain extends ApiBase { - - private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames, $mApiStartTime, $mResult; - - /** - * Constructor - * $apiStartTime - time of the originating call for profiling purposes - * $modules - an array of actions (keys) and classes that handle them (values) - */ - public function __construct($apiStartTime, $modules, $formats) { - // Special handling for the main module: $parent === $this - parent :: __construct($this); - - $this->mModules = $modules; - $this->mModuleNames = array_keys($modules); - $this->mFormats = $formats; - $this->mFormatNames = array_keys($formats); - $this->mApiStartTime = $apiStartTime; - $this->mResult = new ApiResult($this); - } - - public function & getResult() { - return $this->mResult; - } - - protected function getAllowedParams() { - return array ( - 'format' => array ( - GN_ENUM_DFLT => API_DEFAULT_FORMAT, - GN_ENUM_TYPE => $this->mFormatNames - ), - 'action' => array ( - GN_ENUM_DFLT => 'help', - GN_ENUM_TYPE => $this->mModuleNames - ) - ); - } - - protected function getParamDescription() { - return array ( - 'format' => 'The format of the output', - 'action' => 'What action you would like to perform' - ); - } - - public function execute() { - $this->profileIn(); - $action = $format = null; - try { - 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->profileIn(); - $module->execute(); - $module->profileOut(); - $this->printResult(false); - } catch (UsageException $e) { - // 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->profileOut(); - } - - /** - * Internal printer - */ - 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() { - 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) { - $this->mResult->Reset(); - if ($httpRespCode === 0) - header($errorCode, true); - else - header($errorCode, true, $httpRespCode); - - $data = array ( - 'code' => $errorCode - ); - ApiResult :: addContent($data, $this->makeHelpMsg()); - $this->mResult->addValue(null, 'error', $data); - - throw new UsageException($description, $errorCode); - } - - /** - * 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(); - - $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; - $msg .= "\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; - $msg .= "\n"; - } - - return $msg; - } - - private $mIsBot = null; - public function isBot() { - if (!isset ($this->mIsBot)) { - global $wgUser; - $this->mIsBot = $wgUser->isAllowed('bot'); - } - 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}"; - } -} + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiBase.php'); +} + +class ApiMain extends ApiBase { + + private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames, $mApiStartTime, $mResult; + + /** + * Constructor + * $apiStartTime - time of the originating call for profiling purposes + * $modules - an array of actions (keys) and classes that handle them (values) + */ + public function __construct($apiStartTime, $modules, $formats) { + // Special handling for the main module: $parent === $this + parent :: __construct($this); + + $this->mModules = $modules; + $this->mModuleNames = array_keys($modules); + $this->mFormats = $formats; + $this->mFormatNames = array_keys($formats); + $this->mApiStartTime = $apiStartTime; + $this->mResult = new ApiResult($this); + } + + public function & getResult() { + return $this->mResult; + } + + protected function getAllowedParams() { + return array ( + 'format' => array ( + ApiBase::PARAM_DFLT => API_DEFAULT_FORMAT, + ApiBase::PARAM_TYPE => $this->mFormatNames + ), + 'action' => array ( + ApiBase::PARAM_DFLT => 'help', + ApiBase::PARAM_TYPE => $this->mModuleNames + ) + ); + } + + protected function getParamDescription() { + return array ( + 'format' => 'The format of the output', + 'action' => 'What action you would like to perform' + ); + } + + public function execute() { + $this->profileIn(); + $action = $format = null; + try { + 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->profileIn(); + $module->execute(); + $module->profileOut(); + $this->printResult(false); + } catch (UsageException $e) { + // 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->profileOut(); + } + + /** + * Internal printer + */ + 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() { + 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) { + $this->mResult->Reset(); + if ($httpRespCode === 0) + header($errorCode, true); + else + header($errorCode, true, $httpRespCode); + + $data = array ( + 'code' => $errorCode + ); + ApiResult :: addContent($data, $this->makeHelpMsg()); + $this->mResult->addValue(null, 'error', $data); + + throw new UsageException($description, $errorCode); + } + + /** + * 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(); + + $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; + $msg .= "\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; + $msg .= "\n"; + } + + return $msg; + } + + private $mIsBot = null; + public function isBot() { + if (!isset ($this->mIsBot)) { + global $wgUser; + $this->mIsBot = $wgUser->isAllowed('bot'); + } + 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 f859d12889..1343c1ee4f 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -34,6 +34,8 @@ class ApiPageSet extends ApiQueryBase { private $mAllPages; // [ns][dbkey] => page_id or 0 when missing private $mGoodTitles, $mMissingTitles, $mRedirectTitles, $mNormalizedTitles; + private $mRequestedFields; + public function __construct($query) { parent :: __construct($query, __CLASS__); @@ -42,6 +44,12 @@ class ApiPageSet extends ApiQueryBase { $this->mMissingTitles = array (); $this->mRedirectTitles = array (); $this->mNormalizedTitles = array (); + + $this->mRequestedFields = array (); + } + + public function requestField($fieldName) { + $this->mRequestedFields[$fieldName] = null; } /** @@ -88,7 +96,7 @@ class ApiPageSet extends ApiQueryBase { * Get the list of revision IDs (requested with revids= parameter) */ public function getRevisionIDs() { - $this->dieUsage(__FUNCTION__ . ' is not implemented', 'notimplemented'); + $this->dieUsage(__METHOD__ . ' is not implemented', 'notimplemented'); } /** @@ -114,14 +122,20 @@ class ApiPageSet extends ApiQueryBase { */ private function populateTitles($titles, $redirects) { + // Ensure we get minimum required fields $pageFlds = array ( - 'page_id', - 'page_namespace', - 'page_title' + 'page_id' => null, + 'page_namespace' => null, + 'page_title' => null ); - if ($redirects) { - $pageFlds[] = 'page_is_redirect'; - } + + // only store non-default fields + $this->mRequestedFields = array_diff_key($this->mRequestedFields, $pageFlds); + + if ($redirects) + $pageFlds['page_is_redirect'] = null; + + $pageFlds = array_keys(array_merge($this->mRequestedFields, $pageFlds)); // Get validated and normalized title objects $linkBatch = $this->processTitlesStrArray($titles); @@ -142,7 +156,7 @@ class ApiPageSet extends ApiQueryBase { // Get data about $linkBatch from `page` table // $this->profileDBIn(); - $res = $db->select('page', $pageFlds, $set, __CLASS__ . '::' . __FUNCTION__); + $res = $db->select('page', $pageFlds, $set, __METHOD__); $this->profileDBOut(); while ($row = $db->fetchObject($res)) { @@ -186,7 +200,7 @@ class ApiPageSet extends ApiQueryBase { 'pl_title' ), array ( 'pl_from' => array_keys($redirectIds - )), __CLASS__ . '::' . __FUNCTION__); + )), __METHOD__); $this->profileDBOut(); while ($row = $db->fetchObject($res)) { @@ -249,7 +263,7 @@ class ApiPageSet extends ApiQueryBase { } private function populatePageIDs($pageids) { - $this->dieUsage(__FUNCTION__ . ' is not implemented', 'notimplemented'); + $this->dieUsage(__METHOD__ . ' is not implemented', 'notimplemented'); } public function execute() { @@ -290,15 +304,15 @@ class ApiPageSet extends ApiQueryBase { protected function getAllowedParams() { return array ( 'titles' => array ( - GN_ENUM_ISMULTI => true + ApiBase::PARAM_ISMULTI => true ), 'pageids' => array ( - GN_ENUM_TYPE => 'integer', - GN_ENUM_ISMULTI => true + ApiBase::PARAM_TYPE => 'integer', + ApiBase::PARAM_ISMULTI => true ), 'revids' => array ( - GN_ENUM_TYPE => 'integer', - GN_ENUM_ISMULTI => true + ApiBase::PARAM_TYPE => 'integer', + ApiBase::PARAM_ISMULTI => true ), 'redirects' => false ); diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index fe7dd82f78..458007b8cd 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -1,286 +1,295 @@ - - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * http://www.gnu.org/copyleft/gpl.html - */ - -if (!defined('MEDIAWIKI')) { - // Eclipse helper - will be ignored in production - require_once ('ApiBase.php'); -} - -class ApiQuery extends ApiBase { - - private $mMetaModuleNames, $mPropModuleNames, $mListModuleNames; - private $mData; - - private $mQueryMetaModules = array ( - 'siteinfo' => 'ApiQuerySiteinfo' - ); - // 'userinfo' => 'ApiQueryUserinfo', - - private $mQueryPropModules = array ( - 'info' => 'ApiQueryInfo', - 'revisions' => 'ApiQueryRevisions' - ); - // 'categories' => 'ApiQueryCategories', - // 'imageinfo' => 'ApiQueryImageinfo', - // 'langlinks' => 'ApiQueryLanglinks', - // 'links' => 'ApiQueryLinks', - // 'templates' => 'ApiQueryTemplates', - - private $mQueryListModules = array ( - 'allpages' => 'ApiQueryAllpages' - ); - // 'backlinks' => 'ApiQueryBacklinks', - // 'categorymembers' => 'ApiQueryCategorymembers', - // 'embeddedin' => 'ApiQueryEmbeddedin', - // 'imagelinks' => 'ApiQueryImagelinks', - // 'logevents' => 'ApiQueryLogevents', - // 'recentchanges' => 'ApiQueryRecentchanges', - // 'usercontribs' => 'ApiQueryUsercontribs', - // 'users' => 'ApiQueryUsers', - // 'watchlist' => 'ApiQueryWatchlist', - - private $mSlaveDB = null; - - 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); - - // Allow the entire list of modules at first, - // but during module instantiation check if it can be used as a generator. - $this->mAllowedGenerators = array_merge($this->mListModuleNames, $this->mPropModuleNames); - } - - public function getDB() { - if (!isset ($this->mSlaveDB)) - $this->mSlaveDB = & wfGetDB(DB_SLAVE); - return $this->mSlaveDB; - } - - public function getData() { - return $this->mData; - } - - /** - * Query execution happens in the following steps: - * #1 Create a PageSet object with any pages requested by the user - * #2 If using generator, execute it to get a new PageSet object - * #3 Instantiate all requested modules. - * This way the PageSet object will know what shared data is required, - * and minimize DB calls. - * #4 Output all normalization and redirect resolution information - * #5 Execute all requested modules - */ - public function execute() { - $meta = $prop = $list = $generator = null; - extract($this->extractRequestParams()); - - // - // Create and initialize PageSet - // - $this->mData = new ApiPageSet($this); - $this->mData->profileIn(); - $this->mData->execute(); - $this->mData->profileOut(); - - // - // If generator is provided, get a new dataset to work on - // - if (isset ($generator)) - $this->executeGenerator($generator); - - // Instantiate required modules - // During instantiation, modules may optimize data requests through the $this->mData object - // $this->mData will be lazy loaded when modules begin to request data during execution - $modules = array (); - if (isset ($meta)) - foreach ($meta as $moduleName) - $modules[] = new $this->mQueryMetaModules[$moduleName] ($this, $moduleName); - if (isset ($prop)) - foreach ($prop as $moduleName) - $modules[] = new $this->mQueryPropModules[$moduleName] ($this, $moduleName); - if (isset ($list)) - foreach ($list as $moduleName) - $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName); - - // Title normalizations - $normValues = array (); - foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) { - $normValues[] = array ( - 'from' => $rawTitleStr, - 'to' => $titleStr - ); - } - - if (!empty ($normValues)) { - ApiResult :: setIndexedTagName($normValues, 'n'); - $this->getResult()->addValue('query', 'normalized', $normValues); - } - - // Show redirect information - $redirValues = array (); - foreach ($this->mData->getRedirectTitles() as $titleStrFrom => $titleStrTo) { - $redirValues[] = array ( - 'from' => $titleStrFrom, - 'to' => $titleStrTo - ); - } - - if (!empty ($redirValues)) { - ApiResult :: setIndexedTagName($redirValues, 'r'); - $this->getResult()->addValue('query', 'redirects', $redirValues); - } - - // Execute all requested modules. - foreach ($modules as $module) { - $module->profileIn(); - $module->execute(); - $module->profileOut(); - } - - // Ensure that pages are shown as '' elements - $data = & $this->getResultData(); - if (isset ($data['query']['pages'])) { - ApiResult :: setIndexedTagName($data['query']['pages'], 'page'); - } - } - - protected function executeGenerator($generator) { - - // Find class that implements requested generator - if (isset ($this->mQueryListModules[$generator])) - $className = $this->mQueryListModules[$generator]; - else - if (isset ($this->mQueryPropModules[$generator])) - $className = $this->mQueryPropModules[$generator]; - else - ApiBase :: dieDebug("Unknown generator=$generator"); - - $module = new $className ($this, $generator, true); - - // change $this->mData - - // TODO: implement - $this->dieUsage('Generator execution has not been implemented', 'notimplemented'); - } - - protected function getAllowedParams() { - return array ( - 'meta' => array ( - GN_ENUM_ISMULTI => true, - GN_ENUM_TYPE => $this->mMetaModuleNames - ), - 'prop' => array ( - GN_ENUM_ISMULTI => true, - GN_ENUM_TYPE => $this->mPropModuleNames - ), - 'list' => array ( - GN_ENUM_ISMULTI => true, - GN_ENUM_TYPE => $this->mListModuleNames - ) - // 'generator' => array ( - // GN_ENUM_TYPE => $this->mAllowedGenerators - // ), - - - ); - } - - /** - * Override the parent to generate help messages for all available query modules. - */ - public function makeHelpMsg() { - - // Use parent to make default message for the query module - $msg = parent :: makeHelpMsg(); - - // Make sure the internal object is empty - // (just in case a sub-module decides to optimize during instantiation) - $this->mData = null; - - $astriks = str_repeat('--- ', 8); - $msg .= "\n$astriks Query: Meta $astriks\n\n"; - $msg .= $this->makeHelpMsgHelper($this->mQueryMetaModules, 'meta'); - $msg .= "\n$astriks Query: Prop $astriks\n\n"; - $msg .= $this->makeHelpMsgHelper($this->mQueryPropModules, 'prop'); - $msg .= "\n$astriks Query: List $astriks\n\n"; - $msg .= $this->makeHelpMsgHelper($this->mQueryListModules, 'list'); - - return $msg; - } - - private function makeHelpMsgHelper($moduleList, $paramName) { - $msg = ''; - - foreach ($moduleList as $moduleName => $moduleClass) { - $msg .= "* $paramName=$moduleName *"; - $module = new $moduleClass ($this, $moduleName, null); - $msg2 = $module->makeHelpMsg(); - if ($msg2 !== false) - $msg .= $msg2; - $msg .= "\n"; - if ($module->getCanGenerate()) - $msg .= " * Can be used as a generator\n"; - } - - return $msg; - } - - /** - * Override to add extra parameters from PageSet - */ - public function makeHelpMsgParameters() { - $module = new ApiPageSet($this); - return $module->makeHelpMsgParameters() . parent :: makeHelpMsgParameters(); - } - - 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', - - - ); - } - - 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.', - 'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites.' - ); - } - - protected function getExamples() { - return array ( - 'api.php?action=query&what=content&titles=ArticleA|ArticleB' - ); - } -} -?> + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiBase.php'); +} + +class ApiQuery extends ApiBase { + + private $mMetaModuleNames, $mPropModuleNames, $mListModuleNames; + private $mData; + + private $mQueryMetaModules = array ( + 'siteinfo' => 'ApiQuerySiteinfo' + ); + // 'userinfo' => 'ApiQueryUserinfo', + + private $mQueryPropModules = array ( + 'info' => 'ApiQueryInfo', + 'revisions' => 'ApiQueryRevisions' + ); + // 'categories' => 'ApiQueryCategories', + // 'imageinfo' => 'ApiQueryImageinfo', + // 'langlinks' => 'ApiQueryLanglinks', + // 'links' => 'ApiQueryLinks', + // 'templates' => 'ApiQueryTemplates', + + private $mQueryListModules = array ( + 'allpages' => 'ApiQueryAllpages' + ); + // 'backlinks' => 'ApiQueryBacklinks', + // 'categorymembers' => 'ApiQueryCategorymembers', + // 'embeddedin' => 'ApiQueryEmbeddedin', + // 'imagelinks' => 'ApiQueryImagelinks', + // 'logevents' => 'ApiQueryLogevents', + // 'recentchanges' => 'ApiQueryRecentchanges', + // 'usercontribs' => 'ApiQueryUsercontribs', + // 'users' => 'ApiQueryUsers', + // 'watchlist' => 'ApiQueryWatchlist', + + private $mSlaveDB = null; + + 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); + + // Allow the entire list of modules at first, + // but during module instantiation check if it can be used as a generator. + $this->mAllowedGenerators = array_merge($this->mListModuleNames, $this->mPropModuleNames); + } + + public function getDB() { + if (!isset ($this->mSlaveDB)) + $this->mSlaveDB = & wfGetDB(DB_SLAVE); + return $this->mSlaveDB; + } + + public function getData() { + return $this->mData; + } + + /** + * Query execution happens in the following steps: + * #1 Create a PageSet object with any pages requested by the user + * #2 If using generator, execute it to get a new PageSet object + * #3 Instantiate all requested modules. + * This way the PageSet object will know what shared data is required, + * and minimize DB calls. + * #4 Output all normalization and redirect resolution information + * #5 Execute all requested modules + */ + public function execute() { + $meta = $prop = $list = $generator = null; + extract($this->extractRequestParams()); + + // + // Create PageSet + // + $this->mData = new ApiPageSet($this); + + // + // If generator is provided, get a new dataset to work on + // + if (isset ($generator)) + $this->executeGenerator($generator); + + // Instantiate required modules + // During instantiation, modules may optimize data requests through the $this->mData object + // $this->mData will be lazy loaded when modules begin to request data during execution + $modules = array (); + if (isset ($meta)) + foreach ($meta as $moduleName) + $modules[] = new $this->mQueryMetaModules[$moduleName] ($this, $moduleName); + if (isset ($prop)) + foreach ($prop as $moduleName) + $modules[] = new $this->mQueryPropModules[$moduleName] ($this, $moduleName); + if (isset ($list)) + foreach ($list as $moduleName) + $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName); + + // + // Get page information for the given pageSet + // + $this->mData->profileIn(); + $this->mData->execute(); + $this->mData->profileOut(); + + // Title normalizations + $normValues = array (); + foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) { + $normValues[] = array ( + 'from' => $rawTitleStr, + 'to' => $titleStr + ); + } + + if (!empty ($normValues)) { + ApiResult :: setIndexedTagName($normValues, 'n'); + $this->getResult()->addValue('query', 'normalized', $normValues); + } + + // Show redirect information + $redirValues = array (); + foreach ($this->mData->getRedirectTitles() as $titleStrFrom => $titleStrTo) { + $redirValues[] = array ( + 'from' => $titleStrFrom, + 'to' => $titleStrTo + ); + } + + if (!empty ($redirValues)) { + ApiResult :: setIndexedTagName($redirValues, 'r'); + $this->getResult()->addValue('query', 'redirects', $redirValues); + } + + // Execute all requested modules. + foreach ($modules as $module) { + $module->profileIn(); + $module->execute(); + $module->profileOut(); + } + + // Ensure that pages are shown as '' elements + $data = & $this->getResultData(); + if (isset ($data['query']['pages'])) { + ApiResult :: setIndexedTagName($data['query']['pages'], 'page'); + } + } + + protected function executeGenerator($generator) { + + // Find class that implements requested generator + if (isset ($this->mQueryListModules[$generator])) + $className = $this->mQueryListModules[$generator]; + else + if (isset ($this->mQueryPropModules[$generator])) + $className = $this->mQueryPropModules[$generator]; + else + ApiBase :: dieDebug("Unknown generator=$generator"); + + $module = new $className ($this, $generator, true); + + // execute pageSet here to get the data required by the generator module + $this->mData->profileIn(); + $this->mData->execute(); + $this->mData->profileOut(); + + // change $this->mData + + // TODO: implement + $this->dieUsage('Generator execution has not been implemented', 'notimplemented'); + } + + protected function getAllowedParams() { + return array ( + 'meta' => array ( + ApiBase::PARAM_ISMULTI => true, + ApiBase::PARAM_TYPE => $this->mMetaModuleNames + ), + 'prop' => array ( + ApiBase::PARAM_ISMULTI => true, + ApiBase::PARAM_TYPE => $this->mPropModuleNames + ), + 'list' => array ( + ApiBase::PARAM_ISMULTI => true, + ApiBase::PARAM_TYPE => $this->mListModuleNames + ) + // 'generator' => array ( + // ApiBase::PARAM_TYPE => $this->mAllowedGenerators + // ), + + + ); + } + + /** + * Override the parent to generate help messages for all available query modules. + */ + public function makeHelpMsg() { + + // Use parent to make default message for the query module + $msg = parent :: makeHelpMsg(); + + // Make sure the internal object is empty + // (just in case a sub-module decides to optimize during instantiation) + $this->mData = null; + + $astriks = str_repeat('--- ', 8); + $msg .= "\n$astriks Query: Meta $astriks\n\n"; + $msg .= $this->makeHelpMsgHelper($this->mQueryMetaModules, 'meta'); + $msg .= "\n$astriks Query: Prop $astriks\n\n"; + $msg .= $this->makeHelpMsgHelper($this->mQueryPropModules, 'prop'); + $msg .= "\n$astriks Query: List $astriks\n\n"; + $msg .= $this->makeHelpMsgHelper($this->mQueryListModules, 'list'); + + return $msg; + } + + private function makeHelpMsgHelper($moduleList, $paramName) { + $msg = ''; + + foreach ($moduleList as $moduleName => $moduleClass) { + $msg .= "* $paramName=$moduleName *"; + $module = new $moduleClass ($this, $moduleName, null); + $msg2 = $module->makeHelpMsg(); + if ($msg2 !== false) + $msg .= $msg2; + $msg .= "\n"; + if ($module->getCanGenerate()) + $msg .= " * Can be used as a generator\n"; + } + + return $msg; + } + + /** + * Override to add extra parameters from PageSet + */ + public function makeHelpMsgParameters() { + $module = new ApiPageSet($this); + return $module->makeHelpMsgParameters() . parent :: makeHelpMsgParameters(); + } + + 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', + + + ); + } + + 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.', + 'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites.' + ); + } + + protected function getExamples() { + return array ( + 'api.php?action=query&prop=revisions&meta=siteinfo&titles=Main%20Page&rvprop=user|comment' + ); + } +} +?> diff --git a/includes/api/ApiQueryAllpages.php b/includes/api/ApiQueryAllpages.php index 5973250bfe..db7f9ef067 100644 --- a/includes/api/ApiQueryAllpages.php +++ b/includes/api/ApiQueryAllpages.php @@ -107,23 +107,23 @@ class ApiQueryAllpages extends ApiQueryBase { return array ( 'apfrom' => null, 'apnamespace' => array ( - GN_ENUM_DFLT => 0, - GN_ENUM_TYPE => $validNamespaces + ApiBase::PARAM_DFLT => 0, + ApiBase::PARAM_TYPE => $validNamespaces ), 'apfilterredir' => array ( - GN_ENUM_DFLT => 'all', - GN_ENUM_TYPE => array ( + ApiBase::PARAM_DFLT => 'all', + ApiBase::PARAM_TYPE => array ( 'all', 'redirects', 'nonredirects' ) ), 'aplimit' => array ( - GN_ENUM_DFLT => 10, - GN_ENUM_TYPE => 'limit', - GN_ENUM_MIN => 1, - GN_ENUM_MAX1 => 500, - GN_ENUM_MAX2 => 5000 + ApiBase::PARAM_DFLT => 10, + ApiBase::PARAM_TYPE => 'limit', + ApiBase::PARAM_MIN => 1, + ApiBase::PARAM_MAX1 => 500, + ApiBase::PARAM_MAX2 => 5000 ) ); } diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index 732ecf64df..dccad670e2 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -43,9 +43,9 @@ class ApiQueryInfo extends ApiQueryBase { return array ( 'param' => 'default', 'enumparam' => array ( - GN_ENUM_DFLT => 'default', - GN_ENUM_ISMULTI => false, - GN_ENUM_TYPE => array ( + ApiBase::PARAM_DFLT => 'default', + ApiBase::PARAM_ISMULTI => false, + ApiBase::PARAM_TYPE => array ( 'a', 'b' ) diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index f35075fd7a..e8e6efb4d8 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -175,7 +175,7 @@ class ApiQueryRevisions extends ApiQueryBase { $db = $this->getDB(); $this->profileDBIn(); - $res = $db->select($tables, $fields, $conds, __CLASS__ . '::' . __FUNCTION__, $options); + $res = $db->select($tables, $fields, $conds, __METHOD__, $options); $this->profileDBOut(); $data = array (); @@ -239,30 +239,30 @@ class ApiQueryRevisions extends ApiQueryBase { protected function getAllowedParams() { return array ( 'rvlimit' => array ( - GN_ENUM_DFLT => 0, - GN_ENUM_TYPE => 'limit', - GN_ENUM_MIN => 0, - GN_ENUM_MAX1 => 50, - GN_ENUM_MAX2 => 500 + ApiBase::PARAM_DFLT => 0, + ApiBase::PARAM_TYPE => 'limit', + ApiBase::PARAM_MIN => 0, + ApiBase::PARAM_MAX1 => 50, + ApiBase::PARAM_MAX2 => 500 ), 'rvstartid' => 0, 'rvendid' => 0, 'rvstart' => array ( - GN_ENUM_TYPE => 'timestamp' + ApiBase::PARAM_TYPE => 'timestamp' ), 'rvend' => array ( - GN_ENUM_TYPE => 'timestamp' + ApiBase::PARAM_TYPE => 'timestamp' ), 'rvdir' => array ( - GN_ENUM_DFLT => 'older', - GN_ENUM_TYPE => array ( + ApiBase::PARAM_DFLT => 'older', + ApiBase::PARAM_TYPE => array ( 'newer', 'older' ) ), 'rvprop' => array ( - GN_ENUM_ISMULTI => true, - GN_ENUM_TYPE => array ( + ApiBase::PARAM_ISMULTI => true, + ApiBase::PARAM_TYPE => array ( 'timestamp', 'user', 'comment', diff --git a/includes/api/ApiQuerySiteinfo.php b/includes/api/ApiQuerySiteinfo.php index 54d3a5cfb4..6bddee2a8f 100644 --- a/includes/api/ApiQuerySiteinfo.php +++ b/includes/api/ApiQuerySiteinfo.php @@ -78,9 +78,9 @@ class ApiQuerySiteinfo extends ApiQueryBase { protected function getAllowedParams() { return array ( 'siprop' => array ( - GN_ENUM_DFLT => 'general', - GN_ENUM_ISMULTI => true, - GN_ENUM_TYPE => array ( + ApiBase::PARAM_DFLT => 'general', + ApiBase::PARAM_ISMULTI => true, + ApiBase::PARAM_TYPE => array ( 'general', 'namespaces' ) diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php index d99b759417..3e65b57937 100644 --- a/includes/api/ApiResult.php +++ b/includes/api/ApiResult.php @@ -1,143 +1,143 @@ - - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * http://www.gnu.org/copyleft/gpl.html - */ - -if (!defined('MEDIAWIKI')) { - // Eclipse helper - will be ignored in production - require_once ('ApiBase.php'); -} - -class ApiResult extends ApiBase { - - private $mData; - - /** - * Constructor - */ - public function __construct($main) { - parent :: __construct($main); - $this->Reset(); - } - - public function Reset() { - $this->mData = array (); - } - - function & getData() { - return $this->mData; - } - - /** - * Add an output value to the array by name. - * Verifies that value with the same name has not been added before. - */ - public static function addElement(& $arr, $name, $value) { - if ($arr === null || $name === null || $value === null || !is_array($arr) || is_array($name)) - ApiBase :: dieDebug('Bad parameter for ' . __FUNCTION__); - if (isset ($arr[$name])) - ApiBase :: dieDebug("Attempting to add element $name=$value, existing value is {$arr[$name]}"); - $arr[$name] = $value; - } - - /** - * Adds the content element to the array. - * Use this function instead of hardcoding the '*' element. - */ - public static function addContent(& $arr, $value) { - if (is_array($value)) - ApiBase :: dieDebug('Bad parameter for ' . __FUNCTION__); - ApiResult :: addElement($arr, '*', $value); - } - - // public static function makeContentElement($tag, $value) { - // $result = array(); - // ApiResult::addContent($result, ) - // } - // - /** - * In case the array contains indexed values (in addition to named), - * all indexed values will have the given tag name. - */ - public static function setIndexedTagName(& $arr, $tag) { - // Do not use addElement() as it is ok to call this more than once - if ($arr === null || $tag === null || !is_array($arr) || is_array($tag)) - ApiBase :: dieDebug('Bad parameter for ' . __FUNCTION__); - $arr['_element'] = $tag; - } - - /** - * Add value to the output data at the given path. - * Path is an indexed array, each element specifing the branch at which to add the new value - * Setting $path to array('a','b','c') is equivalent to data['a']['b']['c'] = $value - */ - public function addValue($path, $name, $value) { - - $data = & $this->getData(); - - if (isset ($path)) { - if (is_array($path)) { - foreach ($path as $p) { - if (!isset ($data[$p])) - $data[$p] = array (); - $data = & $data[$p]; - } - } else { - if (!isset ($data[$path])) - $data[$path] = array (); - $data = & $data[$path]; - } - } - - ApiResult :: addElement($data, $name, $value); - } - - /** - * Recursivelly removes any elements from the array that begin with an '_'. - * The content element '*' is the only special element that is left. - * Use this method when the entire data object gets sent to the user. - */ - public function SanitizeData() { - ApiResult :: SanitizeDataInt($this->mData); - } - - private static function SanitizeDataInt(& $data) { - foreach ($data as $key => & $value) { - if ($key[0] === '_') { - unset ($data[$key]); - } - elseif ($key === '*' && $value === '') { - unset ($data[$key]); - } - elseif (is_array($value)) { - ApiResult :: SanitizeDataInt($value); - } - } - } - - public function execute() { - $this->dieDebug('execute() is not supported on Result object'); - } -} -?> + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiBase.php'); +} + +class ApiResult extends ApiBase { + + private $mData; + + /** + * Constructor + */ + public function __construct($main) { + parent :: __construct($main); + $this->Reset(); + } + + public function Reset() { + $this->mData = array (); + } + + function & getData() { + return $this->mData; + } + + /** + * Add an output value to the array by name. + * Verifies that value with the same name has not been added before. + */ + public static function addElement(& $arr, $name, $value) { + if ($arr === null || $name === null || $value === null || !is_array($arr) || is_array($name)) + ApiBase :: dieDebug('Bad parameter for ' . __METHOD__); + if (isset ($arr[$name])) + ApiBase :: dieDebug("Attempting to add element $name=$value, existing value is {$arr[$name]}"); + $arr[$name] = $value; + } + + /** + * Adds the content element to the array. + * Use this function instead of hardcoding the '*' element. + */ + public static function addContent(& $arr, $value) { + if (is_array($value)) + ApiBase :: dieDebug('Bad parameter for ' . __METHOD__); + ApiResult :: addElement($arr, '*', $value); + } + + // public static function makeContentElement($tag, $value) { + // $result = array(); + // ApiResult::addContent($result, ) + // } + // + /** + * In case the array contains indexed values (in addition to named), + * all indexed values will have the given tag name. + */ + public static function setIndexedTagName(& $arr, $tag) { + // Do not use addElement() as it is ok to call this more than once + if ($arr === null || $tag === null || !is_array($arr) || is_array($tag)) + ApiBase :: dieDebug('Bad parameter for ' . __METHOD__); + $arr['_element'] = $tag; + } + + /** + * Add value to the output data at the given path. + * Path is an indexed array, each element specifing the branch at which to add the new value + * Setting $path to array('a','b','c') is equivalent to data['a']['b']['c'] = $value + */ + public function addValue($path, $name, $value) { + + $data = & $this->getData(); + + if (isset ($path)) { + if (is_array($path)) { + foreach ($path as $p) { + if (!isset ($data[$p])) + $data[$p] = array (); + $data = & $data[$p]; + } + } else { + if (!isset ($data[$path])) + $data[$path] = array (); + $data = & $data[$path]; + } + } + + ApiResult :: addElement($data, $name, $value); + } + + /** + * Recursivelly removes any elements from the array that begin with an '_'. + * The content element '*' is the only special element that is left. + * Use this method when the entire data object gets sent to the user. + */ + public function SanitizeData() { + ApiResult :: SanitizeDataInt($this->mData); + } + + private static function SanitizeDataInt(& $data) { + foreach ($data as $key => & $value) { + if ($key[0] === '_') { + unset ($data[$key]); + } + elseif ($key === '*' && $value === '') { + unset ($data[$key]); + } + elseif (is_array($value)) { + ApiResult :: SanitizeDataInt($value); + } + } + } + + public function execute() { + $this->dieDebug('execute() is not supported on Result object'); + } +} +?> -- 2.20.1