API: * (bug 15785) Allow for different expiry times for different protections, like...
authorRoan Kattouw <catrope@users.mediawiki.org>
Sat, 4 Oct 2008 14:58:13 +0000 (14:58 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Sat, 4 Oct 2008 14:58:13 +0000 (14:58 +0000)
* 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()

RELEASE-NOTES
includes/api/ApiBase.php
includes/api/ApiProtect.php

index 32a847d..496f6bf 100644 (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 ===
 
index 622b020..8a4b34c 100644 (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"),
index 9b190e1..f9b124c 100644 (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'
                );
        }