* ApiBase::getDescriptionMessage() and the "apihelp-*-description" messages are
deprecated. The existing message should be split between "apihelp-*-summary"
and "apihelp-*-extended-description".
+* (T123931) Individual values of multi-valued parameters can now be marked as
+ deprecated.
=== Languages updated in 1.30 ===
MediaWiki supports over 350 languages. Many localisations are updated
*/
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 = '*';
$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;
}
$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 ] );
}
}
$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];
$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 {
if ( is_array( $type ) ) {
$count = count( $type );
+ $deprecatedValues = isset( $settings[ApiBase::PARAM_DEPRECATED_VALUES] )
+ ? $settings[ApiBase::PARAM_DEPRECATED_VALUES]
+ : [];
$links = isset( $settings[ApiBase::PARAM_VALUE_LINKS] )
? $settings[ApiBase::PARAM_VALUE_LINKS]
: [];
- $values = array_map( function ( $v ) use ( $links ) {
- // We can't know whether this contains LTR or RTL text.
- $ret = $v === '' ? $v : Html::element( 'span', [ 'dir' => 'auto' ], $v );
+ $values = array_map( function ( $v ) use ( $links, $deprecatedValues ) {
+ $attr = [];
+ if ( $v !== '' ) {
+ // We can't know whether this contains LTR or RTL text.
+ $attr['dir'] = 'auto';
+ }
+ if ( isset( $deprecatedValues[$v] ) ) {
+ $attr['class'] = 'apihelp-deprecated-value';
+ }
+ $ret = $attr ? Html::element( 'span', $attr, $v ) : $v;
if ( isset( $links[$v] ) ) {
$ret = "[[{$links[$v]}|$ret]]";
}
class ApiHelpParamValueMessage extends Message {
protected $paramValue;
+ protected $deprecated;
/**
* @see Message::__construct
* @param string $paramValue Parameter value being documented
* @param string $text Message to use.
* @param array $params Parameters for the message.
+ * @param bool $deprecated Whether the value is deprecated
* @throws InvalidArgumentException
+ * @since 1.30 Added the `$deprecated` parameter
*/
- public function __construct( $paramValue, $text, $params = [] ) {
+ public function __construct( $paramValue, $text, $params = [], $deprecated = false ) {
parent::__construct( $text, $params );
$this->paramValue = $paramValue;
+ $this->deprecated = (bool)$deprecated;
}
/**
return $this->paramValue;
}
+ /**
+ * Fetch the 'deprecated' flag
+ * @since 1.30
+ * @return bool
+ */
+ public function isDeprecated() {
+ return $this->deprecated;
+ }
+
/**
* Fetch the message.
* @return string
*/
public function fetchMessage() {
if ( $this->message === null ) {
+ $dep = '';
+ if ( $this->isDeprecated() ) {
+ $msg = new Message( 'api-help-param-deprecated' );
+ $msg->interface = $this->interface;
+ $msg->language = $this->language;
+ $msg->useDatabase = $this->useDatabase;
+ $msg->title = $this->title;
+ $dep = '<span class="apihelp-deprecated">' . $msg->fetchMessage() . '</span> ';
+ }
$this->message = ";<span dir=\"ltr\" lang=\"en\">{$this->paramValue}</span>:"
- . parent::fetchMessage();
+ . $dep . parent::fetchMessage();
}
return $this->message;
}
if ( !empty( $settings[ApiBase::PARAM_RANGE_ENFORCE] ) ) {
$item['enforcerange'] = true;
}
+ if ( !empty( $settings[ApiBase::PARAM_DEPRECATED_VALUES] ) ) {
+ $deprecatedValues = array_keys( $settings[ApiBase::PARAM_DEPRECATED_VALUES] );
+ if ( is_array( $item['type'] ) ) {
+ $deprecatedValues = array_intersect( $deprecatedValues, $item['type'] );
+ }
+ if ( $deprecatedValues ) {
+ $item['deprecatedvalues'] = array_values( $deprecatedValues );
+ ApiResult::setIndexedTagName( $item['deprecatedvalues'], 'v' );
+ }
+ }
if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) {
$item['info'] = [];
} else {
$result_array['headitems'] = $this->formatHeadItems( $p_result->getHeadItems() );
}
- $this->addDeprecation( 'apiwarn-deprecation-parse-headitems', 'action=parse&prop=headitems' );
}
if ( isset( $prop['headhtml'] ) ) {
'sections',
'revid',
'displaytitle',
- 'headitems',
'headhtml',
'modules',
'jsconfigvars',
'limitreportdata',
'limitreporthtml',
'parsetree',
- 'parsewarnings'
+ 'parsewarnings',
+ 'headitems',
],
ApiBase::PARAM_HELP_MSG_PER_VALUE => [
'parsetree' => [ 'apihelp-parse-paramvalue-prop-parsetree', CONTENT_MODEL_WIKITEXT ],
],
+ ApiBase::PARAM_DEPRECATED_VALUES => [
+ 'headitems' => 'apiwarn-deprecation-parse-headitems',
+ ],
],
'wrapoutputclass' => 'mw-parser-output',
'pst' => false,
$searchInfo = array_flip( $params['info'] );
$prop = array_flip( $params['prop'] );
- // Deprecated parameters
- if ( isset( $prop['hasrelated'] ) ) {
- $this->addDeprecation(
- [ 'apiwarn-deprecation-parameter', 'srprop=hasrelated' ], 'action=search&srprop=hasrelated'
- );
- }
- if ( isset( $prop['score'] ) ) {
- $this->addDeprecation(
- [ 'apiwarn-deprecation-parameter', 'srprop=score' ], 'action=search&srprop=score'
- );
- }
-
// Create search engine instance and set options
$search = $this->buildSearchEngine( $params );
$search->setFeatureData( 'rewrite', (bool)$params['enablerewrites'] );
],
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
+ ApiBase::PARAM_DEPRECATED_VALUES => [
+ 'score' => true,
+ 'hasrelated' => true
+ ],
],
'interwiki' => false,
'enablerewrites' => false,
$vals['options'][ApiResult::META_BC_BOOLS] = array_keys( $vals['options'] );
}
- if ( isset( $this->prop['preferencestoken'] ) ) {
- $p = $this->getModulePrefix();
- $this->addDeprecation(
- [
- 'apiwarn-deprecation-withreplacement',
- "{$p}prop=preferencestoken",
- 'action=query&meta=tokens',
- ],
- "meta=userinfo&{$p}prop=preferencestoken"
- );
- }
if ( isset( $this->prop['preferencestoken'] ) &&
!$this->lacksSameOriginSecurity() &&
$user->isAllowed( 'editmyoptions' )
'rights',
'changeablegroups',
'options',
- 'preferencestoken',
'editcount',
'ratelimits',
'email',
'registrationdate',
'unreadcount',
'centralids',
+ 'preferencestoken',
],
ApiBase::PARAM_HELP_MSG_PER_VALUE => [
'unreadcount' => [
self::WL_UNREAD_LIMIT . '+',
],
],
+ ApiBase::PARAM_DEPRECATED_VALUES => [
+ 'preferencestoken' => [
+ 'apiwarn-deprecation-withreplacement',
+ $this->getModulePrefix() . "prop=preferencestoken",
+ 'action=query&meta=tokens',
+ ]
+ ],
],
'attachedwiki' => null,
];
"apihelp-parse-paramvalue-prop-sections": "Gives the sections in the parsed wikitext.",
"apihelp-parse-paramvalue-prop-revid": "Adds the revision ID of the parsed page.",
"apihelp-parse-paramvalue-prop-displaytitle": "Adds the title of the parsed wikitext.",
- "apihelp-parse-paramvalue-prop-headitems": "<span class=\"apihelp-deprecated\">Deprecated.</span> Gives items to put in the <code><head></code> of the page.",
+ "apihelp-parse-paramvalue-prop-headitems": "Gives items to put in the <code><head></code> of the page.",
"apihelp-parse-paramvalue-prop-headhtml": "Gives parsed <code><head></code> of the page.",
"apihelp-parse-paramvalue-prop-modules": "Gives the ResourceLoader modules used on the page. To load, use <code>mw.loader.using()</code>. Either <kbd>jsconfigvars</kbd> or <kbd>encodedjsconfigvars</kbd> must be requested jointly with <kbd>modules</kbd>.",
"apihelp-parse-paramvalue-prop-jsconfigvars": "Gives the JavaScript configuration variables specific to the page. To apply, use <code>mw.config.set()</code>.",
"apihelp-query+search-paramvalue-prop-sectiontitle": "Adds the title of the matching section.",
"apihelp-query+search-paramvalue-prop-categorysnippet": "Adds a parsed snippet of the matching category.",
"apihelp-query+search-paramvalue-prop-isfilematch": "Adds a boolean indicating if the search matched file content.",
- "apihelp-query+search-paramvalue-prop-score": "<span class=\"apihelp-deprecated\">Deprecated and ignored.</span>",
- "apihelp-query+search-paramvalue-prop-hasrelated": "<span class=\"apihelp-deprecated\">Deprecated and ignored.</span>",
+ "apihelp-query+search-paramvalue-prop-score": "Ignored.",
+ "apihelp-query+search-paramvalue-prop-hasrelated": "Ignored.",
"apihelp-query+search-param-limit": "How many total pages to return.",
"apihelp-query+search-param-interwiki": "Include interwiki results in the search, if available.",
"apihelp-query+search-param-backend": "Which search backend to use, if not the default.",
"apihelp-query+userinfo-paramvalue-prop-rights": "Lists all the rights the current user has.",
"apihelp-query+userinfo-paramvalue-prop-changeablegroups": "Lists the groups the current user can add to and remove from.",
"apihelp-query+userinfo-paramvalue-prop-options": "Lists all preferences the current user has set.",
- "apihelp-query+userinfo-paramvalue-prop-preferencestoken": "<span class=\"apihelp-deprecated\">Deprecated.</span> Get a token to change current user's preferences.",
+ "apihelp-query+userinfo-paramvalue-prop-preferencestoken": "Get a token to change current user's preferences.",
"apihelp-query+userinfo-paramvalue-prop-editcount": "Adds the current user's edit count.",
"apihelp-query+userinfo-paramvalue-prop-ratelimits": "Lists all rate limits applying to the current user.",
"apihelp-query+userinfo-paramvalue-prop-realname": "Adds the user's real name.",
/* Leave at least enough space for icon, indicator, and a sliver of text */
min-width: 6em;
}
+
+.apihelp-deprecated {
+ font-weight: bold;
+ color: #f00;
+}
+
+.apihelp-deprecated-value .oo-ui-labelElement-label {
+ text-decoration: line-through;
+}
this.setIcon( ok ? null : 'alert' );
this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() );
return $.Deferred().resolve( ok ).promise();
+ },
+ createItemWidget: function ( data, label ) {
+ var item = OO.ui.CapsuleMultiselectWidget.prototype.createItemWidget.call( this, data, label );
+ if ( this.paramInfo.deprecatedvalues &&
+ this.paramInfo.deprecatedvalues.indexOf( data ) >= 0
+ ) {
+ item.$element.addClass( 'apihelp-deprecated-value' );
+ }
+ return item;
}
},
}
items = $.map( pi.type, function ( v ) {
- return new OO.ui.MenuOptionWidget( { data: String( v ), label: String( v ) } );
+ var config = {
+ data: String( v ),
+ label: String( v ),
+ classes: []
+ };
+ if ( pi.deprecatedvalues && pi.deprecatedvalues.indexOf( v ) >= 0 ) {
+ config.classes.push( 'apihelp-deprecated-value' );
+ }
+ return new OO.ui.MenuOptionWidget( config );
} );
if ( Util.apiBool( pi.multi ) ) {
if ( pi.allspecifier !== undefined ) {
$.extend( widget, WidgetMethods.dropdownWidget );
if ( Util.apiBool( pi.submodules ) ) {
widget.getSubmodules = WidgetMethods.submoduleWidget.single;
- widget.getMenu().on( 'choose', ApiSandbox.updateUI );
+ widget.getMenu().on( 'select', ApiSandbox.updateUI );
+ }
+ if ( pi.deprecatedvalues ) {
+ widget.getMenu().on( 'select', function ( item ) {
+ this.$element.toggleClass(
+ 'apihelp-deprecated-value',
+ pi.deprecatedvalues.indexOf( item.data ) >= 0
+ );
+ }, [], widget );
}
}
menu: { items: [] },
$overlay: $( '#mw-apisandbox-ui' )
} );
- formatDropdown.getMenu().on( 'choose', Util.onFormatDropdownChange );
+ formatDropdown.getMenu().on( 'select', Util.onFormatDropdownChange );
}
menu = formatDropdown.getMenu();
color: #f00;
}
+.apihelp-deprecated-value {
+ text-decoration: line-through;
+}
+
.apihelp-unknown {
color: #888;
}