*/
abstract class ApiBase {
- // These constants allow modules to specify exactly how to treat incomming parameters.
+ // These constants allow modules to specify exactly how to treat incoming parameters.
- const PARAM_DFLT = 0;
- const PARAM_ISMULTI = 1;
- const PARAM_TYPE = 2;
- const PARAM_MAX = 3;
- const PARAM_MAX2 = 4;
- const PARAM_MIN = 5;
+ const PARAM_DFLT = 0; // Default value of the parameter
+ const PARAM_ISMULTI = 1; // Boolean, do we accept more than one item for this parameter (e.g.: titles)?
+ const PARAM_TYPE = 2; // Can be either a string type (e.g.: 'integer') or an array of allowed values
+ const PARAM_MAX = 3; // Max value allowed for a parameter. Only applies if TYPE='integer'
+ const PARAM_MAX2 = 4; // Max value allowed for a parameter for bots and sysops. Only applies if TYPE='integer'
+ const PARAM_MIN = 5; // Lowest value allowed for a parameter. Only applies if TYPE='integer'
+ const PARAM_ALLOW_DUPLICATES = 6; // Boolean, do we allow the same value to be set more than once when ISMULTI=true
const LIMIT_BIG1 = 500; // Fast query, std user limit
const LIMIT_BIG2 = 5000; // Fast query, bot/sysop limit
$data =& $this->getResult()->getData();
if(isset($data['warnings'][$this->getModuleName()]))
{
+ # Don't add duplicate warnings
+ $warn_regex = preg_quote($warning, '/');
+ if(preg_match("/{$warn_regex}(\\n|$)/", $data['warnings'][$this->getModuleName()]['*']))
+ return;
$warning = "{$data['warnings'][$this->getModuleName()]['*']}\n$warning";
unset($data['warnings'][$this->getModuleName()]);
}
* module's help.
*/
public function makeHelpMsgParameters() {
- $params = $this->getAllowedParams();
+ $params = $this->getFinalParams();
if ($params !== false) {
- $paramsDescription = $this->getParamDescription();
+ $paramsDescription = $this->getFinalParamDescription();
$msg = '';
$paramPrefix = "\n" . str_repeat(' ', 19);
foreach ($params as $paramName => $paramSettings) {
}
/**
- * Returns an array of allowed parameters (keys) => default value for that parameter
+ * Returns an array of allowed parameters (keys) => default value for that parameter.
+ * Don't call this function directly: use getFinalParams() to allow hooks
+ * to modify parameters as needed.
*/
protected function getAllowedParams() {
return false;
}
/**
- * Returns the description string for the given parameter.
+ * Returns an array of parameter descriptions.
+ * Don't call this functon directly: use getFinalParamDescription() to allow
+ * hooks to modify descriptions as needed.
*/
protected function getParamDescription() {
return false;
}
+
+ /**
+ * Get final list of parameters, after hooks have had
+ * a chance to tweak it as needed.
+ */
+ public function getFinalParams() {
+ $params = $this->getAllowedParams();
+ wfRunHooks('APIGetAllowedParams', array(&$this, &$params));
+ return $params;
+ }
+
+
+ public function getFinalParamDescription() {
+ $desc = $this->getParamDescription();
+ wfRunHooks('APIGetParamDescription', array(&$this, &$desc));
+ return $desc;
+ }
/**
* This method mangles parameter name based on the prefix supplied to the constructor.
/**
* 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().
* limit=max will not be parsed if $parseMaxLimit is set to false; use this
* when the max limit is not definite, e.g. when getting revisions.
*/
public function extractRequestParams($parseMaxLimit = true) {
- $params = $this->getAllowedParams();
+ $params = $this->getFinalParams();
$results = array ();
foreach ($params as $paramName => $paramSettings)
* Get a value for the given parameter
*/
protected function getParameter($paramName, $parseMaxLimit = true) {
- $params = $this->getAllowedParams();
+ $params = $this->getFinalParams();
$paramSettings = $params[$paramName];
return $this->getParameterFromSettings($paramName, $paramSettings, $parseMaxLimit);
}
+
+ /**
+ * Die if none or more than one of a certain set of parameters is set
+ */
+ public function requireOnlyOneParameter($params) {
+ $required = func_get_args();
+ array_shift($required);
+
+ $intersection = array_intersect(array_keys(array_filter($params,
+ create_function('$x', 'return !is_null($x);')
+ )), $required);
+ if (count($intersection) > 1) {
+ $this->dieUsage('The parameters '.implode(', ', $intersection).' can not be used together', 'invalidparammix');
+ } elseif (count($intersection) == 0) {
+ $this->dieUsage('One of the parameters '.implode(', ', $required).' is required', 'missingparam');
+ }
+ }
/**
* Returns an array of the namespaces (by integer id) that exist on the
$default = $paramSettings;
$multi = false;
$type = gettype($paramSettings);
+ $dupes = false;
} 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;
+ $dupes = isset ($paramSettings[self:: PARAM_ALLOW_DUPLICATES]) ? $paramSettings[self :: PARAM_ALLOW_DUPLICATES] : false;
// When type is not given, and no choices, the type is the same as $default
if (!isset ($type)) {
}
}
- // There should never be any duplicate values in a list
- if (is_array($value))
+ // Throw out duplicates if requested
+ if (is_array($value) && !$dupes)
$value = array_unique($value);
}
return array();
$sizeLimit = $this->mMainModule->canApiHighLimits() ? self::LIMIT_SML2 : self::LIMIT_SML1;
$valuesList = explode('|', $value, $sizeLimit + 1);
- if( count($valuesList) == $sizeLimit + 1 ) {
- $junk = array_pop($valuesList); // kill last jumbled param
- // Set a warning too
+ if( self::truncateArray($valuesList, $sizeLimit) ) {
$this->setWarning("Too many values supplied for parameter '$valueName': the limit is $sizeLimit");
}
if (!$allowMultiple && count($valuesList) != 1) {
if (is_array($allowedValues)) {
# Check for unknown values
$unknown = array_diff($valuesList, $allowedValues);
- if(!empty($unknown))
+ if(count($unknown))
{
if($allowMultiple)
{
}
}
}
+
+ /**
+ * Truncate an array to a certain length.
+ * @param $arr array Array to truncate
+ * @param $limit int Maximum length
+ * @return bool True if the array was truncated, false otherwise
+ */
+ public static function truncateArray(&$arr, $limit)
+ {
+ $modified = false;
+ while(count($arr) > $limit)
+ {
+ $junk = array_pop($arr);
+ $modified = true;
+ }
+ return $modified;
+ }
/**
* Call main module's error handler
'ipb_blocked_as_range' => array('code' => 'blockedasrange', 'info' => "IP address ``\$1'' was blocked as part of range ``\$2''. You can't unblock the IP invidually, but you can unblock the range as a whole."),
'ipb_cant_unblock' => array('code' => 'cantunblock', 'info' => "The block you specified was not found. It may have been unblocked already"),
'mailnologin' => array('code' => 'cantsend', 'info' => "You're not logged in or you don't have a confirmed e-mail address, so you can't send e-mail"),
- 'usermaildisabled' => array('code' => 'usermaildisabled' 'info' => "User email has been disabled"),
+ 'usermaildisabled' => array('code' => 'usermaildisabled', 'info' => "User email has been disabled"),
'blockedemailuser' => array('code' => 'blockedfrommail', 'info' => "You have been blocked from sending e-mail"),
'notarget' => array('code' => 'notarget', 'info' => "You have not specified a valid target for this action"),
'noemail' => array('code' => 'noemail', 'info' => "The user has not specified a valid e-mail address, or has chosen not to receive e-mail from other users"),
-
-
+ 'rcpatroldisabled' => array('code' => 'patroldisabled', 'info' => "Patrolling is disabled on this wiki"),
+ 'markedaspatrollederror-noautopatrol' => array('code' => 'noautopatrol', 'info' => "You don't have permission to patrol your own changes"),
// API-specific messages
'missingparam' => array('code' => 'no$1', 'info' => "The \$1 parameter must be set"),
'invalidtitle' => array('code' => 'invalidtitle', 'info' => "Bad title ``\$1''"),
+ 'nosuchpageid' => array('code' => 'nosuchpageid', 'info' => "There is no page with ID \$1"),
'invaliduser' => array('code' => 'invaliduser', 'info' => "Invalid username ``\$1''"),
- 'invalidexpiry' => array('code' => 'invalidexpiry', 'info' => "Invalid expiry time"),
- 'pastexpiry' => array('code' => 'pastexpiry', 'info' => "Expiry time is in the past"),
+ 'invalidexpiry' => array('code' => 'invalidexpiry', 'info' => "Invalid expiry time ``\$1''"),
+ 'pastexpiry' => array('code' => 'pastexpiry', 'info' => "Expiry time ``\$1'' is in the past"),
'create-titleexists' => array('code' => 'create-titleexists', 'info' => "Existing titles can't be protected with 'create'"),
'missingtitle-createonly' => array('code' => 'missingtitle-createonly', 'info' => "Missing titles can only be protected with 'create'"),
'cantblock' => array('code' => 'cantblock', 'info' => "You don't have permission to block users"),
'permdenied-undelete' => array('code' => 'permissiondenied', 'info' => "You don't have permission to restore deleted revisions"),
'createonly-exists' => array('code' => 'articleexists', 'info' => "The article you tried to create has been created already"),
'nocreate-missing' => array('code' => 'missingtitle', 'info' => "The article you tried to edit doesn't exist"),
+ 'nosuchrcid' => array('code' => 'nosuchrcid', 'info' => "There is no change with rcid ``\$1''"),
+ 'cantpurge' => array('code' => 'cantpurge', 'info' => "Only users with the 'purge' right can purge pages via the API"),
+ 'protect-invalidaction' => array('code' => 'protect-invalidaction', 'info' => "Invalid protection type ``\$1''"),
+ 'protect-invalidlevel' => array('code' => 'protect-invalidlevel', 'info' => "Invalid protection level ``\$1''"),
+ 'toofewexpiries' => array('code' => 'toofewexpiries', 'info' => "\$1 expiry timestamps were provided where \$2 were needed"),
+
// ApiEditPage messages
'noimageredirect-anon' => array('code' => 'noimageredirect-anon', 'info' => "Anonymous users can't create image redirects"),