59 parent::__construct(
'Tags' );
60 $this->changeTagsStore = $changeTagsStore;
87 private function showTagList() {
89 $out->setPageTitleMsg( $this->
msg(
'tags-title' ) );
90 $out->wrapWikiMsg(
"<div class='mw-tags-intro'>\n$1\n</div>",
'tags-intro' );
93 $userCanManage = $authority->isAllowed(
'managechangetags' );
94 $userCanDelete = $authority->isAllowed(
'deletechangetags' );
95 $userCanEditInterface = $authority->isAllowed(
'editinterface' );
98 if ( $userCanManage ) {
102 'label' => $this->
msg(
'tags-create-tag-name' )->plain(),
107 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
108 'label' => $this->
msg(
'tags-create-reason' )->plain(),
111 'IgnoreWarnings' => [
116 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
117 ->setAction( $this->
getPageTitle(
'create' )->getLocalURL() )
118 ->setWrapperLegendMsg(
'tags-create-heading' )
119 ->setHeaderHtml( $this->
msg(
'tags-create-explanation' )->parseAsBlock() )
120 ->setSubmitCallback( [ $this,
'processCreateTagForm' ] )
121 ->setSubmitTextMsg(
'tags-create-submit' )
131 if ( $out->getRedirect() !==
'' ) {
137 $tagStats = $this->changeTagsStore->tagUsageStatistics();
140 $this->explicitlyDefinedTags = array_fill_keys(
141 $this->changeTagsStore->listExplicitlyDefinedTags(),
true );
142 $this->softwareDefinedTags = array_fill_keys(
143 $this->changeTagsStore->listSoftwareDefinedTags(),
true );
146 $definedTags = array_keys( $this->explicitlyDefinedTags + $this->softwareDefinedTags );
149 if ( !$tagStats && !$definedTags ) {
154 $thead =
Xml::tags(
'tr',
null, Xml::tags(
'th',
null, $this->
msg(
'tags-tag' )->parse() ) .
155 Xml::tags(
'th',
null, $this->
msg(
'tags-display-header' )->parse() ) .
156 Xml::tags(
'th',
null, $this->
msg(
'tags-description-header' )->parse() ) .
157 Xml::tags(
'th',
null, $this->
msg(
'tags-source-header' )->parse() ) .
158 Xml::tags(
'th',
null, $this->
msg(
'tags-active-header' )->parse() ) .
159 Xml::tags(
'th',
null, $this->
msg(
'tags-hitcount-header' )->parse() ) .
160 ( ( $userCanManage || $userCanDelete ) ?
161 Xml::tags(
'th', [
'class' =>
'unsortable' ],
162 $this->
msg(
'tags-actions-header' )->parse() ) :
168 $this->softwareActivatedTags = array_fill_keys(
169 $this->changeTagsStore->listSoftwareActivatedTags(),
true );
172 foreach ( $tagStats as $tag => $hitcount ) {
173 $tbody .= $this->doTagRow( $tag, $hitcount, $userCanManage,
174 $userCanDelete, $userCanEditInterface );
177 foreach ( $definedTags as $tag ) {
178 if ( !isset( $tagStats[$tag] ) ) {
179 $tbody .= $this->doTagRow( $tag, 0, $userCanManage, $userCanDelete, $userCanEditInterface );
183 $out->addModuleStyles( [
184 'jquery.tablesorter.styles',
185 'mediawiki.pager.styles'
187 $out->addModules(
'jquery.tablesorter' );
188 $out->addHTML( Xml::tags(
190 [
'class' =>
'mw-datatable sortable mw-tags-table' ],
191 Xml::tags(
'thead',
null, $thead ) .
192 Xml::tags(
'tbody',
null, $tbody )
196 private function doTagRow(
197 $tag, $hitcount, $showManageActions, $showDeleteActions, $showEditLinks
200 $newRow .=
Xml::tags(
'td',
null, Xml::element(
'code',
null, $tag ) );
204 if ( $disp ===
false ) {
205 $disp =
Xml::element(
'em',
null, $this->
msg(
'tags-hidden' )->text() );
207 if ( $showEditLinks ) {
209 $editLink = $linkRenderer->makeLink(
210 $this->
msg(
"tag-$tag" )->inContentLanguage()->
getTitle(),
211 $this->
msg(
'tags-edit' )->text(),
213 [
'action' =>
'edit' ]
215 $disp .= $this->
msg(
'parentheses' )->rawParams( $editLink )->escaped();
217 $newRow .=
Xml::tags(
'td',
null, $disp );
219 $msg = $this->
msg(
"tag-$tag-description" );
220 $desc = !$msg->exists() ?
'' : $msg->parse();
221 if ( $showEditLinks ) {
223 $editDescLink = $linkRenderer->makeLink(
224 $this->
msg(
"tag-$tag-description" )->inContentLanguage()->
getTitle(),
225 $this->
msg(
'tags-edit' )->text(),
227 [
'action' =>
'edit' ]
229 $desc .= $this->
msg(
'parentheses' )->rawParams( $editDescLink )->escaped();
231 $newRow .=
Xml::tags(
'td',
null, $desc );
234 $isSoftware = isset( $this->softwareDefinedTags[$tag] );
235 $isExplicit = isset( $this->explicitlyDefinedTags[$tag] );
238 $sourceMsgs[] = $this->
msg(
'tags-source-extension' )->escaped();
241 $sourceMsgs[] = $this->
msg(
'tags-source-manual' )->escaped();
243 if ( !$sourceMsgs ) {
244 $sourceMsgs[] = $this->
msg(
'tags-source-none' )->escaped();
246 $newRow .=
Xml::tags(
'td',
null, implode( Xml::element(
'br' ), $sourceMsgs ) );
248 $isActive = $isExplicit || isset( $this->softwareActivatedTags[$tag] );
249 $activeMsg = ( $isActive ?
'tags-active-yes' :
'tags-active-no' );
250 $newRow .=
Xml::tags(
'td',
null, $this->
msg( $activeMsg )->escaped() );
252 $hitcountLabelMsg = $this->
msg(
'tags-hitcount' )->numParams( $hitcount );
254 $hitcountLabel = $linkRenderer->makeLink(
256 $hitcountLabelMsg->text(),
258 [
'tagfilter' => $tag ]
261 $hitcountLabel = $hitcountLabelMsg->escaped();
265 $newRow .=
Xml::tags(
'td', [
'data-sort-value' => $hitcount ], $hitcountLabel );
270 $actionLinks[] = $linkRenderer->makeKnownLink(
272 $this->
msg(
'tags-delete' )->text(),
277 if ( $showManageActions ) {
279 $actionLinks[] = $linkRenderer->makeKnownLink(
281 $this->
msg(
'tags-activate' )->text(),
287 $actionLinks[] = $linkRenderer->makeKnownLink(
289 $this->
msg(
'tags-deactivate' )->text(),
295 if ( $showDeleteActions || $showManageActions ) {
299 return Xml::tags(
'tr',
null, $newRow ) .
"\n";
304 $out = $context->getOutput();
306 $tag = trim( strval( $data[
'Tag'] ) );
307 $ignoreWarnings = isset( $data[
'IgnoreWarnings'] ) && $data[
'IgnoreWarnings'] ===
'1';
309 $context->getAuthority(), $ignoreWarnings );
311 if ( $status->isGood() ) {
314 } elseif ( $status->isOK() ) {
318 'IgnoreWarnings' => [
324 $headerText = $this->
msg(
'tags-create-warnings-above', $tag,
325 count( $status->getWarningsArray() ) )->parseAsBlock() .
326 $out->parseAsInterface( $status->getWikiText() ) .
327 $this->
msg(
'tags-create-warnings-below' )->parseAsBlock();
330 ->setSubmitTextMsg(
'htmlform-yes' );
335 $out->wrapWikiTextAsInterface(
'error', $status->getWikiText() );
342 if ( !$authority->isAllowed(
'deletechangetags' ) ) {
347 $out->setPageTitleMsg( $this->
msg(
'tags-delete-title' ) );
352 if ( !$canDeleteResult->isGood() ) {
353 $out->wrapWikiTextAsInterface(
'error', $canDeleteResult->getWikiText() );
354 if ( !$canDeleteResult->isOK() ) {
359 $preText = $this->
msg(
'tags-delete-explanation-initial', $tag )->parseAsBlock();
360 $tagUsage = $this->changeTagsStore->tagUsageStatistics();
361 if ( isset( $tagUsage[$tag] ) && $tagUsage[$tag] > 0 ) {
362 $preText .= $this->
msg(
'tags-delete-explanation-in-use', $tag,
363 $tagUsage[$tag] )->parseAsBlock();
365 $preText .= $this->
msg(
'tags-delete-explanation-warning', $tag )->parseAsBlock();
368 $this->softwareActivatedTags = array_fill_keys(
369 $this->changeTagsStore->listSoftwareActivatedTags(),
true );
370 if ( isset( $this->softwareActivatedTags[$tag] ) ) {
371 $preText .= $this->
msg(
'tags-delete-explanation-active', $tag )->parseAsBlock();
375 $fields[
'Reason'] = [
377 'label' => $this->
msg(
'tags-delete-reason' )->plain(),
380 $fields[
'HiddenTag'] = [
387 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
388 ->setAction( $this->
getPageTitle(
'delete' )->getLocalURL() )
389 ->setSubmitCallback(
function ( $data, $form ) {
392 ->setSubmitTextMsg(
'tags-delete-submit' )
393 ->setSubmitDestructive()
394 ->addPreHtml( $preText )
399 $actionStr = $activate ?
'activate' :
'deactivate';
402 if ( !$authority->isAllowed(
'managechangetags' ) ) {
408 $out->setPageTitleMsg( $this->
msg(
"tags-$actionStr-title" ) );
417 if ( !$result->isGood() ) {
418 $out->wrapWikiTextAsInterface(
'error', $result->getWikiText() );
419 if ( !$result->isOK() ) {
425 $preText = $this->
msg(
"tags-$actionStr-question", $tag )->parseAsBlock();
429 $fields[
'Reason'] = [
431 'label' => $this->
msg(
"tags-$actionStr-reason" )->plain(),
434 $fields[
'HiddenTag'] = [
441 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
442 ->setAction( $this->
getPageTitle( $actionStr )->getLocalURL() )
443 ->setSubmitCallback(
function ( $data, $form ) use ( $actionStr ) {
447 ->setSubmitTextMsg(
"tags-$actionStr-submit" )
448 ->addPreHtml( $preText )
460 $out = $context->getOutput();
462 $tag = $data[
'HiddenTag'];
464 $status = call_user_func( [ ChangeTags::class,
"{$action}TagWithChecks" ],
465 $tag, $data[
'Reason'], $context->getUser(),
true );
467 if ( $status->isGood() ) {
470 } elseif ( $status->isOK() && $action ===
'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() );
507class_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 Per default the message key is the canonical name o...
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.
Module of static functions for generating XML.
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.