21use OOUI\ComboBoxInputWidget;
41 private const int TAG_DESC_CHARACTER_LIMIT = 120;
49 $this->options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
71 if ( $tags ===
'' || $tags === null ) {
77 $tags = explode(
',', $tags );
78 $tags = $this->changeTagsStore->filterViewableTags( $tags, $authority );
79 $order = array_flip( $this->changeTagsStore->listDefinedTags() );
80 usort( $tags,
static function ( $a, $b ) use ( $order ) {
81 return ( $order[ $a ] ?? INF ) <=> ( $order[ $b ] ?? INF );
85 foreach ( $tags as $tag ) {
89 $classes[] = Sanitizer::escapeClass(
"mw-tag-$tag" );
91 if ( $description ===
'' ) {
94 $displayTags[] = Html::rawElement(
96 [
'class' =>
'mw-tag-marker ' . Sanitizer::escapeClass(
"mw-tag-marker-$tag" ) ],
101 if ( !$displayTags ) {
102 return [
'', $classes ];
105 $markers = $localizer->
msg(
'tag-list-wrapper' )
106 ->numParams( count( $displayTags ) )
107 ->rawParams( implode(
' ', $displayTags ) )
109 $markers = Html::rawElement(
'span', [
'class' =>
'mw-tag-markers' ], $markers );
111 return [ $markers, $classes ];
121 $msg = $this->tagShortDescriptionMessage( $tag, $localizer );
122 $link = $this->tagHelpLink( $tag, $localizer );
123 if ( !$msg->isDisabled() && $link ) {
124 $label = $msg->parse();
126 if ( !str_contains( $label,
'<a ' ) ) {
127 return Html::rawElement(
'a', [
'href' => $link ], $label );
130 return !$msg->isDisabled() ? $msg->parse() :
'';
136 private function tagShortDescriptionMessage(
string $tag, MessageLocalizer $messageLocalizer ): Message {
137 $msg = $messageLocalizer->msg(
"tag-$tag" );
138 if ( !$msg->exists() ) {
142 return $messageLocalizer->msg(
new RawMessage(
'$1', [ Message::plaintextParam( $tag ) ] ) );
151 private function tagHelpLink(
string $tag, MessageLocalizer $context ): ?string {
152 $msg = $context->
msg(
"tag-$tag-helppage" )->inContentLanguage();
153 if ( !$msg->isDisabled() ) {
154 return Skin::makeInternalOrExternalUrl( $msg->text() ) ?:
null;
181 bool $activeOnly =
true,
182 bool $useAllTags =
true
186 !count( $this->changeTagsStore->listDefinedTags() )
191 $tags = $this->getChangeTagList(
193 $context->getAuthority(),
200 foreach ( $tags as $tagInfo ) {
201 $autocomplete[ $tagInfo[
'label'] ] = $tagInfo[
'name'];
205 $data[0] = Html::rawElement(
207 [
'for' =>
'tagfilter' ],
208 $context->msg(
'tag-filter' )->parse()
211 if ( $format ===
'ooui' ) {
212 $options = Html::listDropdownOptionsOoui( $autocomplete );
214 $data[1] =
new ComboBoxInputWidget( [
216 'name' =>
'tagfilter',
217 'value' => $selected,
218 'classes' =>
'mw-tagfilter-input',
219 'options' => $options,
223 foreach ( $autocomplete as $label => $name ) {
224 $optionsHtml .= Html::element(
'option', [
'value' => $name ], $label );
226 $datalistHtml = Html::rawElement(
'datalist', [
'id' =>
'tagfilter-datalist' ], $optionsHtml );
228 $data[1] = Html::input(
233 'class' => [
'mw-tagfilter-input',
'cdx-text-input__input' => $format ===
'codex' ],
236 'list' =>
'tagfilter-datalist',
239 if ( $format ===
'codex' ) {
240 $data[1] = Html::rawElement(
'div', [
'class' =>
'cdx-text-input' ], $data[1] );
242 $data[1] .= $datalistHtml;
281 bool $activeOnly =
true,
282 bool $useAllTags =
true
285 $tagKeys = $this->changeTagsStore->listDefinedTags();
286 $cacheKey =
'tags-list-summary';
288 $tagKeys = $this->changeTagsStore->getCoreDefinedTags();
289 $cacheKey =
'core-software-tags-summary';
293 $tagHitCounts =
null;
295 $tagHitCounts = $this->changeTagsStore->tagUsageStatistics();
301 $summary = $this->cache->getWithSetCallback(
302 $this->cache->makeKey( $cacheKey, strtolower( $localizationContext->
getLanguageCode()->toBcp47Code() ) ),
303 WANObjectCache::TTL_DAY,
304 function () use ( $localizationContext, $tagKeys, $tagHitCounts ) {
306 foreach ( $tagKeys as $tagName ) {
308 if ( $tagHitCounts !==
null ) {
310 $hits = $tagHitCounts[$tagName] ?? 0;
316 $labelMsg = $this->tagShortDescriptionMessage( $tagName, $localizationContext );
317 $helpLink = $this->tagHelpLink( $tagName, $localizationContext );
318 $descriptionMsg = $localizationContext->
msg(
"tag-$tagName-description" );
322 'labelMsg' => !$labelMsg->isDisabled(),
323 'label' => !$labelMsg->isDisabled() ? $labelMsg->plain() : $tagName,
324 'descriptionMsg' => !$descriptionMsg->isDisabled(),
325 'description' => !$descriptionMsg->isDisabled() ? $descriptionMsg->plain() :
'',
326 'helpLink' => $helpLink,
327 'cssClass' => Sanitizer::escapeClass(
'mw-tag-' . $tagName ),
336 $viewable = array_fill_keys(
337 $this->changeTagsStore->filterViewableTags( array_column( $summary,
'name' ), $authority ),
340 return array_values( array_filter(
342 static fn ( array $tagInfo ) => isset( $viewable[ $tagInfo[
'name'] ] )
367 bool $activeOnly =
true,
368 bool $useAllTags =
true,
369 bool $labelsOnly =
false
371 $tags = $this->getChangeTagListSummary( $localizationContext, $authority, $activeOnly, $useAllTags );
373 $language = $this->languageFactory->getLanguage( $localizationContext->
getLanguageCode() );
374 foreach ( $tags as &$tagInfo ) {
375 if ( $tagInfo[
'labelMsg'] ) {
379 $labelMsg =
new RawMessage( $tagInfo[
'label'] );
380 $tagInfo[
'label'] = Sanitizer::stripAllTags( $localizationContext->
msg( $labelMsg )->parse() );
383 $tagInfo[
'label'] = $localizationContext->
msg(
'tag-hidden', $tagInfo[
'name'] )->text();
387 unset( $tagInfo[
'description'] );
388 } elseif ( $tagInfo[
'descriptionMsg'] ) {
390 if (
wfEscapeWikiText( $tagInfo[
'description'] ) !== $tagInfo[
'description'] ) {
391 $descriptionMsg =
new RawMessage( $tagInfo[
'description'] );
392 $tagInfo[
'description'] = Sanitizer::stripAllTags(
393 $localizationContext->
msg( $descriptionMsg )->parse()
396 $tagInfo[
'description'] = $language->truncateForVisual( $tagInfo[
'description'],
397 self::TAG_DESC_CHARACTER_LIMIT );
399 unset( $tagInfo[
'labelMsg'] );
400 unset( $tagInfo[
'descriptionMsg'] );
404 usort( $tags,
static function ( $a, $b ) {
405 return strcasecmp( $a[
'label'], $b[
'label'] );
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
if(!defined('MW_SETUP_CALLBACK'))
A class containing constants representing the names of configuration variables.
const UseTagFilter
Name constant for the UseTagFilter setting, for use with Config::get()
Interface for objects which can provide a MediaWiki context on request.
Interface supporting message localization in MediaWiki.
getLanguageCode()
Returns the target language for UI localization.