API: * (bug 15785) Allow for different expiry times for different protections, like the UI does

* BREAKING CHANGE: Alter action=protect output to display multiple expiry times
* BREAKING CHANGE: Error messages invalidexpiry and pastexpiry now state the expiry they're about
* Add ApiBase::PARAM_ALLOW_DUPLICATES and honor it in ApiBase::getParameterFromSettings()
This commit is contained in:
Roan Kattouw 2008-10-04 14:58:13 +00:00
parent 7bb4064436
commit 212720fa28
3 changed files with 49 additions and 27 deletions

View file

@ -293,6 +293,8 @@ The following extensions are migrated into MediaWiki 1.14:
* (bug 15768) Add list=watchlistraw
* (bug 15647) action=edit with basetimestamp fails if the page has been deleted
and undeleted since the last edit
* (bug 15785) Allow for different expiry times for different protections in
action=protect
=== Languages updated in 1.14 ===

View file

@ -46,6 +46,7 @@ abstract class ApiBase {
const PARAM_MAX = 3;
const PARAM_MAX2 = 4;
const PARAM_MIN = 5;
const PARAM_ALLOW_DUPLICATES = 6;
const LIMIT_BIG1 = 500; // Fast query, std user limit
const LIMIT_BIG2 = 5000; // Fast query, bot/sysop limit
@ -442,10 +443,12 @@ abstract class ApiBase {
$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)) {
@ -536,8 +539,8 @@ abstract class ApiBase {
}
}
// 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);
}
@ -686,8 +689,8 @@ abstract class ApiBase {
'missingparam' => array('code' => 'no$1', 'info' => "The \$1 parameter must be set"),
'invalidtitle' => array('code' => 'invalidtitle', 'info' => "Bad title ``\$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"),
@ -704,6 +707,8 @@ abstract class ApiBase {
'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"),

View file

@ -61,22 +61,19 @@ class ApiProtect extends ApiBase {
// We don't care about multiple errors, just report one of them
$this->dieUsageMsg(current($errors));
if(in_array($params['expiry'], array('infinite', 'indefinite', 'never')))
$expiry = Block::infinity();
else
$expiry = (array)$params['expiry'];
if(count($expiry) != count($params['protections']))
{
$expiry = strtotime($params['expiry']);
if($expiry < 0 || $expiry == false)
$this->dieUsageMsg(array('invalidexpiry'));
$expiry = wfTimestamp(TS_MW, $expiry);
if($expiry < wfTimestampNow())
$this->dieUsageMsg(array('pastexpiry'));
if(count($expiry) == 1)
$expiry = array_fill(0, count($params['protections']), $expiry[0]);
else
$this->dieUsageMsg(array('toofewexpiries', count($expiry), count($params['protections'])));
}
$protections = array();
$expiryarray = array();
foreach($params['protections'] as $prot)
$resultProtections = array();
foreach($params['protections'] as $i => $prot)
{
$p = explode('=', $prot);
$protections[$p[0]] = ($p[1] == 'all' ? '' : $p[1]);
@ -88,7 +85,24 @@ class ApiProtect extends ApiBase {
$this->dieUsageMsg(array('protect-invalidaction', $p[0]));
if(!in_array($p[1], $wgRestrictionLevels) && $p[1] != 'all')
$this->dieUsageMsg(array('protect-invalidlevel', $p[1]));
$expiryarray[$p[0]] = $expiry;
if(in_array($expiry[$i], array('infinite', 'indefinite', 'never')))
$expiryarray[$p[0]] = Block::infinity();
else
{
$exp = strtotime($expiry[$i]);
if($exp < 0 || $exp == false)
$this->dieUsageMsg(array('invalidexpiry', $expiry[$i]));
$exp = wfTimestamp(TS_MW, $exp);
if($exp < wfTimestampNow())
$this->dieUsageMsg(array('pastexpiry', $expiry[$i]));
$expiryarray[$p[0]] = $exp;
}
$resultProtections[] = array($p[0] => $protections[$p[0]],
'expiry' => ($expiryarray[$p[0]] == Block::infinity() ?
'infinite' :
wfTimestamp(TS_ISO_8601, $expiryarray[$p[0]])));
}
if($titleObj->exists()) {
@ -101,18 +115,14 @@ class ApiProtect extends ApiBase {
// Just throw an unknown error in this case, as it's very likely to be a race condition
$this->dieUsageMsg(array());
$res = array('title' => $titleObj->getPrefixedText(), 'reason' => $params['reason']);
if($expiry == Block::infinity())
$res['expiry'] = 'infinity';
else
$res['expiry'] = wfTimestamp(TS_ISO_8601, $expiry);
if($params['cascade'])
$res['cascade'] = '';
$res['protections'] = $protections;
$res['protections'] = $resultProtections;
$this->getResult()->setIndexedTagName($res['protections'], 'protection');
$this->getResult()->addValue(null, $this->getModuleName(), $res);
}
public function mustBePosted() { return true; }
//public function mustBePosted() { return true; }
public function getAllowedParams() {
return array (
@ -121,7 +131,11 @@ class ApiProtect extends ApiBase {
'protections' => array(
ApiBase :: PARAM_ISMULTI => true
),
'expiry' => 'infinite',
'expiry' => array(
ApiBase :: PARAM_ISMULTI => true,
ApiBase :: PARAM_ALLOW_DUPLICATES => true,
ApiBase :: PARAM_DFLT => 'infinite',
),
'reason' => '',
'cascade' => false
);
@ -132,7 +146,8 @@ class ApiProtect extends ApiBase {
'title' => 'Title of the page you want to (un)protect.',
'token' => 'A protect token previously retrieved through prop=info',
'protections' => 'Pipe-separated list of protection levels, formatted action=group (e.g. edit=sysop)',
'expiry' => 'Expiry timestamp. If set to \'infinite\', \'indefinite\' or \'never\', the protection will never expire.',
'expiry' => array('Expiry timestamps. If only one timestamp is set, it\'ll be used for all protections.',
'Use \'infinite\', \'indefinite\' or \'never\', for a neverexpiring protection.'),
'reason' => 'Reason for (un)protecting (optional)',
'cascade' => 'Enable cascading protection (i.e. protect pages included in this page)'
);
@ -146,7 +161,7 @@ class ApiProtect extends ApiBase {
protected function getExamples() {
return array (
'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=sysop|move=sysop&cascade&expiry=20070901163000',
'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=sysop|move=sysop&cascade&expiry=20070901163000|never',
'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=all|move=all&reason=Lifting%20restrictions'
);
}