Merge "content: Recognise .json as JsonContent in User and MediaWiki namespace"
[lhc/web/wiklou.git] / includes / api / ApiBase.php
index f4f2c8c..55f9677 100644 (file)
@@ -85,6 +85,15 @@ abstract class ApiBase extends ContextSource {
        // $msg for ApiBase::makeMessage(). Any value not having a mapping will use
        // apihelp-{$path}-paramvalue-{$param}-{$value} is used.
        const PARAM_HELP_MSG_PER_VALUE = 14;
+       /// @since 1.26
+       // When PARAM_TYPE is 'submodule', map parameter values to submodule paths.
+       // Default is to use all modules in $this->getModuleManager() in the group
+       // matching the parameter name.
+       const PARAM_SUBMODULE_MAP = 15;
+       /// @since 1.26
+       // When PARAM_TYPE is 'submodule', used to indicate the 'g' prefix added by
+       // ApiQueryGeneratorBase (and similar if anything else ever does that).
+       const PARAM_SUBMODULE_PARAM_PREFIX = 16;
 
        const LIMIT_BIG1 = 500; // Fast query, std user limit
        const LIMIT_BIG2 = 5000; // Fast query, bot/sysop limit
@@ -472,11 +481,17 @@ abstract class ApiBase extends ContextSource {
        }
 
        /**
-        * Get the result data array (read-only)
-        * @return array
+        * Get the error formatter
+        * @return ApiErrorFormatter
         */
-       public function getResultData() {
-               return $this->getResult()->getData();
+       public function getErrorFormatter() {
+               // Main module has getErrorFormatter() method overridden
+               // Safety - avoid infinite loop:
+               if ( $this->isMain() ) {
+                       ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+               }
+
+               return $this->getMain()->getErrorFormatter();
        }
 
        /**
@@ -491,6 +506,34 @@ abstract class ApiBase extends ContextSource {
                return $this->mSlaveDB;
        }
 
+       /**
+        * Get the continuation manager
+        * @return ApiContinuationManager|null
+        */
+       public function getContinuationManager() {
+               // Main module has getContinuationManager() method overridden
+               // Safety - avoid infinite loop:
+               if ( $this->isMain() ) {
+                       ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+               }
+
+               return $this->getMain()->getContinuationManager();
+       }
+
+       /**
+        * Set the continuation manager
+        * @param ApiContinuationManager|null
+        */
+       public function setContinuationManager( $manager ) {
+               // Main module has setContinuationManager() method overridden
+               // Safety - avoid infinite loop:
+               if ( $this->isMain() ) {
+                       ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+               }
+
+               $this->getMain()->setContinuationManager( $manager );
+       }
+
        /**@}*/
 
        /************************************************************************//**
@@ -804,7 +847,11 @@ abstract class ApiBase extends ContextSource {
                                $type = MWNamespace::getValidNamespaces();
                        }
                        if ( isset( $value ) && $type == 'submodule' ) {
-                               $type = $this->getModuleManager()->getNames( $paramName );
+                               if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) {
+                                       $type = array_keys( $paramSettings[self::PARAM_SUBMODULE_MAP] );
+                               } else {
+                                       $type = $this->getModuleManager()->getNames( $paramName );
+                               }
                        }
                }
 
@@ -825,6 +872,8 @@ abstract class ApiBase extends ContextSource {
                                        case 'NULL': // nothing to do
                                                break;
                                        case 'string':
+                                       case 'text':
+                                       case 'password':
                                                if ( $required && $value === '' ) {
                                                        $this->dieUsageMsg( array( 'missingparam', $paramName ) );
                                                }
@@ -870,7 +919,7 @@ abstract class ApiBase extends ContextSource {
                                                        $value = $this->getMain()->canApiHighLimits()
                                                                ? $paramSettings[self::PARAM_MAX2]
                                                                : $paramSettings[self::PARAM_MAX];
-                                                       $this->getResult()->setParsedLimit( $this->getModuleName(), $value );
+                                                       $this->getResult()->addParsedLimit( $this->getModuleName(), $value );
                                                } else {
                                                        $value = intval( $value );
                                                        $this->validateLimit(
@@ -1044,6 +1093,24 @@ abstract class ApiBase extends ContextSource {
         * @return string Validated and normalized parameter
         */
        protected function validateTimestamp( $value, $encParamName ) {
+               // Confusing synonyms for the current time accepted by wfTimestamp()
+               // (wfTimestamp() also accepts various non-strings and the string of 14
+               // ASCII NUL bytes, but those can't get here)
+               if ( !$value ) {
+                       $this->logFeatureUsage( 'unclear-"now"-timestamp' );
+                       $this->setWarning(
+                               "Passing '$value' for timestamp parameter $encParamName has been deprecated." .
+                                       ' If for some reason you need to explicitly specify the current time without' .
+                                       ' calculating it client-side, use "now".'
+                       );
+                       return wfTimestamp( TS_MW );
+               }
+
+               // Explicit synonym for the current time
+               if ( $value === 'now' ) {
+                       return wfTimestamp( TS_MW );
+               }
+
                $unixTimestamp = wfTimestamp( TS_UNIX, $value );
                if ( $unixTimestamp === false ) {
                        $this->dieUsage(
@@ -1246,28 +1313,8 @@ abstract class ApiBase extends ContextSource {
         * @param string $warning Warning message
         */
        public function setWarning( $warning ) {
-               $result = $this->getResult();
-               $data = $result->getData();
-               $moduleName = $this->getModuleName();
-               if ( isset( $data['warnings'][$moduleName] ) ) {
-                       // Don't add duplicate warnings
-                       $oldWarning = $data['warnings'][$moduleName]['*'];
-                       $warnPos = strpos( $oldWarning, $warning );
-                       // If $warning was found in $oldWarning, check if it starts at 0 or after "\n"
-                       if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
-                               // Check if $warning is followed by "\n" or the end of the $oldWarning
-                               $warnPos += strlen( $warning );
-                               if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
-                                       return;
-                               }
-                       }
-                       // If there is a warning already, append it to the existing one
-                       $warning = "$oldWarning\n$warning";
-               }
-               $msg = array();
-               ApiResult::setContent( $msg, $warning );
-               $result->addValue( 'warnings', $moduleName,
-                       $msg, ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
+               $msg = new ApiRawMessage( $warning, 'warning' );
+               $this->getErrorFormatter()->addWarning( $this->getModuleName(), $msg );
        }
 
        /**
@@ -2288,8 +2335,10 @@ abstract class ApiBase extends ContextSource {
         *
         * @param string[] &$help Array of help data
         * @param array $options Options passed to ApiHelp::getHelp
+        * @param array &$tocData If a TOC is being generated, this array has keys
+        *   as anchors in the page and values as for Linker::generateTOC().
         */
-       public function modifyHelp( array &$help, array $options ) {
+       public function modifyHelp( array &$help, array $options, array &$tocData ) {
        }
 
        /**@}*/
@@ -2656,7 +2705,11 @@ abstract class ApiBase extends ContextSource {
                                        }
 
                                        if ( $type === 'submodule' ) {
-                                               $type = $this->getModuleManager()->getNames( $paramName );
+                                               if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) {
+                                                       $type = array_keys( $paramSettings[self::PARAM_SUBMODULE_MAP] );
+                                               } else {
+                                                       $type = $this->getModuleManager()->getNames( $paramName );
+                                               }
                                                sort( $type );
                                        }
                                        if ( is_array( $type ) ) {
@@ -2809,6 +2862,16 @@ abstract class ApiBase extends ContextSource {
                return 0;
        }
 
+       /**
+        * Get the result data array (read-only)
+        * @deprecated since 1.25, use $this->getResult() methods instead
+        * @return array
+        */
+       public function getResultData() {
+               wfDeprecated( __METHOD__, '1.25' );
+               return $this->getResult()->getData();
+       }
+
        /**@}*/
 }