49 parent::__construct(
'Tags' );
76 private function showTagList() {
78 $out->setPageTitle( $this->
msg(
'tags-title' ) );
79 $out->wrapWikiMsg(
"<div class='mw-tags-intro'>\n$1\n</div>",
'tags-intro' );
82 $userCanManage = $authority->isAllowed(
'managechangetags' );
83 $userCanDelete = $authority->isAllowed(
'deletechangetags' );
84 $userCanEditInterface = $authority->isAllowed(
'editinterface' );
87 if ( $userCanManage ) {
91 'label' => $this->
msg(
'tags-create-tag-name' )->plain(),
96 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
97 'label' => $this->
msg(
'tags-create-reason' )->plain(),
100 'IgnoreWarnings' => [
105 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
106 ->setAction( $this->
getPageTitle(
'create' )->getLocalURL() )
107 ->setWrapperLegendMsg(
'tags-create-heading' )
108 ->setHeaderText( $this->
msg(
'tags-create-explanation' )->parseAsBlock() )
109 ->setSubmitCallback( [ $this,
'processCreateTagForm' ] )
110 ->setSubmitTextMsg(
'tags-create-submit' )
120 if ( $out->getRedirect() !==
'' ) {
129 $this->explicitlyDefinedTags = array_fill_keys(
131 $this->softwareDefinedTags = array_fill_keys(
135 $definedTags = array_keys( $this->explicitlyDefinedTags + $this->softwareDefinedTags );
138 if ( !$tagStats && !$definedTags ) {
143 $thead =
Xml::tags(
'tr',
null, Xml::tags(
'th',
null, $this->
msg(
'tags-tag' )->parse() ) .
144 Xml::tags(
'th',
null, $this->
msg(
'tags-display-header' )->parse() ) .
145 Xml::tags(
'th',
null, $this->
msg(
'tags-description-header' )->parse() ) .
146 Xml::tags(
'th',
null, $this->
msg(
'tags-source-header' )->parse() ) .
147 Xml::tags(
'th',
null, $this->
msg(
'tags-active-header' )->parse() ) .
148 Xml::tags(
'th',
null, $this->
msg(
'tags-hitcount-header' )->parse() ) .
149 ( ( $userCanManage || $userCanDelete ) ?
150 Xml::tags(
'th', [
'class' =>
'unsortable' ],
151 $this->
msg(
'tags-actions-header' )->parse() ) :
157 $this->softwareActivatedTags = array_fill_keys(
161 foreach ( $tagStats as $tag => $hitcount ) {
162 $tbody .= $this->doTagRow( $tag, $hitcount, $userCanManage,
163 $userCanDelete, $userCanEditInterface );
166 foreach ( $definedTags as $tag ) {
167 if ( !isset( $tagStats[$tag] ) ) {
168 $tbody .= $this->doTagRow( $tag, 0, $userCanManage, $userCanDelete, $userCanEditInterface );
172 $out->addModuleStyles( [
173 'jquery.tablesorter.styles',
174 'mediawiki.pager.styles'
176 $out->addModules(
'jquery.tablesorter' );
177 $out->addHTML( Xml::tags(
179 [
'class' =>
'mw-datatable sortable mw-tags-table' ],
180 Xml::tags(
'thead',
null, $thead ) .
181 Xml::tags(
'tbody',
null, $tbody )
185 private function doTagRow(
186 $tag, $hitcount, $showManageActions, $showDeleteActions, $showEditLinks
189 $newRow .=
Xml::tags(
'td',
null, Xml::element(
'code',
null, $tag ) );
193 if ( $disp ===
false ) {
194 $disp =
Xml::element(
'em',
null, $this->
msg(
'tags-hidden' )->text() );
196 if ( $showEditLinks ) {
198 $editLink = $linkRenderer->makeLink(
199 $this->
msg(
"tag-$tag" )->inContentLanguage()->
getTitle(),
200 $this->
msg(
'tags-edit' )->text(),
202 [
'action' =>
'edit' ]
204 $disp .= $this->
msg(
'parentheses' )->rawParams( $editLink )->escaped();
206 $newRow .=
Xml::tags(
'td',
null, $disp );
208 $msg = $this->
msg(
"tag-$tag-description" );
209 $desc = !$msg->exists() ?
'' : $msg->parse();
210 if ( $showEditLinks ) {
212 $editDescLink = $linkRenderer->makeLink(
213 $this->
msg(
"tag-$tag-description" )->inContentLanguage()->
getTitle(),
214 $this->
msg(
'tags-edit' )->text(),
216 [
'action' =>
'edit' ]
218 $desc .= $this->
msg(
'parentheses' )->rawParams( $editDescLink )->escaped();
220 $newRow .=
Xml::tags(
'td',
null, $desc );
223 $isSoftware = isset( $this->softwareDefinedTags[$tag] );
224 $isExplicit = isset( $this->explicitlyDefinedTags[$tag] );
227 $sourceMsgs[] = $this->
msg(
'tags-source-extension' )->escaped();
230 $sourceMsgs[] = $this->
msg(
'tags-source-manual' )->escaped();
232 if ( !$sourceMsgs ) {
233 $sourceMsgs[] = $this->
msg(
'tags-source-none' )->escaped();
235 $newRow .=
Xml::tags(
'td',
null, implode( Xml::element(
'br' ), $sourceMsgs ) );
237 $isActive = $isExplicit || isset( $this->softwareActivatedTags[$tag] );
238 $activeMsg = ( $isActive ?
'tags-active-yes' :
'tags-active-no' );
239 $newRow .=
Xml::tags(
'td',
null, $this->
msg( $activeMsg )->escaped() );
241 $hitcountLabelMsg = $this->
msg(
'tags-hitcount' )->numParams( $hitcount );
242 if ( $this->
getConfig()->
get( MainConfigNames::UseTagFilter ) ) {
243 $hitcountLabel = $linkRenderer->makeLink(
245 $hitcountLabelMsg->text(),
247 [
'tagfilter' => $tag ]
250 $hitcountLabel = $hitcountLabelMsg->escaped();
254 $newRow .=
Xml::tags(
'td', [
'data-sort-value' => $hitcount ], $hitcountLabel );
259 $actionLinks[] = $linkRenderer->makeKnownLink(
261 $this->
msg(
'tags-delete' )->text(),
266 if ( $showManageActions ) {
268 $actionLinks[] = $linkRenderer->makeKnownLink(
270 $this->
msg(
'tags-activate' )->text(),
276 $actionLinks[] = $linkRenderer->makeKnownLink(
278 $this->
msg(
'tags-deactivate' )->text(),
284 if ( $showDeleteActions || $showManageActions ) {
288 return Xml::tags(
'tr',
null, $newRow ) .
"\n";
293 $out = $context->getOutput();
295 $tag = trim( strval( $data[
'Tag'] ) );
296 $ignoreWarnings = isset( $data[
'IgnoreWarnings'] ) && $data[
'IgnoreWarnings'] ===
'1';
298 $context->getAuthority(), $ignoreWarnings );
300 if ( $status->isGood() ) {
303 } elseif ( $status->isOK() ) {
307 'IgnoreWarnings' => [
313 $headerText = $this->
msg(
'tags-create-warnings-above', $tag,
314 count( $status->getWarningsArray() ) )->parseAsBlock() .
315 $out->parseAsInterface( $status->getWikiText() ) .
316 $this->
msg(
'tags-create-warnings-below' )->parseAsBlock();
319 ->setSubmitTextMsg(
'htmlform-yes' );
324 $out->wrapWikiTextAsInterface(
'error', $status->getWikiText() );
331 if ( !$authority->isAllowed(
'deletechangetags' ) ) {
336 $out->setPageTitle( $this->
msg(
'tags-delete-title' ) );
341 if ( !$canDeleteResult->isGood() ) {
342 $out->wrapWikiTextAsInterface(
'error', $canDeleteResult->getWikiText() );
343 if ( !$canDeleteResult->isOK() ) {
348 $preText = $this->
msg(
'tags-delete-explanation-initial', $tag )->parseAsBlock();
350 if ( isset( $tagUsage[$tag] ) && $tagUsage[$tag] > 0 ) {
351 $preText .= $this->
msg(
'tags-delete-explanation-in-use', $tag,
352 $tagUsage[$tag] )->parseAsBlock();
354 $preText .= $this->
msg(
'tags-delete-explanation-warning', $tag )->parseAsBlock();
357 $this->softwareActivatedTags = array_fill_keys(
359 if ( isset( $this->softwareActivatedTags[$tag] ) ) {
360 $preText .= $this->
msg(
'tags-delete-explanation-active', $tag )->parseAsBlock();
364 $fields[
'Reason'] = [
366 'label' => $this->
msg(
'tags-delete-reason' )->plain(),
369 $fields[
'HiddenTag'] = [
376 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
377 ->setAction( $this->
getPageTitle(
'delete' )->getLocalURL() )
378 ->setSubmitCallback(
function ( $data, $form ) {
381 ->setSubmitTextMsg(
'tags-delete-submit' )
382 ->setSubmitDestructive()
383 ->addPreText( $preText )
388 $actionStr = $activate ?
'activate' :
'deactivate';
391 if ( !$authority->isAllowed(
'managechangetags' ) ) {
397 $out->setPageTitle( $this->
msg(
"tags-$actionStr-title" ) );
406 if ( !$result->isGood() ) {
407 $out->wrapWikiTextAsInterface(
'error', $result->getWikiText() );
408 if ( !$result->isOK() ) {
414 $preText = $this->
msg(
"tags-$actionStr-question", $tag )->parseAsBlock();
418 $fields[
'Reason'] = [
420 'label' => $this->
msg(
"tags-$actionStr-reason" )->plain(),
423 $fields[
'HiddenTag'] = [
430 HTMLForm::factory(
'ooui', $fields, $this->
getContext() )
431 ->setAction( $this->
getPageTitle( $actionStr )->getLocalURL() )
432 ->setSubmitCallback(
function ( $data, $form ) use ( $actionStr ) {
436 ->setSubmitTextMsg(
"tags-$actionStr-submit" )
437 ->addPreText( $preText )
449 $out = $context->getOutput();
451 $tag = $data[
'HiddenTag'];
453 $status = call_user_func( [ ChangeTags::class,
"{$action}TagWithChecks" ],
454 $tag, $data[
'Reason'], $context->getUser(),
true );
456 if ( $status->isGood() ) {
459 } elseif ( $status->isOK() && $action ===
'delete' ) {
461 $out->addWikiTextAsInterface( $this->
msg(
'tags-delete-warnings-after-delete', $tag,
462 count( $status->getWarningsArray() ) )->text() .
"\n" .
463 $status->getWikitext() );
467 $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.