X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fapi%2FApiBase.php;h=3a9167f0d00052f69ff7892b5fe21a3241a56bbc;hb=08e0ed2b70ba5986a96c701f84a7679c98a6f2fd;hp=bf8e632387aca2285a38ea869e1d155a3d2696e3;hpb=e0b6258185e05cfc20c7b084bb8e9af650196cda;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index bf8e632387..3a9167f0d0 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -188,13 +188,22 @@ abstract class ApiBase extends ContextSource { */ const PARAM_EXTRA_NAMESPACES = 18; - /* + /** * (boolean) Is the parameter sensitive? Note 'password'-type fields are * always sensitive regardless of the value of this field. * @since 1.29 */ const PARAM_SENSITIVE = 19; + /** + * (array) When PARAM_TYPE is an array, this indicates which of the values are deprecated. + * Keys are the deprecated parameter values, values define the warning + * message to emit: either boolean true (to use a default message) or a + * $msg for ApiBase::makeMessage(). + * @since 1.30 + */ + const PARAM_DEPRECATED_VALUES = 20; + /**@}*/ const ALL_DEFAULT_STRING = '*'; @@ -385,6 +394,13 @@ abstract class ApiBase extends ContextSource { /** * Indicates whether this module requires write mode + * + * This should return true for modules that may require synchronous database writes. + * Modules that do not need such writes should also not rely on master database access, + * since only read queries are needed and each master DB is a single point of failure. + * Additionally, requests that only need replica DBs can be efficiently routed to any + * datacenter via the Promise-Non-Write-API-Action header. + * * @return bool */ public function isWriteMode() { @@ -1018,6 +1034,9 @@ abstract class ApiBase extends ContextSource { $deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] ) ? $paramSettings[self::PARAM_DEPRECATED] : false; + $deprecatedValues = isset( $paramSettings[self::PARAM_DEPRECATED_VALUES] ) + ? $paramSettings[self::PARAM_DEPRECATED_VALUES] + : []; $required = isset( $paramSettings[self::PARAM_REQUIRED] ) ? $paramSettings[self::PARAM_REQUIRED] : false; @@ -1259,6 +1278,29 @@ abstract class ApiBase extends ContextSource { } $this->addDeprecation( [ 'apiwarn-deprecation-parameter', $encParamName ], $feature ); } + + // Set a warning if a deprecated parameter value has been passed + $usedDeprecatedValues = $deprecatedValues && $value !== false + ? array_intersect( array_keys( $deprecatedValues ), (array)$value ) + : []; + if ( $usedDeprecatedValues ) { + $feature = "$encParamName="; + $m = $this; + while ( !$m->isMain() ) { + $p = $m->getParent(); + $name = $m->getModuleName(); + $param = $p->encodeParamName( $p->getModuleManager()->getModuleGroup( $name ) ); + $feature = "{$param}={$name}&{$feature}"; + $m = $p; + } + foreach ( $usedDeprecatedValues as $v ) { + $msg = $deprecatedValues[$v]; + if ( $msg === true ) { + $msg = [ 'apiwarn-deprecation-parameter', "$encParamName=$v" ]; + } + $this->addDeprecation( $msg, "$feature$v" ); + } + } } elseif ( $required ) { $this->dieWithError( [ 'apierror-missingparam', $paramName ] ); } @@ -1856,6 +1898,23 @@ abstract class ApiBase extends ContextSource { throw new MWException( 'Successful status passed to ApiBase::dieStatus' ); } + // ApiUsageException needs a fatal status, but this method has + // historically accepted any non-good status. Convert it if necessary. + $status->setOK( false ); + if ( !$status->getErrorsByType( 'error' ) ) { + $newStatus = Status::newGood(); + foreach ( $status->getErrorsByType( 'warning' ) as $err ) { + call_user_func_array( + [ $newStatus, 'fatal' ], + array_merge( [ $err['message'] ], $err['params'] ) + ); + } + if ( !$newStatus->getErrorsByType( 'error' ) ) { + $newStatus->fatal( 'unknownerror-nocode' ); + } + $status = $newStatus; + } + throw new ApiUsageException( $this, $status ); } @@ -1980,12 +2039,62 @@ abstract class ApiBase extends ContextSource { */ /** - * Return the description message. + * Return the summary message. * + * This is a one-line description of the module, suitable for display in a + * list of modules. + * + * @since 1.30 * @return string|array|Message */ - protected function getDescriptionMessage() { - return "apihelp-{$this->getModulePath()}-description"; + protected function getSummaryMessage() { + return "apihelp-{$this->getModulePath()}-summary"; + } + + /** + * Return the extended help text message. + * + * This is additional text to display at the top of the help section, below + * the summary. + * + * @since 1.30 + * @return string|array|Message + */ + protected function getExtendedDescription() { + return [ [ + "apihelp-{$this->getModulePath()}-extended-description", + 'api-help-no-extended-description', + ] ]; + } + + /** + * Get final module summary + * + * Ideally this will just be the getSummaryMessage(). However, for + * backwards compatibility, if that message does not exist then the first + * line of wikitext from the description message will be used instead. + * + * @since 1.30 + * @return Message + */ + public function getFinalSummary() { + $msg = ApiBase::makeMessage( $this->getSummaryMessage(), $this->getContext(), [ + $this->getModulePrefix(), + $this->getModuleName(), + $this->getModulePath(), + ] ); + if ( !$msg->exists() ) { + wfDeprecated( 'API help "description" messages', '1.30' ); + $msg = ApiBase::makeMessage( $this->getDescriptionMessage(), $this->getContext(), [ + $this->getModulePrefix(), + $this->getModuleName(), + $this->getModulePath(), + ] ); + $msg = ApiBase::makeMessage( 'rawmessage', $this->getContext(), [ + preg_replace( '/\n.*/s', '', $msg->text() ) + ] ); + } + return $msg; } /** @@ -2008,15 +2117,33 @@ abstract class ApiBase extends ContextSource { $desc = (string)$desc; } - $msg = ApiBase::makeMessage( $this->getDescriptionMessage(), $this->getContext(), [ + $summary = ApiBase::makeMessage( $this->getSummaryMessage(), $this->getContext(), [ $this->getModulePrefix(), $this->getModuleName(), $this->getModulePath(), ] ); - if ( !$msg->exists() ) { - $msg = $this->msg( 'api-help-fallback-description', $desc ); + $extendedDescription = ApiBase::makeMessage( + $this->getExtendedDescription(), $this->getContext(), [ + $this->getModulePrefix(), + $this->getModuleName(), + $this->getModulePath(), + ] + ); + + if ( $summary->exists() ) { + $msgs = [ $summary, $extendedDescription ]; + } else { + wfDeprecated( 'API help "description" messages', '1.30' ); + $description = ApiBase::makeMessage( $this->getDescriptionMessage(), $this->getContext(), [ + $this->getModulePrefix(), + $this->getModuleName(), + $this->getModulePath(), + ] ); + if ( !$description->exists() ) { + $description = $this->msg( 'api-help-fallback-description', $desc ); + } + $msgs = [ $description ]; } - $msgs = [ $msg ]; Hooks::run( 'APIGetDescriptionMessages', [ $this, &$msgs ] ); @@ -2114,7 +2241,49 @@ abstract class ApiBase extends ContextSource { } $msgs[$param] = [ $msg ]; - if ( isset( $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE] ) ) { + if ( isset( $settings[ApiBase::PARAM_TYPE] ) && + $settings[ApiBase::PARAM_TYPE] === 'submodule' + ) { + if ( isset( $settings[ApiBase::PARAM_SUBMODULE_MAP] ) ) { + $map = $settings[ApiBase::PARAM_SUBMODULE_MAP]; + } else { + $prefix = $this->isMain() ? '' : ( $this->getModulePath() . '+' ); + $map = []; + foreach ( $this->getModuleManager()->getNames( $param ) as $submoduleName ) { + $map[$submoduleName] = $prefix . $submoduleName; + } + } + ksort( $map ); + $submodules = []; + $deprecatedSubmodules = []; + foreach ( $map as $v => $m ) { + $arr = &$submodules; + $isDeprecated = false; + $summary = null; + try { + $submod = $this->getModuleFromPath( $m ); + if ( $submod ) { + $summary = $submod->getFinalSummary(); + $isDeprecated = $submod->isDeprecated(); + if ( $isDeprecated ) { + $arr = &$deprecatedSubmodules; + } + } + } catch ( ApiUsageException $ex ) { + // Ignore + } + if ( $summary ) { + $key = $summary->getKey(); + $params = $summary->getParams(); + } else { + $key = 'api-help-undocumented-module'; + $params = [ $m ]; + } + $m = new ApiHelpParamValueMessage( "[[Special:ApiHelp/$m|$v]]", $key, $params, $isDeprecated ); + $arr[] = $m->setContext( $this->getContext() ); + } + $msgs[$param] = array_merge( $msgs[$param], $submodules, $deprecatedSubmodules ); + } elseif ( isset( $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE] ) ) { if ( !is_array( $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE] ) ) { self::dieDebug( __METHOD__, 'ApiBase::PARAM_HELP_MSG_PER_VALUE is not valid' ); @@ -2126,6 +2295,10 @@ abstract class ApiBase extends ContextSource { } $valueMsgs = $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE]; + $deprecatedValues = isset( $settings[ApiBase::PARAM_DEPRECATED_VALUES] ) + ? $settings[ApiBase::PARAM_DEPRECATED_VALUES] + : []; + foreach ( $settings[ApiBase::PARAM_TYPE] as $value ) { if ( isset( $valueMsgs[$value] ) ) { $msg = $valueMsgs[$value]; @@ -2138,7 +2311,8 @@ abstract class ApiBase extends ContextSource { $m = new ApiHelpParamValueMessage( $value, [ $m->getKey(), 'api-help-param-no-description' ], - $m->getParams() + $m->getParams(), + isset( $deprecatedValues[$value] ) ); $msgs[$param][] = $m->setContext( $this->getContext() ); } else { @@ -2731,6 +2905,21 @@ abstract class ApiBase extends ContextSource { $this->dieWithErrorOrDebug( $this->parseMsgInternal( $error ) ); } + /** + * Return the description message. + * + * This is additional text to display on the help page after the summary. + * + * @deprecated since 1.30 + * @return string|array|Message + */ + protected function getDescriptionMessage() { + return [ [ + "apihelp-{$this->getModulePath()}-description", + "apihelp-{$this->getModulePath()}-summary", + ] ]; + } + /**@}*/ }