50 parent::__construct(
'Tags' );
77 private function showTagList() {
79 $out->setPageTitle( $this->
msg(
'tags-title' ) );
80 $out->wrapWikiMsg(
"<div class='mw-tags-intro'>\n$1\n</div>",
'tags-intro' );
83 $userCanManage = $authority->isAllowed(
'managechangetags' );
84 $userCanDelete = $authority->isAllowed(
'deletechangetags' );
85 $userCanEditInterface = $authority->isAllowed(
'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 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
107 ->setAction( $this->
getPageTitle(
'create' )->getLocalURL() )
108 ->setWrapperLegendMsg(
'tags-create-heading' )
109 ->setHeaderHtml( $this->
msg(
'tags-create-explanation' )->parseAsBlock() )
110 ->setSubmitCallback( [ $this,
'processCreateTagForm' ] )
111 ->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( [
174 'jquery.tablesorter.styles',
175 'mediawiki.pager.styles'
177 $out->addModules(
'jquery.tablesorter' );
178 $out->addHTML( Xml::tags(
180 [
'class' =>
'mw-datatable sortable mw-tags-table' ],
181 Xml::tags(
'thead',
null, $thead ) .
182 Xml::tags(
'tbody',
null, $tbody )
186 private function doTagRow(
187 $tag, $hitcount, $showManageActions, $showDeleteActions, $showEditLinks
190 $newRow .=
Xml::tags(
'td',
null, Xml::element(
'code',
null, $tag ) );
194 if ( $disp ===
false ) {
195 $disp =
Xml::element(
'em',
null, $this->
msg(
'tags-hidden' )->text() );
197 if ( $showEditLinks ) {
199 $editLink = $linkRenderer->makeLink(
200 $this->
msg(
"tag-$tag" )->inContentLanguage()->
getTitle(),
201 $this->
msg(
'tags-edit' )->text(),
203 [
'action' =>
'edit' ]
205 $disp .= $this->
msg(
'parentheses' )->rawParams( $editLink )->escaped();
207 $newRow .=
Xml::tags(
'td',
null, $disp );
209 $msg = $this->
msg(
"tag-$tag-description" );
210 $desc = !$msg->exists() ?
'' : $msg->parse();
211 if ( $showEditLinks ) {
213 $editDescLink = $linkRenderer->makeLink(
214 $this->
msg(
"tag-$tag-description" )->inContentLanguage()->
getTitle(),
215 $this->
msg(
'tags-edit' )->text(),
217 [
'action' =>
'edit' ]
219 $desc .= $this->
msg(
'parentheses' )->rawParams( $editDescLink )->escaped();
221 $newRow .=
Xml::tags(
'td',
null, $desc );
224 $isSoftware = isset( $this->softwareDefinedTags[$tag] );
225 $isExplicit = isset( $this->explicitlyDefinedTags[$tag] );
228 $sourceMsgs[] = $this->
msg(
'tags-source-extension' )->escaped();
231 $sourceMsgs[] = $this->
msg(
'tags-source-manual' )->escaped();
233 if ( !$sourceMsgs ) {
234 $sourceMsgs[] = $this->
msg(
'tags-source-none' )->escaped();
236 $newRow .=
Xml::tags(
'td',
null, implode( Xml::element(
'br' ), $sourceMsgs ) );
238 $isActive = $isExplicit || isset( $this->softwareActivatedTags[$tag] );
239 $activeMsg = ( $isActive ?
'tags-active-yes' :
'tags-active-no' );
240 $newRow .=
Xml::tags(
'td',
null, $this->
msg( $activeMsg )->escaped() );
242 $hitcountLabelMsg = $this->
msg(
'tags-hitcount' )->numParams( $hitcount );
243 if ( $this->
getConfig()->
get( MainConfigNames::UseTagFilter ) ) {
244 $hitcountLabel = $linkRenderer->makeLink(
246 $hitcountLabelMsg->text(),
248 [
'tagfilter' => $tag ]
251 $hitcountLabel = $hitcountLabelMsg->escaped();
255 $newRow .=
Xml::tags(
'td', [
'data-sort-value' => $hitcount ], $hitcountLabel );
260 $actionLinks[] = $linkRenderer->makeKnownLink(
262 $this->
msg(
'tags-delete' )->text(),
267 if ( $showManageActions ) {
269 $actionLinks[] = $linkRenderer->makeKnownLink(
271 $this->
msg(
'tags-activate' )->text(),
277 $actionLinks[] = $linkRenderer->makeKnownLink(
279 $this->
msg(
'tags-deactivate' )->text(),
285 if ( $showDeleteActions || $showManageActions ) {
289 return Xml::tags(
'tr',
null, $newRow ) .
"\n";
294 $out = $context->getOutput();
296 $tag = trim( strval( $data[
'Tag'] ) );
297 $ignoreWarnings = isset( $data[
'IgnoreWarnings'] ) && $data[
'IgnoreWarnings'] ===
'1';
299 $context->getAuthority(), $ignoreWarnings );
301 if ( $status->isGood() ) {
304 } elseif ( $status->isOK() ) {
308 'IgnoreWarnings' => [
314 $headerText = $this->
msg(
'tags-create-warnings-above', $tag,
315 count( $status->getWarningsArray() ) )->parseAsBlock() .
316 $out->parseAsInterface( $status->getWikiText() ) .
317 $this->
msg(
'tags-create-warnings-below' )->parseAsBlock();
320 ->setSubmitTextMsg(
'htmlform-yes' );
325 $out->wrapWikiTextAsInterface(
'error', $status->getWikiText() );
332 if ( !$authority->isAllowed(
'deletechangetags' ) ) {
337 $out->setPageTitle( $this->
msg(
'tags-delete-title' ) );
342 if ( !$canDeleteResult->isGood() ) {
343 $out->wrapWikiTextAsInterface(
'error', $canDeleteResult->getWikiText() );
344 if ( !$canDeleteResult->isOK() ) {
349 $preText = $this->
msg(
'tags-delete-explanation-initial', $tag )->parseAsBlock();
351 if ( isset( $tagUsage[$tag] ) && $tagUsage[$tag] > 0 ) {
352 $preText .= $this->
msg(
'tags-delete-explanation-in-use', $tag,
353 $tagUsage[$tag] )->parseAsBlock();
355 $preText .= $this->
msg(
'tags-delete-explanation-warning', $tag )->parseAsBlock();
358 $this->softwareActivatedTags = array_fill_keys(
360 if ( isset( $this->softwareActivatedTags[$tag] ) ) {
361 $preText .= $this->
msg(
'tags-delete-explanation-active', $tag )->parseAsBlock();
365 $fields[
'Reason'] = [
367 'label' => $this->
msg(
'tags-delete-reason' )->plain(),
370 $fields[
'HiddenTag'] = [
377 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
378 ->setAction( $this->
getPageTitle(
'delete' )->getLocalURL() )
379 ->setSubmitCallback(
function ( $data, $form ) {
382 ->setSubmitTextMsg(
'tags-delete-submit' )
383 ->setSubmitDestructive()
384 ->addPreHtml( $preText )
389 $actionStr = $activate ?
'activate' :
'deactivate';
392 if ( !$authority->isAllowed(
'managechangetags' ) ) {
398 $out->setPageTitle( $this->
msg(
"tags-$actionStr-title" ) );
407 if ( !$result->isGood() ) {
408 $out->wrapWikiTextAsInterface(
'error', $result->getWikiText() );
409 if ( !$result->isOK() ) {
415 $preText = $this->
msg(
"tags-$actionStr-question", $tag )->parseAsBlock();
419 $fields[
'Reason'] = [
421 'label' => $this->
msg(
"tags-$actionStr-reason" )->plain(),
424 $fields[
'HiddenTag'] = [
431 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
432 ->setAction( $this->
getPageTitle( $actionStr )->getLocalURL() )
433 ->setSubmitCallback(
function ( $data, $form ) use ( $actionStr ) {
437 ->setSubmitTextMsg(
"tags-$actionStr-submit" )
438 ->addPreHtml( $preText )
450 $out = $context->getOutput();
452 $tag = $data[
'HiddenTag'];
454 $status = call_user_func( [ ChangeTags::class,
"{$action}TagWithChecks" ],
455 $tag, $data[
'Reason'], $context->getUser(),
true );
457 if ( $status->isGood() ) {
460 } elseif ( $status->isOK() && $action ===
'delete' ) {
462 $out->addWikiTextAsInterface( $this->
msg(
'tags-delete-warnings-after-delete', $tag,
463 count( $status->getWarningsArray() ) )->text() .
"\n" .
464 $status->getWikitext() );
468 $out->wrapWikiTextAsInterface(
'error', $status->getWikitext() );
getContext()
Get the base IContextSource object.
A class containing constants representing the names of configuration variables.
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.
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.
getAuthority()
Shortcut to get the Authority executing this instance.
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.
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.