API: Fix profiling errors caused by calling wfProfileClose() from dieUsage()
[lhc/web/wiklou.git] / includes / api / ApiBase.php
index 622b020..8afaae1 100644 (file)
  */
 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
@@ -264,7 +265,7 @@ abstract class ApiBase {
                                                $choices = array();
                                                $nothingPrompt = false;
                                                foreach ($type as $t)
-                                                       if ($t=='')
+                                                       if ($t === '')
                                                                $nothingPrompt = 'Can be empty, or ';
                                                        else
                                                                $choices[] =  $t;
@@ -368,7 +369,6 @@ abstract class ApiBase {
        /**
        * 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.
        */
@@ -442,10 +442,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 +538,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);
                }
 
@@ -559,9 +561,7 @@ abstract class ApiBase {
                        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) {
@@ -571,7 +571,7 @@ abstract class ApiBase {
                if (is_array($allowedValues)) {
                        # Check for unknown values
                        $unknown = array_diff($valuesList, $allowedValues);
-                       if(!empty($unknown))
+                       if(count($unknown))
                        {
                                if($allowMultiple)
                                {
@@ -613,11 +613,29 @@ abstract class ApiBase {
                        }
                }
        }
+       
+       /**
+        * 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
         */
        public function dieUsage($description, $errorCode, $httpRespCode = 0) {
+               wfProfileClose();
                throw new UsageException($description, $this->encodeParamName($errorCode), $httpRespCode);
        }
 
@@ -681,13 +699,15 @@ abstract class ApiBase {
                '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"),
+               'delete-toobig' => array('code' => 'bigdelete', 'info' => "You can't delete this page because it has more than \$1 revisions"),
 
                // 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"),
@@ -704,6 +724,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"),