Highlight internal modules in API help and sandbox

This mostly mirrors the existing handling for deprecated modules. In
lists, internal modules are ordered after deprecated ones, with
deprecated internal modules at the very end.

action=paraminfo gains an array of internalvalues analogous to
deprecatedvalues. Help messages for internal modules are prefixed with
the text “Internal”. The help page and API sandbox styles color internal
values in red, just like deprecated values (and matching the existing
style for the “this module is internal or unstable” warning in the help
page), but do not add a strikethrough.

Bug: T185508
Change-Id: I5dfc3bacbc070d74f467eb1a4042cab159aa28ec
This commit is contained in:
Lucas Werkmeister 2019-10-10 17:51:57 +02:00
parent b02b2704b9
commit 3983e1af46
9 changed files with 120 additions and 44 deletions

View file

@ -2413,21 +2413,20 @@ abstract class ApiBase extends ContextSource {
$map[$submoduleName] = $prefix . $submoduleName;
}
}
ksort( $map );
$submodules = [];
$deprecatedSubmodules = [];
$submoduleFlags = []; // for sorting: higher flags are sorted later
$submoduleNames = []; // for sorting: lexicographical, ascending
foreach ( $map as $v => $m ) {
$arr = &$submodules;
$isDeprecated = false;
$isInternal = false;
$summary = null;
try {
$submod = $this->getModuleFromPath( $m );
if ( $submod ) {
$summary = $submod->getFinalSummary();
$isDeprecated = $submod->isDeprecated();
if ( $isDeprecated ) {
$arr = &$deprecatedSubmodules;
}
$isInternal = $submod->isInternal();
}
} catch ( ApiUsageException $ex ) {
// Ignore
@ -2439,10 +2438,20 @@ abstract class ApiBase extends ContextSource {
$key = 'api-help-undocumented-module';
$params = [ $m ];
}
$m = new ApiHelpParamValueMessage( "[[Special:ApiHelp/$m|$v]]", $key, $params, $isDeprecated );
$arr[] = $m->setContext( $this->getContext() );
$m = new ApiHelpParamValueMessage(
"[[Special:ApiHelp/$m|$v]]",
$key,
$params,
$isDeprecated,
$isInternal
);
$submodules[] = $m->setContext( $this->getContext() );
$submoduleFlags[] = ( $isDeprecated ? 1 : 0 ) | ( $isInternal ? 2 : 0 );
$submoduleNames[] = $v;
}
$msgs[$param] = array_merge( $msgs[$param], $submodules, $deprecatedSubmodules );
// sort $submodules by $submoduleFlags and $submoduleNames
array_multisort( $submoduleFlags, $submoduleNames, $submodules );
$msgs[$param] = array_merge( $msgs[$param], $submodules );
} elseif ( isset( $settings[self::PARAM_HELP_MSG_PER_VALUE] ) ) {
if ( !is_array( $settings[self::PARAM_HELP_MSG_PER_VALUE] ) ) {
self::dieDebug( __METHOD__,

View file

@ -568,28 +568,33 @@ class ApiHelp extends ApiBase {
}
$defaultAttrs = [ 'dir' => 'ltr', 'lang' => 'en' ];
}
ksort( $map );
$submodules = [];
$deprecatedSubmodules = [];
$submoduleFlags = []; // for sorting: higher flags are sorted later
$submoduleNames = []; // for sorting: lexicographical, ascending
foreach ( $map as $v => $m ) {
$attrs = $defaultAttrs;
$arr = &$submodules;
$flags = 0;
try {
$submod = $module->getModuleFromPath( $m );
if ( $submod && $submod->isDeprecated() ) {
$arr = &$deprecatedSubmodules;
$attrs['class'] = 'apihelp-deprecated-value';
$attrs['class'][] = 'apihelp-deprecated-value';
$flags |= 1;
}
if ( $submod && $submod->isInternal() ) {
$attrs['class'][] = 'apihelp-internal-value';
$flags |= 2;
}
} catch ( ApiUsageException $ex ) {
// Ignore
}
if ( $attrs ) {
$v = Html::element( 'span', $attrs, $v );
}
$arr[] = "[[Special:ApiHelp/{$m}|{$v}]]";
$v = Html::element( 'span', $attrs, $v );
$submodules[] = "[[Special:ApiHelp/{$m}|{$v}]]";
$submoduleFlags[] = $flags;
$submoduleNames[] = $v;
}
$submodules = array_merge( $submodules, $deprecatedSubmodules );
// sort $submodules by $submoduleFlags and $submoduleNames
array_multisort( $submoduleFlags, $submoduleNames, $submodules );
$count = count( $submodules );
$info[] = $context->msg( 'api-help-param-list' )
->params( $multi ? 2 : 1 )

View file

@ -34,6 +34,7 @@ class ApiHelpParamValueMessage extends Message {
protected $paramValue;
protected $deprecated;
protected $internal;
/**
* @see Message::__construct
@ -42,13 +43,22 @@ class ApiHelpParamValueMessage extends Message {
* @param string $text Message to use.
* @param array $params Parameters for the message.
* @param bool $deprecated Whether the value is deprecated
* @param bool $internal Whether the value is internal
* @throws InvalidArgumentException
* @since 1.30 Added the `$deprecated` parameter
* @since 1.35 Added the `$internal` parameter
*/
public function __construct( $paramValue, $text, $params = [], $deprecated = false ) {
public function __construct(
$paramValue,
$text,
$params = [],
$deprecated = false,
$internal = false
) {
parent::__construct( $text, $params );
$this->paramValue = $paramValue;
$this->deprecated = (bool)$deprecated;
$this->internal = (bool)$internal;
}
/**
@ -68,25 +78,47 @@ class ApiHelpParamValueMessage extends Message {
return $this->deprecated;
}
/**
* Fetch the 'internal' flag
* @since 1.35
* @return bool
*/
public function isInternal() {
return $this->internal;
}
/**
* Fetch the message.
* @return string
*/
public function fetchMessage() {
if ( $this->message === null ) {
$dep = '';
$prefix = '';
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> ';
$prefix .= '<span class="apihelp-deprecated">' .
$this->subMessage( 'api-help-param-deprecated' ) .
'</span>' .
$this->subMessage( 'word-separator' );
}
if ( $this->isInternal() ) {
$prefix .= '<span class="apihelp-internal">' .
$this->subMessage( 'api-help-param-internal' ) .
'</span>' .
$this->subMessage( 'word-separator' );
}
$this->message = ";<span dir=\"ltr\" lang=\"en\">{$this->paramValue}</span>:"
. $dep . parent::fetchMessage();
. $prefix . parent::fetchMessage();
}
return $this->message;
}
private function subMessage( $key ) {
$msg = new Message( $key );
$msg->interface = $this->interface;
$msg->language = $this->language;
$msg->useDatabase = $this->useDatabase;
$msg->title = $this->title;
return $msg->fetchMessage();
}
}

View file

@ -392,12 +392,10 @@ class ApiParamInfo extends ApiBase {
if ( isset( $settings[ApiBase::PARAM_TYPE] ) ) {
if ( $settings[ApiBase::PARAM_TYPE] === 'submodule' ) {
if ( isset( $settings[ApiBase::PARAM_SUBMODULE_MAP] ) ) {
ksort( $settings[ApiBase::PARAM_SUBMODULE_MAP] );
$item['type'] = array_keys( $settings[ApiBase::PARAM_SUBMODULE_MAP] );
$item['submodules'] = $settings[ApiBase::PARAM_SUBMODULE_MAP];
} else {
$item['type'] = $module->getModuleManager()->getNames( $name );
sort( $item['type'] );
$prefix = $module->isMain()
? '' : ( $module->getModulePath() . '+' );
$item['submodules'] = [];
@ -409,23 +407,35 @@ class ApiParamInfo extends ApiBase {
$item['submoduleparamprefix'] = $settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX];
}
$deprecatedSubmodules = [];
$submoduleFlags = []; // for sorting: higher flags are sorted later
$submoduleNames = []; // for sorting: lexicographical, ascending
foreach ( $item['submodules'] as $v => $submodulePath ) {
try {
$submod = $this->getModuleFromPath( $submodulePath );
if ( $submod && $submod->isDeprecated() ) {
$deprecatedSubmodules[] = $v;
}
} catch ( ApiUsageException $ex ) {
// Ignore
$submoduleFlags[] = 0;
$submoduleNames[] = $v;
continue;
}
$flags = 0;
if ( $submod && $submod->isDeprecated() ) {
$item['deprecatedvalues'][] = $v;
$flags |= 1;
}
if ( $submod && $submod->isInternal() ) {
$item['internalvalues'][] = $v;
$flags |= 2;
}
$submoduleFlags[] = $flags;
$submoduleNames[] = $v;
}
if ( $deprecatedSubmodules ) {
$item['type'] = array_merge(
array_diff( $item['type'], $deprecatedSubmodules ),
$deprecatedSubmodules
);
$item['deprecatedvalues'] = $deprecatedSubmodules;
// sort $item['submodules'] and $item['type'] by $submoduleFlags and $submoduleNames
array_multisort( $submoduleFlags, $submoduleNames, $item['submodules'], $item['type'] );
if ( isset( $item['deprecatedvalues'] ) ) {
sort( $item['deprecatedvalues'] );
}
if ( isset( $item['internalvalues'] ) ) {
sort( $item['internalvalues'] );
}
} elseif ( $settings[ApiBase::PARAM_TYPE] === 'tags' ) {
$item['type'] = ChangeTags::listExplicitlyDefinedTags();

View file

@ -1627,6 +1627,7 @@
"api-help-help-urls": "",
"api-help-parameters": "{{PLURAL:$1|Parameter|Parameters}}:",
"api-help-param-deprecated": "Deprecated.",
"api-help-param-internal": "Internal.",
"api-help-param-required": "This parameter is required.",
"api-help-param-templated": "This is a [[Special:ApiHelp/main#main/templatedparams|templated parameter]]. When making the request, $2.",
"api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> in the parameter's name should be replaced with values of <var>$2</var>",

View file

@ -1517,6 +1517,7 @@
"api-help-help-urls": "{{ignored}} Label for the API help urls section\n\nParameters:\n* $1 - Number of urls to be displayed",
"api-help-parameters": "Label for the API help parameters section\n\nParameters:\n* $1 - Number of parameters to be displayed\n{{Identical|Parameter}}",
"api-help-param-deprecated": "Displayed in the API help for any deprecated parameter\n{{Identical|Deprecated}}",
"api-help-param-internal": "Displayed in the API help for any internal parameter",
"api-help-param-required": "Displayed in the API help for any required parameter",
"api-help-param-templated": "Displayed in the API help for any templated parameter.\n\nParameters:\n* $1 - Count of template variables in the parameter name.\n* $2 - A list, composed using {{msg-mw|comma-separator}} and {{msg-mw|and}}, of the template variables in the parameter name. The first is formatted using {{msg-mw|api-help-param-templated-var-first|notext=1}} and the rest use {{msg-mw|api-help-param-templated-var|notext=1}}.\n\nSee also:\n* {{msg-mw|api-help-param-templated-var-first}}\n* {{msg-mw|api-help-param-templated-var}}",
"api-help-param-templated-var-first": "Used with {{msg-mw|api-help-param-templated|notext=1}} to display templated parameter replacement variables. See that message for context.\n\nParameters:\n* $1 - Variable.\n* $2 - Parameter from which values are taken.\n\nSee also:\n* {{msg-mw|api-help-param-templated}}\n* {{msg-mw|api-help-param-templated-var}}",

View file

@ -36,6 +36,7 @@ div.apihelp-linktrail {
}
.apihelp-deprecated,
.apihelp-internal,
.apihelp-flag-deprecated,
.apihelp-flag-internal strong {
font-weight: bold;

View file

@ -100,13 +100,14 @@
min-width: 6em;
}
/* stylelint-disable-next-line selector-class-pattern */
.apihelp-deprecated {
/* stylelint-disable selector-class-pattern */
.apihelp-deprecated,
.apihelp-internal {
font-weight: bold;
color: #d33;
}
/* stylelint-disable-next-line selector-class-pattern */
.apihelp-deprecated-value .oo-ui-labelElement-label {
text-decoration: line-through;
}
/* stylelint-enable selector-class-pattern */

View file

@ -243,6 +243,11 @@
) {
item.$element.addClass( 'apihelp-deprecated-value' );
}
if ( this.paramInfo.internalvalues &&
this.paramInfo.internalvalues.indexOf( data ) >= 0
) {
item.$element.addClass( 'apihelp-internal-value' );
}
return item;
}
},
@ -571,6 +576,9 @@
if ( pi.deprecatedvalues && pi.deprecatedvalues.indexOf( v ) >= 0 ) {
config.classes.push( 'apihelp-deprecated-value' );
}
if ( pi.internalvalues && pi.internalvalues.indexOf( v ) >= 0 ) {
config.classes.push( 'apihelp-internal-value' );
}
return new OO.ui.MenuOptionWidget( config );
} );
if ( Util.apiBool( pi.multi ) ) {
@ -610,6 +618,14 @@
);
}, [], widget );
}
if ( pi.internalvalues ) {
widget.getMenu().on( 'select', function ( item ) {
this.$element.toggleClass(
'apihelp-internal-value',
pi.internalvalues.indexOf( item.data ) >= 0
);
}, [], widget );
}
}
break;