summaryrefslogtreecommitdiff
path: root/includes/api/ApiBase.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/api/ApiBase.php')
-rw-r--r--includes/api/ApiBase.php200
1 files changed, 146 insertions, 54 deletions
diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php
index f578f41b..1a9c1e3d 100644
--- a/includes/api/ApiBase.php
+++ b/includes/api/ApiBase.php
@@ -35,6 +35,11 @@ abstract class ApiBase {
const PARAM_MAX2 = 4;
const PARAM_MIN = 5;
+ const LIMIT_BIG1 = 500; // Fast query, user's limit
+ const LIMIT_BIG2 = 5000; // Fast query, bot's limit
+ const LIMIT_SML1 = 50; // Slow query, user's limit
+ const LIMIT_SML2 = 500; // Slow query, bot's limit
+
private $mMainModule, $mModuleName, $mParamPrefix;
/**
@@ -42,7 +47,7 @@ abstract class ApiBase {
*/
public function __construct($mainModule, $moduleName, $paramPrefix = '') {
$this->mMainModule = $mainModule;
- $this->mModuleName = $moduleName;
+ $this->mModuleName = $moduleName;
$this->mParamPrefix = $paramPrefix;
}
@@ -51,12 +56,22 @@ abstract class ApiBase {
*/
public abstract function execute();
- /**
- * Get the name of the query being executed by this instance
- */
- public function getModuleName() {
- return $this->mModuleName;
- }
+ /**
+ * Get the name of the module being executed by this instance
+ */
+ public function getModuleName() {
+ return $this->mModuleName;
+ }
+
+ /**
+ * Get the name of the module as shown in the profiler log
+ */
+ public function getModuleProfileName($db = false) {
+ if ($db)
+ return 'API:' . $this->mModuleName . '-DB';
+ else
+ return 'API:' . $this->mModuleName;
+ }
/**
* Get main module
@@ -91,6 +106,15 @@ abstract class ApiBase {
}
/**
+ * If the module may only be used with a certain format module,
+ * it should override this method to return an instance of that formatter.
+ * A value of null means the default format will be used.
+ */
+ public function getCustomPrinter() {
+ return null;
+ }
+
+ /**
* Generates help message for this module, or false if there is no description
*/
public function makeHelpMsg() {
@@ -126,8 +150,17 @@ abstract class ApiBase {
if ($this->getMain()->getShowVersions()) {
$versions = $this->getVersion();
- if (is_array($versions))
+ $pattern = '(\$.*) ([0-9a-z_]+\.php) (.*\$)';
+ $replacement = '\\0' . "\n " . 'http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/api/\\2';
+
+ if (is_array($versions)) {
+ foreach ($versions as &$v)
+ $v = eregi_replace($pattern, $replacement, $v);
$versions = implode("\n ", $versions);
+ }
+ else
+ $versions = eregi_replace($pattern, $replacement, $versions);
+
$msg .= "Version:\n $versions\n";
}
}
@@ -141,10 +174,32 @@ abstract class ApiBase {
$paramsDescription = $this->getParamDescription();
$msg = '';
- foreach (array_keys($params) as $paramName) {
+ $paramPrefix = "\n" . str_repeat(' ', 19);
+ foreach ($params as $paramName => $paramSettings) {
$desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : '';
if (is_array($desc))
- $desc = implode("\n" . str_repeat(' ', 19), $desc);
+ $desc = implode($paramPrefix, $desc);
+
+ @ $type = $paramSettings[self :: PARAM_TYPE];
+ if (isset ($type)) {
+ if (isset ($paramSettings[self :: PARAM_ISMULTI]))
+ $prompt = 'Values (separate with \'|\'): ';
+ else
+ $prompt = 'One value: ';
+
+ if (is_array($type)) {
+ $desc .= $paramPrefix . $prompt . implode(', ', $type);
+ }
+ elseif ($type == 'namespace') {
+ // Special handling because namespaces are type-limited, yet they are not given
+ $desc .= $paramPrefix . $prompt . implode(', ', ApiBase :: getValidNamespaces());
+ }
+ }
+
+ $default = is_array($paramSettings) ? (isset ($paramSettings[self :: PARAM_DFLT]) ? $paramSettings[self :: PARAM_DFLT] : null) : $paramSettings;
+ if (!is_null($default) && $default !== false)
+ $desc .= $paramPrefix . "Default: $default";
+
$msg .= sprintf(" %-14s - %s\n", $this->encodeParamName($paramName), $desc);
}
return $msg;
@@ -180,7 +235,7 @@ abstract class ApiBase {
protected function getParamDescription() {
return false;
}
-
+
/**
* This method mangles parameter name based on the prefix supplied to the constructor.
* Override this method to change parameter name during runtime
@@ -213,13 +268,26 @@ abstract class ApiBase {
return $this->getParameterFromSettings($paramName, $paramSettings);
}
+ public static function getValidNamespaces() {
+ static $mValidNamespaces = null;
+ if (is_null($mValidNamespaces)) {
+
+ global $wgContLang;
+ $mValidNamespaces = array ();
+ foreach (array_keys($wgContLang->getNamespaces()) as $ns) {
+ if ($ns >= 0)
+ $mValidNamespaces[] = $ns;
+ }
+ }
+ return $mValidNamespaces;
+ }
+
/**
* Using the settings determine the value for the given parameter
* @param $paramName String: parameter name
* @param $paramSettings Mixed: default value or an array of settings using PARAM_* constants.
- */
+ */
protected function getParameterFromSettings($paramName, $paramSettings) {
- global $wgRequest;
// Some classes may decide to change parameter names
$paramName = $this->encodeParamName($paramName);
@@ -248,48 +316,58 @@ abstract class ApiBase {
ApiBase :: dieDebug(__METHOD__, "Boolean param $paramName's default is set to '$default'");
}
- $value = $wgRequest->getCheck($paramName);
- } else
- $value = $wgRequest->getVal($paramName, $default);
+ $value = $this->getMain()->getRequest()->getCheck($paramName);
+ } else {
+ $value = $this->getMain()->getRequest()->getVal($paramName, $default);
+
+ if (isset ($value) && $type == 'namespace')
+ $type = ApiBase :: getValidNamespaces();
+ }
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(__METHOD__, "MAX1 or MAX2 are not defined for the limit $paramName");
- if ($multi)
- ApiBase :: dieDebug(__METHOD__, "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(__METHOD__, "Multi-values not supported for $paramName");
- break;
- case 'timestamp' :
- if ($multi)
- ApiBase :: dieDebug(__METHOD__, "Multi-values not supported for $paramName");
- if (!preg_match('/^[0-9]{14}$/', $value))
- $this->dieUsage("Invalid value '$value' for timestamp parameter $paramName", "badtimestamp_{$valueName}");
- break;
- default :
- ApiBase :: dieDebug(__METHOD__, "Param $paramName's type is unknown - $type");
-
+ if (isset ($value)) {
+ if (!is_array($type)) {
+ 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(__METHOD__, "MAX1 or MAX2 are not defined for the limit $paramName");
+ if ($multi)
+ ApiBase :: dieDebug(__METHOD__, "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(__METHOD__, "Multi-values not supported for $paramName");
+ break;
+ case 'timestamp' :
+ if ($multi)
+ ApiBase :: dieDebug(__METHOD__, "Multi-values not supported for $paramName");
+ $value = wfTimestamp(TS_UNIX, $value);
+ if ($value === 0)
+ $this->dieUsage("Invalid value '$value' for timestamp parameter $paramName", "badtimestamp_{$paramName}");
+ $value = wfTimestamp(TS_MW, $value);
+ break;
+ default :
+ ApiBase :: dieDebug(__METHOD__, "Param $paramName's type is unknown - $type");
+ }
}
+
+ // There should never be any duplicate values in a list
+ if (is_array($value))
+ $value = array_unique($value);
}
return $value;
@@ -314,7 +392,7 @@ abstract class ApiBase {
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" : "") . " for parameter '$valueName'", "unknown_$valueName");
}
}
@@ -325,8 +403,6 @@ 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) {
- global $wgUser;
-
if ($value < $min) {
$this->dieUsage("$varname may not be less than $min (set to $value)", $varname);
}
@@ -345,7 +421,7 @@ abstract class ApiBase {
* Call main module's error handler
*/
public function dieUsage($description, $errorCode, $httpRespCode = 0) {
- $this->getMain()->mainDieUsage($description, $this->encodeParamName($errorCode), $httpRespCode);
+ throw new UsageException($description, $this->encodeParamName($errorCode), $httpRespCode);
}
/**
@@ -367,6 +443,7 @@ abstract class ApiBase {
if ($this->mTimeIn !== 0)
ApiBase :: dieDebug(__METHOD__, 'called twice without calling profileOut()');
$this->mTimeIn = microtime(true);
+ wfProfileIn($this->getModuleProfileName());
}
/**
@@ -380,6 +457,19 @@ abstract class ApiBase {
$this->mModuleTime += microtime(true) - $this->mTimeIn;
$this->mTimeIn = 0;
+ wfProfileOut($this->getModuleProfileName());
+ }
+
+ /**
+ * When modules crash, sometimes it is needed to do a profileOut() regardless
+ * of the profiling state the module was in. This method does such cleanup.
+ */
+ public function safeProfileOut() {
+ if ($this->mTimeIn !== 0) {
+ if ($this->mDBTimeIn !== 0)
+ $this->profileDBOut();
+ $this->profileOut();
+ }
}
/**
@@ -405,6 +495,7 @@ abstract class ApiBase {
if ($this->mDBTimeIn !== 0)
ApiBase :: dieDebug(__METHOD__, 'called twice without calling profileDBOut()');
$this->mDBTimeIn = microtime(true);
+ wfProfileIn($this->getModuleProfileName(true));
}
/**
@@ -421,6 +512,7 @@ abstract class ApiBase {
$this->mDBTime += $time;
$this->getMain()->mDBTime += $time;
+ wfProfileOut($this->getModuleProfileName(true));
}
/**
@@ -433,9 +525,9 @@ abstract class ApiBase {
}
public abstract function getVersion();
-
+
public static function getBaseVersion() {
- return __CLASS__ . ': $Id: ApiBase.php 16757 2006-10-03 05:41:55Z yurik $';
+ return __CLASS__ . ': $Id: ApiBase.php 17880 2006-11-23 08:25:56Z nickj $';
}
}
?> \ No newline at end of file