49 parent::__construct(
'Tags' );
78 $out->setPageTitle( $this->
msg(
'tags-title' ) );
79 $out->wrapWikiMsg(
"<div class='mw-tags-intro'>\n$1\n</div>",
'tags-intro' );
82 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
83 $userCanManage = $permissionManager->userHasRight( $user,
'managechangetags' );
84 $userCanDelete = $permissionManager->userHasRight( $user,
'deletechangetags' );
85 $userCanEditInterface = $permissionManager->userHasRight( $user,
'editinterface' );
88 if ( $userCanManage ) {
92 'label' => $this->
msg(
'tags-create-tag-name' )->plain(),
97 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
98 'label' => $this->
msg(
'tags-create-reason' )->plain(),
101 'IgnoreWarnings' => [
106 $form = HTMLForm::factory(
'ooui', $fields, $this->
getContext() );
107 $form->setAction( $this->
getPageTitle(
'create' )->getLocalURL() );
108 $form->setWrapperLegendMsg(
'tags-create-heading' );
109 $form->setHeaderText( $this->
msg(
'tags-create-explanation' )->parseAsBlock() );
110 $form->setSubmitCallback( [ $this,
'processCreateTagForm' ] );
111 $form->setSubmitTextMsg(
'tags-create-submit' );
121 if ( $out->getRedirect() !==
'' ) {
130 $this->explicitlyDefinedTags = array_fill_keys(
132 $this->softwareDefinedTags = array_fill_keys(
136 $definedTags = array_keys( $this->explicitlyDefinedTags + $this->softwareDefinedTags );
139 if ( !$tagStats && !$definedTags ) {
144 $thead = Xml::tags(
'tr',
null, Xml::tags(
'th',
null, $this->
msg(
'tags-tag' )->parse() ) .
145 Xml::tags(
'th',
null, $this->
msg(
'tags-display-header' )->parse() ) .
146 Xml::tags(
'th',
null, $this->
msg(
'tags-description-header' )->parse() ) .
147 Xml::tags(
'th',
null, $this->
msg(
'tags-source-header' )->parse() ) .
148 Xml::tags(
'th',
null, $this->
msg(
'tags-active-header' )->parse() ) .
149 Xml::tags(
'th',
null, $this->
msg(
'tags-hitcount-header' )->parse() ) .
150 ( ( $userCanManage || $userCanDelete ) ?
151 Xml::tags(
'th', [
'class' =>
'unsortable' ],
152 $this->
msg(
'tags-actions-header' )->parse() ) :
158 $this->softwareActivatedTags = array_fill_keys(
162 foreach ( $tagStats as $tag => $hitcount ) {
163 $tbody .= $this->
doTagRow( $tag, $hitcount, $userCanManage,
164 $userCanDelete, $userCanEditInterface );
167 foreach ( $definedTags as $tag ) {
168 if ( !isset( $tagStats[$tag] ) ) {
169 $tbody .= $this->
doTagRow( $tag, 0, $userCanManage, $userCanDelete, $userCanEditInterface );
173 $out->addModuleStyles(
'jquery.tablesorter.styles' );
174 $out->addModules(
'jquery.tablesorter' );
175 $out->addHTML( Xml::tags(
177 [
'class' =>
'mw-datatable sortable mw-tags-table' ],
178 Xml::tags(
'thead',
null, $thead ) .
179 Xml::tags(
'tbody',
null, $tbody )
184 $tag, $hitcount, $showManageActions, $showDeleteActions, $showEditLinks
187 $newRow .= Xml::tags(
'td',
null, Xml::element(
'code',
null, $tag ) );
191 if ( $showEditLinks ) {
194 $this->
msg(
"tag-$tag" )->inContentLanguage()->
getTitle(),
195 $this->
msg(
'tags-edit' )->text(),
197 [
'action' =>
'edit' ]
199 $disp .= $this->
msg(
'parentheses' )->rawParams( $editLink )->escaped();
201 $newRow .= Xml::tags(
'td',
null, $disp );
203 $msg = $this->
msg(
"tag-$tag-description" );
204 $desc = !$msg->exists() ?
'' : $msg->parse();
205 if ( $showEditLinks ) {
208 $this->
msg(
"tag-$tag-description" )->inContentLanguage()->
getTitle(),
209 $this->
msg(
'tags-edit' )->text(),
211 [
'action' =>
'edit' ]
213 $desc .= $this->
msg(
'parentheses' )->rawParams( $editDescLink )->escaped();
215 $newRow .= Xml::tags(
'td',
null, $desc );
218 $isSoftware = isset( $this->softwareDefinedTags[$tag] );
219 $isExplicit = isset( $this->explicitlyDefinedTags[$tag] );
222 $sourceMsgs[] = $this->
msg(
'tags-source-extension' )->escaped();
225 $sourceMsgs[] = $this->
msg(
'tags-source-manual' )->escaped();
227 if ( !$sourceMsgs ) {
228 $sourceMsgs[] = $this->
msg(
'tags-source-none' )->escaped();
230 $newRow .= Xml::tags(
'td',
null, implode( Xml::element(
'br' ), $sourceMsgs ) );
232 $isActive = $isExplicit || isset( $this->softwareActivatedTags[$tag] );
233 $activeMsg = ( $isActive ?
'tags-active-yes' :
'tags-active-no' );
234 $newRow .= Xml::tags(
'td',
null, $this->
msg( $activeMsg )->escaped() );
236 $hitcountLabelMsg = $this->
msg(
'tags-hitcount' )->numParams( $hitcount );
237 if ( $this->
getConfig()->
get(
'UseTagFilter' ) ) {
240 $hitcountLabelMsg->text(),
242 [
'tagfilter' => $tag ]
245 $hitcountLabel = $hitcountLabelMsg->escaped();
249 $newRow .= Xml::tags(
'td', [
'data-sort-value' => $hitcount ], $hitcountLabel );
256 $this->
msg(
'tags-delete' )->text(),
261 if ( $showManageActions ) {
265 $this->
msg(
'tags-activate' )->text(),
273 $this->
msg(
'tags-deactivate' )->text(),
279 if ( $showDeleteActions || $showManageActions ) {
280 $newRow .= Xml::tags(
'td',
null, $this->
getLanguage()->pipeList( $actionLinks ) );
283 return Xml::tags(
'tr',
null, $newRow ) .
"\n";
288 $out = $context->getOutput();
290 $tag = trim( strval( $data[
'Tag'] ) );
291 $ignoreWarnings = isset( $data[
'IgnoreWarnings'] ) && $data[
'IgnoreWarnings'] ===
'1';
293 $context->getUser(), $ignoreWarnings );
295 if ( $status->isGood() ) {
298 } elseif ( $status->isOK() ) {
303 'default' => $data[
'Tag'],
307 'default' => $data[
'Reason'],
309 'IgnoreWarnings' => [
317 $context->getRequest()->unsetVal(
'wpEditToken' );
319 $headerText = $this->
msg(
'tags-create-warnings-above', $tag,
320 count( $status->getWarningsArray() ) )->parseAsBlock() .
321 $out->parseAsInterface( $status->getWikiText() ) .
322 $this->
msg(
'tags-create-warnings-below' )->parseAsBlock();
324 $subform = HTMLForm::factory(
'ooui', $fields, $this->
getContext() );
325 $subform->setAction( $this->
getPageTitle(
'create' )->getLocalURL() );
326 $subform->setWrapperLegendMsg(
'tags-create-heading' );
327 $subform->setHeaderText( $headerText );
328 $subform->setSubmitCallback( [ $this,
'processCreateTagForm' ] );
329 $subform->setSubmitTextMsg(
'htmlform-yes' );
335 $out->wrapWikiTextAsInterface(
'error', $status->getWikiText() );
342 if ( !MediaWikiServices::getInstance()
344 ->userHasRight( $user,
'deletechangetags' ) ) {
349 $out->setPageTitle( $this->
msg(
'tags-delete-title' ) );
354 if ( !$canDeleteResult->isGood() ) {
355 $out->wrapWikiTextAsInterface(
'error', $canDeleteResult->getWikiText() );
356 if ( !$canDeleteResult->isOK() ) {
361 $preText = $this->
msg(
'tags-delete-explanation-initial', $tag )->parseAsBlock();
363 if ( isset( $tagUsage[$tag] ) && $tagUsage[$tag] > 0 ) {
364 $preText .= $this->
msg(
'tags-delete-explanation-in-use', $tag,
365 $tagUsage[$tag] )->parseAsBlock();
367 $preText .= $this->
msg(
'tags-delete-explanation-warning', $tag )->parseAsBlock();
370 $this->softwareActivatedTags = array_fill_keys(
372 if ( isset( $this->softwareActivatedTags[$tag] ) ) {
373 $preText .= $this->
msg(
'tags-delete-explanation-active', $tag )->parseAsBlock();
377 $fields[
'Reason'] = [
379 'label' => $this->
msg(
'tags-delete-reason' )->plain(),
382 $fields[
'HiddenTag'] = [
389 $form = HTMLForm::factory(
'ooui', $fields, $this->
getContext() );
390 $form->setAction( $this->
getPageTitle(
'delete' )->getLocalURL() );
392 $form->tagAction =
'delete';
393 $form->setSubmitCallback( [ $this,
'processTagForm' ] );
394 $form->setSubmitTextMsg(
'tags-delete-submit' );
395 $form->setSubmitDestructive();
396 $form->addPreText( $preText );
401 $actionStr = $activate ?
'activate' :
'deactivate';
404 if ( !MediaWikiServices::getInstance()
406 ->userHasRight( $user,
'managechangetags' ) ) {
412 $out->setPageTitle( $this->
msg(
"tags-$actionStr-title" ) );
416 $func = $activate ?
'canActivateTag' :
'canDeactivateTag';
417 $result = ChangeTags::$func( $tag, $user );
418 if ( !$result->isGood() ) {
419 $out->wrapWikiTextAsInterface(
'error', $result->getWikiText() );
420 if ( !$result->isOK() ) {
426 $preText = $this->
msg(
"tags-$actionStr-question", $tag )->parseAsBlock();
430 $fields[
'Reason'] = [
432 'label' => $this->
msg(
"tags-$actionStr-reason" )->plain(),
435 $fields[
'HiddenTag'] = [
442 $form = HTMLForm::factory(
'ooui', $fields, $this->
getContext() );
443 $form->setAction( $this->
getPageTitle( $actionStr )->getLocalURL() );
445 $form->tagAction = $actionStr;
446 $form->setSubmitCallback( [ $this,
'processTagForm' ] );
448 $form->setSubmitTextMsg(
"tags-$actionStr-submit" );
449 $form->addPreText( $preText );
461 $out = $context->getOutput();
463 $tag = $data[
'HiddenTag'];
464 $status = call_user_func( [ ChangeTags::class,
"{$form->tagAction}TagWithChecks" ],
465 $tag, $data[
'Reason'], $context->getUser(),
true );
467 if ( $status->isGood() ) {
470 } elseif ( $status->isOK() && $form->tagAction ===
'delete' ) {
472 $out->addWikiTextAsInterface( $this->
msg(
'tags-delete-warnings-after-delete', $tag,
473 count( $status->getWarningsArray() ) )->text() .
"\n" .
474 $status->getWikitext() );
478 $out->wrapWikiTextAsInterface(
'error', $status->getWikitext() );
getContext()
Get the base IContextSource object.
Show an error when a user tries to do something they do not have the necessary permissions for.
Parent class for all special pages.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!...
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
MediaWiki Linker LinkRenderer null $linkRenderer