56 parent::__construct(
'Tags' );
57 $this->changeTagsStore = $changeTagsStore;
84 private function showTagList() {
86 $out->setPageTitleMsg( $this->
msg(
'tags-title' ) );
87 $out->wrapWikiMsg(
"<div class='mw-tags-intro'>\n$1\n</div>",
'tags-intro' );
90 $userCanManage = $authority->isAllowed(
'managechangetags' );
91 $userCanDelete = $authority->isAllowed(
'deletechangetags' );
92 $userCanEditInterface = $authority->isAllowed(
'editinterface' );
95 if ( $userCanManage ) {
99 'label' => $this->
msg(
'tags-create-tag-name' )->plain(),
104 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
105 'label' => $this->
msg(
'tags-create-reason' )->plain(),
108 'IgnoreWarnings' => [
113 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
114 ->setAction( $this->
getPageTitle(
'create' )->getLocalURL() )
115 ->setWrapperLegendMsg(
'tags-create-heading' )
116 ->setHeaderHtml( $this->
msg(
'tags-create-explanation' )->parseAsBlock() )
117 ->setSubmitCallback( [ $this,
'processCreateTagForm' ] )
118 ->setSubmitTextMsg(
'tags-create-submit' )
128 if ( $out->getRedirect() !==
'' ) {
134 $tagStats = $this->changeTagsStore->tagUsageStatistics();
137 $this->explicitlyDefinedTags = array_fill_keys(
138 $this->changeTagsStore->listExplicitlyDefinedTags(),
true );
139 $this->softwareDefinedTags = array_fill_keys(
140 $this->changeTagsStore->listSoftwareDefinedTags(),
true );
143 $definedTags = array_keys( $this->explicitlyDefinedTags + $this->softwareDefinedTags );
146 if ( !$tagStats && !$definedTags ) {
151 $thead = Xml::tags(
'tr',
null, Xml::tags(
'th',
null, $this->
msg(
'tags-tag' )->parse() ) .
152 Xml::tags(
'th',
null, $this->
msg(
'tags-display-header' )->parse() ) .
153 Xml::tags(
'th',
null, $this->
msg(
'tags-description-header' )->parse() ) .
154 Xml::tags(
'th',
null, $this->
msg(
'tags-source-header' )->parse() ) .
155 Xml::tags(
'th',
null, $this->
msg(
'tags-active-header' )->parse() ) .
156 Xml::tags(
'th',
null, $this->
msg(
'tags-hitcount-header' )->parse() ) .
157 ( ( $userCanManage || $userCanDelete ) ?
158 Xml::tags(
'th', [
'class' =>
'unsortable' ],
159 $this->
msg(
'tags-actions-header' )->parse() ) :
165 $this->softwareActivatedTags = array_fill_keys(
166 $this->changeTagsStore->listSoftwareActivatedTags(),
true );
169 foreach ( $tagStats as $tag => $hitcount ) {
170 $tbody .= $this->doTagRow( $tag, $hitcount, $userCanManage,
171 $userCanDelete, $userCanEditInterface );
174 foreach ( $definedTags as $tag ) {
175 if ( !isset( $tagStats[$tag] ) ) {
176 $tbody .= $this->doTagRow( $tag, 0, $userCanManage, $userCanDelete, $userCanEditInterface );
180 $out->addModuleStyles( [
181 'jquery.tablesorter.styles',
182 'mediawiki.pager.styles'
184 $out->addModules(
'jquery.tablesorter' );
185 $out->addHTML( Xml::tags(
187 [
'class' =>
'mw-datatable sortable mw-tags-table' ],
188 Xml::tags(
'thead',
null, $thead ) .
189 Xml::tags(
'tbody',
null, $tbody )
193 private function doTagRow(
194 $tag, $hitcount, $showManageActions, $showDeleteActions, $showEditLinks
197 $newRow .= Xml::tags(
'td',
null,
Xml::element(
'code',
null, $tag ) );
201 if ( $disp ===
false ) {
202 $disp =
Xml::element(
'em',
null, $this->
msg(
'tags-hidden' )->text() );
204 if ( $showEditLinks ) {
206 $editLink = $linkRenderer->makeLink(
208 $this->
msg(
'tags-edit' )->text(),
210 [
'action' =>
'edit' ]
212 $helpEditLink = $linkRenderer->makeLink(
213 $this->
msg(
"tag-$tag-helppage" )->inContentLanguage()->
getTitle(),
214 $this->
msg(
'tags-helppage-edit' )->text(),
216 [
'action' =>
'edit' ]
218 $disp .= $this->
msg(
'parentheses' )->rawParams(
219 $this->
getLanguage()->pipeList( [ $editLink, $helpEditLink ] )
222 $newRow .= Xml::tags(
'td',
null, $disp );
224 $msg = $this->
msg(
"tag-$tag-description" );
225 $desc = !$msg->exists() ?
'' : $msg->parse();
226 if ( $showEditLinks ) {
228 $editDescLink = $linkRenderer->makeLink(
229 $this->
msg(
"tag-$tag-description" )->inContentLanguage()->
getTitle(),
230 $this->
msg(
'tags-edit' )->text(),
232 [
'action' =>
'edit' ]
234 $desc .= $this->
msg(
'parentheses' )->rawParams( $editDescLink )->escaped();
236 $newRow .= Xml::tags(
'td',
null, $desc );
239 $isSoftware = isset( $this->softwareDefinedTags[$tag] );
240 $isExplicit = isset( $this->explicitlyDefinedTags[$tag] );
243 $sourceMsgs[] = $this->
msg(
'tags-source-extension' )->escaped();
246 $sourceMsgs[] = $this->
msg(
'tags-source-manual' )->escaped();
248 if ( !$sourceMsgs ) {
249 $sourceMsgs[] = $this->
msg(
'tags-source-none' )->escaped();
251 $newRow .= Xml::tags(
'td',
null, implode(
Xml::element(
'br' ), $sourceMsgs ) );
253 $isActive = $isExplicit || isset( $this->softwareActivatedTags[$tag] );
254 $activeMsg = ( $isActive ?
'tags-active-yes' :
'tags-active-no' );
255 $newRow .= Xml::tags(
'td',
null, $this->
msg( $activeMsg )->escaped() );
257 $hitcountLabelMsg = $this->
msg(
'tags-hitcount' )->numParams( $hitcount );
259 $hitcountLabel = $linkRenderer->makeLink(
261 $hitcountLabelMsg->text(),
263 [
'tagfilter' => $tag ]
266 $hitcountLabel = $hitcountLabelMsg->escaped();
270 $newRow .= Xml::tags(
'td', [
'data-sort-value' => $hitcount ], $hitcountLabel );
275 $actionLinks[] = $linkRenderer->makeKnownLink(
277 $this->
msg(
'tags-delete' )->text(),
282 if ( $showManageActions ) {
284 $actionLinks[] = $linkRenderer->makeKnownLink(
286 $this->
msg(
'tags-activate' )->text(),
292 $actionLinks[] = $linkRenderer->makeKnownLink(
294 $this->
msg(
'tags-deactivate' )->text(),
300 if ( $showDeleteActions || $showManageActions ) {
301 $newRow .= Xml::tags(
'td',
null, $this->
getLanguage()->pipeList( $actionLinks ) );
304 return Xml::tags(
'tr',
null, $newRow ) .
"\n";
309 $out = $context->getOutput();
311 $tag = trim( strval( $data[
'Tag'] ) );
312 $ignoreWarnings = isset( $data[
'IgnoreWarnings'] ) && $data[
'IgnoreWarnings'] ===
'1';
314 $context->getAuthority(), $ignoreWarnings );
316 if ( $status->isGood() ) {
319 } elseif ( $status->isOK() ) {
323 'IgnoreWarnings' => [
329 $headerText = $this->
msg(
'tags-create-warnings-above', $tag,
330 count( $status->getMessages(
'warning' ) ) )->parseAsBlock() .
331 $out->parseAsInterface( $status->getWikiText() ) .
332 $this->
msg(
'tags-create-warnings-below' )->parseAsBlock();
335 ->setSubmitTextMsg(
'htmlform-yes' );
340 $out->wrapWikiTextAsInterface(
'error', $status->getWikiText() );
347 if ( !$authority->isAllowed(
'deletechangetags' ) ) {
352 $out->setPageTitleMsg( $this->
msg(
'tags-delete-title' ) );
357 if ( !$canDeleteResult->isGood() ) {
358 $out->wrapWikiTextAsInterface(
'error', $canDeleteResult->getWikiText() );
359 if ( !$canDeleteResult->isOK() ) {
364 $preText = $this->
msg(
'tags-delete-explanation-initial', $tag )->parseAsBlock();
365 $tagUsage = $this->changeTagsStore->tagUsageStatistics();
366 if ( isset( $tagUsage[$tag] ) && $tagUsage[$tag] > 0 ) {
367 $preText .= $this->
msg(
'tags-delete-explanation-in-use', $tag,
368 $tagUsage[$tag] )->parseAsBlock();
370 $preText .= $this->
msg(
'tags-delete-explanation-warning', $tag )->parseAsBlock();
373 $this->softwareActivatedTags = array_fill_keys(
374 $this->changeTagsStore->listSoftwareActivatedTags(),
true );
375 if ( isset( $this->softwareActivatedTags[$tag] ) ) {
376 $preText .= $this->
msg(
'tags-delete-explanation-active', $tag )->parseAsBlock();
380 $fields[
'Reason'] = [
382 'label' => $this->
msg(
'tags-delete-reason' )->plain(),
385 $fields[
'HiddenTag'] = [
392 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
393 ->setAction( $this->
getPageTitle(
'delete' )->getLocalURL() )
394 ->setSubmitCallback(
function ( $data, $form ) {
397 ->setSubmitTextMsg(
'tags-delete-submit' )
398 ->setSubmitDestructive()
399 ->addPreHtml( $preText )
404 $actionStr = $activate ?
'activate' :
'deactivate';
407 if ( !$authority->isAllowed(
'managechangetags' ) ) {
413 $out->setPageTitleMsg( $this->
msg(
"tags-$actionStr-title" ) );
422 if ( !$result->isGood() ) {
423 $out->wrapWikiTextAsInterface(
'error', $result->getWikiText() );
424 if ( !$result->isOK() ) {
430 $preText = $this->
msg(
"tags-$actionStr-question", $tag )->parseAsBlock();
434 $fields[
'Reason'] = [
436 'label' => $this->
msg(
"tags-$actionStr-reason" )->plain(),
439 $fields[
'HiddenTag'] = [
446 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
447 ->setAction( $this->
getPageTitle( $actionStr )->getLocalURL() )
448 ->setSubmitCallback(
function ( $data, $form ) use ( $actionStr ) {
452 ->setSubmitTextMsg(
"tags-$actionStr-submit" )
453 ->addPreHtml( $preText )
465 $out = $context->getOutput();
467 $tag = $data[
'HiddenTag'];
469 $status = call_user_func( [ ChangeTags::class,
"{$action}TagWithChecks" ],
470 $tag, $data[
'Reason'], $context->getUser(),
true );
472 if ( $status->isGood() ) {
475 } elseif ( $status->isOK() && $action ===
'delete' ) {
477 $out->addWikiTextAsInterface( $this->
msg(
'tags-delete-warnings-after-delete', $tag,
478 count( $status->getMessages(
'warning' ) ) )->text() .
"\n" .
479 $status->getWikitext() );
483 $out->wrapWikiTextAsInterface(
'error', $status->getWikitext() );
512class_alias( SpecialTags::class,
'SpecialTags' );
getContext()
Get the base IContextSource object.
A class containing constants representing the names of configuration variables.
const UseTagFilter
Name constant for the UseTagFilter setting, for use with Config::get()
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
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,...
getPageTitle( $subpage=false)
Get a self-referential title object.
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Show an error when a user tries to do something they do not have the necessary permissions for.