From 03d3a5c062db74c2ed809f7e61a9ca9c3dbd9c36 Mon Sep 17 00:00:00 2001 From: Andrew H Date: Fri, 3 Jun 2016 05:40:25 +0000 Subject: [PATCH] Add PARAM_ALL setting for multi-option API parameters Adds support for specifying an asterisk '*' instead of a pipe seperated list of all the allowed options for a multi-option param. Adds a line to the api help for these parameters. Adds a "allspecifier" key to ApiParamInfo parameter responses Enables the default ('*') for parameters of type 'namespace'. Bug: T124009 Change-Id: I3905bb2516dc1ff982f1beeac3deed6b69446a77 --- includes/api/ApiBase.php | 41 ++++++++++++++++++++++++++++++++--- includes/api/ApiHelp.php | 14 ++++++++++++ includes/api/ApiParamInfo.php | 15 +++++++++++++ includes/api/i18n/en.json | 1 + includes/api/i18n/qqq.json | 1 + 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 506ff73a41..0cd46e42b4 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -67,7 +67,8 @@ abstract class ApiBase extends ContextSource { * - limit: An integer or the string 'max'. Default lower limit is 0 (but * see PARAM_MIN), and requires that PARAM_MAX and PARAM_MAX2 be * specified. Cannot be used with PARAM_ISMULTI. - * - namespace: An integer representing a MediaWiki namespace. + * - namespace: An integer representing a MediaWiki namespace. Forces PARAM_ALL = true to + * support easily specifying all namespaces. * - NULL: Any string. * - password: Any non-empty string. Input value is private or sensitive. * would be an appropriate HTML form field. @@ -171,8 +172,18 @@ abstract class ApiBase extends ContextSource { */ const PARAM_SUBMODULE_PARAM_PREFIX = 16; + /** + * (boolean|string) When PARAM_TYPE has a defined set of values and PARAM_ISMULTI is true, + * this allows for an asterisk ('*') to be passed in place of a pipe-separated list of + * every possible value. If a string is set, it will be used in place of the asterisk. + * @since 1.29 + */ + const PARAM_ALL = 17; + /**@}*/ + const ALL_DEFAULT_STRING = '*'; + /** Fast query, standard limit. */ const LIMIT_BIG1 = 500; /** Fast query, apihighlimits limit. */ @@ -920,6 +931,7 @@ abstract class ApiBase extends ContextSource { $dupes = false; $deprecated = false; $required = false; + $allowAll = false; } else { $default = isset( $paramSettings[self::PARAM_DFLT] ) ? $paramSettings[self::PARAM_DFLT] @@ -939,6 +951,9 @@ abstract class ApiBase extends ContextSource { $required = isset( $paramSettings[self::PARAM_REQUIRED] ) ? $paramSettings[self::PARAM_REQUIRED] : false; + $allowAll = isset( $paramSettings[self::PARAM_ALL] ) + ? $paramSettings[self::PARAM_ALL] + : false; // When type is not given, and no choices, the type is the same as $default if ( !isset( $type ) ) { @@ -992,6 +1007,9 @@ abstract class ApiBase extends ContextSource { if ( isset( $value ) && $type == 'namespace' ) { $type = MWNamespace::getValidNamespaces(); + // By default, namespace parameters allow ALL_DEFAULT_STRING to be used to specify + // all namespaces. + $allowAll = true; } if ( isset( $value ) && $type == 'submodule' ) { if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) { @@ -1027,12 +1045,19 @@ abstract class ApiBase extends ContextSource { } } + $allSpecifier = ( is_string( $allowAll ) ? $allowAll : self::ALL_DEFAULT_STRING ); + if ( $allowAll && $multi && is_array( $type ) && in_array( $allSpecifier, $type, true ) ) { + ApiBase::dieDebug( + __METHOD__, + "For param $encParamName, PARAM_ALL collides with a possible value" ); + } if ( isset( $value ) && ( $multi || is_array( $type ) ) ) { $value = $this->parseMultiValue( $encParamName, $value, $multi, - is_array( $type ) ? $type : null + is_array( $type ) ? $type : null, + $allowAll ? $allSpecifier : null ); } @@ -1215,9 +1240,13 @@ abstract class ApiBase extends ContextSource { * separated by '|'? * @param string[]|null $allowedValues An array of values to check against. If * null, all values are accepted. + * @param string|null $allSpecifier String to use to specify all allowed values, or null + * if this behavior should not be allowed * @return string|string[] (allowMultiple ? an_array_of_values : a_single_value) */ - protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues ) { + protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues, + $allSpecifier = null + ) { if ( ( trim( $value ) === '' || trim( $value ) === "\x1f" ) && $allowMultiple ) { return []; } @@ -1229,6 +1258,12 @@ abstract class ApiBase extends ContextSource { ? self::LIMIT_SML2 : self::LIMIT_SML1; + if ( $allowMultiple && is_array( $allowedValues ) && $allSpecifier && + count( $valuesList ) === 1 && $valuesList[0] === $allSpecifier + ) { + return $allowedValues; + } + if ( self::truncateArray( $valuesList, $sizeLimit ) ) { $this->logFeatureUsage( "too-many-$valueName-for-{$this->getModulePath()}" ); $this->setWarning( "Too many values supplied for parameter '$valueName': " . diff --git a/includes/api/ApiHelp.php b/includes/api/ApiHelp.php index 02efd7b5c9..2a6c938a47 100644 --- a/includes/api/ApiHelp.php +++ b/includes/api/ApiHelp.php @@ -645,6 +645,20 @@ class ApiHelp extends ApiBase { if ( $extra ) { $info[] = implode( ' ', $extra ); } + + $allowAll = isset( $settings[ApiBase::PARAM_ALL] ) + ? $settings[ApiBase::PARAM_ALL] + : false; + if ( $allowAll || $settings[ApiBase::PARAM_TYPE] === 'namespace' ) { + if ( $settings[ApiBase::PARAM_TYPE] === 'namespace' ) { + $allSpecifier = ApiBase::ALL_DEFAULT_STRING; + } else { + $allSpecifier = ( is_string( $allowAll ) ? $allowAll : ApiBase::ALL_DEFAULT_STRING ); + } + $info[] = $context->msg( 'api-help-param-multi-all' ) + ->params( $allSpecifier ) + ->parse(); + } } } diff --git a/includes/api/ApiParamInfo.php b/includes/api/ApiParamInfo.php index caf0cd76fc..ffc3fc2e32 100644 --- a/includes/api/ApiParamInfo.php +++ b/includes/api/ApiParamInfo.php @@ -406,6 +406,21 @@ class ApiParamInfo extends ApiBase { $item['type'] = array_values( $item['type'] ); ApiResult::setIndexedTagName( $item['type'], 't' ); } + + // Add 'allspecifier' if applicable + if ( $item['type'] === 'namespace' ) { + $allowAll = true; + $allSpecifier = ApiBase::ALL_DEFAULT_STRING; + } else { + $allowAll = isset( $settings[ApiBase::PARAM_ALL] ) + ? $settings[ApiBase::PARAM_ALL] + : false; + $allSpecifier = ( is_string( $allowAll ) ? $allowAll : ApiBase::ALL_DEFAULT_STRING ); + } + if ( $allowAll && $item['multi'] && + ( is_array( $item['type'] ) || $item['type'] === 'namespace' ) ) { + $item['allspecifier'] = $allSpecifier; + } } if ( isset( $settings[ApiBase::PARAM_MAX] ) ) { $item['max'] = $settings[ApiBase::PARAM_MAX]; diff --git a/includes/api/i18n/en.json b/includes/api/i18n/en.json index 0f184d9f5d..a043f1e1ad 100644 --- a/includes/api/i18n/en.json +++ b/includes/api/i18n/en.json @@ -1501,6 +1501,7 @@ "api-help-param-upload": "Must be posted as a file upload using multipart/form-data.", "api-help-param-multi-separate": "Separate values with | or [[Special:ApiHelp/main#main/datatypes|alternative]].", "api-help-param-multi-max": "Maximum number of values is {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} for bots).", + "api-help-param-multi-all": "To specify all values, use $1.", "api-help-param-default": "Default: $1", "api-help-param-default-empty": "Default: (empty)", "api-help-param-token": "A \"$1\" token retrieved from [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]", diff --git a/includes/api/i18n/qqq.json b/includes/api/i18n/qqq.json index f7c750e373..6c8606785f 100644 --- a/includes/api/i18n/qqq.json +++ b/includes/api/i18n/qqq.json @@ -1397,6 +1397,7 @@ "api-help-param-upload": "{{technical}} Used to indicate that an 'upload'-type parameter must be posted as a file upload using multipart/form-data", "api-help-param-multi-separate": "Used to indicate how to separate multiple values. Not used with {{msg-mw|api-help-param-list}}.", "api-help-param-multi-max": "Used to indicate the maximum number of values accepted for a multi-valued parameter.\n\nParameters:\n* $1 - Maximum value without the apihighlimits right\n* $2 - Maximum value with the apihighlimits right", + "api-help-param-multi-all": "Used to indicate what string can be used to specify all possible values of a multi-valued parameter. \n\nParameters:\n* $1 - String to specify all possible values of the parameter", "api-help-param-default": "Used to display the default value for an API parameter\n\nParameters:\n* $1 - Default value\n\nSee also:\n* {{msg-mw|api-help-param-default-empty}}\n{{Identical|Default}}", "api-help-param-default-empty": "Used to display the default value for an API parameter when that default is an empty value\n\nSee also:\n* {{msg-mw|api-help-param-default}}", "api-help-param-token": "{{doc-apihelp-param|description=any 'token' parameter|paramstart=2|params=\n* $1 - Token type|noseealso=1}}", -- 2.20.1