22 namespace MediaWiki\Specials;
53 private $submitClicked;
79 parent::__construct(
'EditTags',
'changetags' );
81 $this->permissionManager = $permissionManager;
82 $this->changeTagsStore = $changeTagsStore;
100 $output->addModules( [
'mediawiki.misc-authed-curate' ] );
101 $output->addModuleStyles( [
102 'mediawiki.interface.helpers.styles',
106 $this->submitClicked = $request->wasPosted() && $request->getBool(
'wpSubmit' );
109 $ids = $request->getVal(
'ids' );
110 if ( $ids !==
null ) {
112 $this->ids = explode(
',', $ids );
115 $this->ids = array_keys( $request->getArray(
'ids', [] ) );
117 $this->ids = array_unique( array_filter( $this->ids ) );
120 if ( count( $this->ids ) == 0 ) {
121 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
124 $this->typeName = $request->getVal(
'type' );
127 switch ( $this->typeName ) {
130 $this->typeName =
'logentry';
133 $this->typeName =
'revision';
141 $this->typeName ===
'revision' ?
'revision' :
'logging',
146 $this->reason = $request->getVal(
'wpReason',
'' );
148 if ( $this->targetObj ===
null ) {
149 $output->addWikiMsg(
'undelete-header' );
154 $checkReplica = !$this->submitClicked;
156 $this->permissionManager->isBlockedFrom(
166 $this->getLanguage(),
175 if ( $this->submitClicked ) {
182 $tagLogPage =
new LogPage(
'tag' );
183 $output->addHTML(
"<h2>" . $tagLogPage->getName()->escaped() .
"</h2>\n" );
189 [
'lim' => 25,
'conds' => [],
'useMaster' => $this->wasSaved ]
198 if ( $this->targetObj ) {
200 $this->
getSkin()->setRelevantTitle( $this->targetObj );
204 $links[] = $linkRenderer->makeKnownLink(
206 $this->
msg(
'viewpagelogs' )->text(),
209 'page' => $this->targetObj->getPrefixedText(),
210 'wpfilters' => [
'tag' ],
213 if ( !$this->targetObj->isSpecialPage() ) {
215 $links[] = $linkRenderer->makeKnownLink(
217 $this->
msg(
'pagehist' )->text(),
219 [
'action' =>
'history' ]
223 $links[] = $linkRenderer->makeKnownLink(
225 $this->
msg(
'tags-edit-manage-link' )->text()
237 if ( $this->revList ===
null ) {
239 $this->targetObj, $this->ids );
242 return $this->revList;
252 $out->wrapWikiMsg(
"<strong>$1</strong>", [
253 "tags-edit-{$this->typeName}-selected",
254 $this->
getLanguage()->formatNum( count( $this->ids ) ),
255 $this->targetObj->getPrefixedText()
259 $out->addHTML(
"<ul>" );
264 for ( $list->reset(); $list->current(); $list->next() ) {
265 $item = $list->current();
266 if ( !$item->canView() ) {
267 throw new ErrorPageError(
'permissionserrors',
'tags-update-no-permission' );
270 $out->addHTML( $item->getHTML() );
273 if ( !$numRevisions ) {
274 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
277 $out->addHTML(
"</ul>" );
279 $out->wrapWikiMsg(
'<p>$1</p>',
"tags-edit-{$this->typeName}-explanation" );
283 'action' => $this->
getPageTitle()->getLocalURL( [
'action' =>
'submit' ] ),
284 'id' =>
'mw-revdel-form-revisions' ] ) .
286 count( $this->ids ) )->text() ) .
290 '<td class="mw-label">' .
291 Xml::label( $this->
msg(
'tags-edit-reason' )->text(),
'wpReason' ) .
293 '<td class="mw-input">' .
304 '<td class="mw-submit">' .
306 $numRevisions )->text(), [
'name' =>
'wpSubmit' ] ) .
311 Html::hidden(
'target', $this->targetObj->getPrefixedText() ) .
317 $out->addHTML( $form );
327 if ( $list->length() == 1 ) {
329 $tags = $list->current()->getTags();
331 $tags = explode(
',', $tags );
336 $html =
'<table id="mw-edittags-tags-selector">';
337 $html .=
'<tr><td>' . $this->
msg(
'tags-edit-existing-tags' )->escaped() .
340 $html .= $this->
getLanguage()->commaList( array_map(
'htmlspecialchars', $tags ) );
342 $html .= $this->
msg(
'tags-edit-existing-tags-none' )->parse();
344 $html .=
'</td></tr>';
345 $tagSelect = $this->
getTagSelect( $tags, $this->
msg(
'tags-edit-new-tags' )->plain() );
346 $html .=
'<tr><td>' . $tagSelect[0] .
'</td><td>' . $tagSelect[1];
351 for ( $list->reset(); $list->current(); $list->next() ) {
352 $currentTags = $list->current()->getTags();
353 if ( $currentTags ) {
354 $tags = array_merge( $tags, explode(
',', $currentTags ) );
357 $tags = array_unique( $tags );
359 $html =
'<table id="mw-edittags-tags-selector-multi"><tr><td>';
360 $tagSelect = $this->
getTagSelect( [], $this->
msg(
'tags-edit-add' )->plain() );
361 $html .=
'<p>' . $tagSelect[0] .
'</p>' . $tagSelect[1] .
'</td><td>';
362 $html .=
Xml::element(
'p',
null, $this->
msg(
'tags-edit-remove' )->plain() );
364 'wpRemoveAllTags',
'mw-edittags-remove-all' );
366 foreach ( $tags as $tag ) {
368 'wpTagsToRemove[]',
'mw-edittags-remove-' . $i++,
false, [
370 'class' =>
'mw-edittags-remove-checkbox',
377 $html .=
Html::hidden(
'wpExistingTags', implode(
',', $tags ) );
378 $html .=
'</td></tr></table>';
397 $result[0] =
Xml::label( $label,
'mw-edittags-tag-list' );
399 $select =
new XmlSelect(
'wpTagList[]',
'mw-edittags-tag-list', $selectedTags );
400 $select->setAttribute(
'multiple',
'multiple' );
401 $select->setAttribute(
'size',
'8' );
403 $tags = $this->changeTagsStore->listExplicitlyDefinedTags();
404 $tags = array_unique( array_merge( $tags, $selectedTags ) );
407 $select->addOptions( array_combine( $tags, $tags ) );
409 $result[1] = $select->getHTML();
420 $token = $request->getVal(
'wpEditToken' );
421 if ( $this->submitClicked && !$this->
getUser()->matchEditToken( $token ) ) {
422 $this->
getOutput()->addWikiMsg(
'sessionfailure' );
427 $tagList = $request->getArray(
'wpTagList' ) ?? [];
428 $existingTags = $request->getVal(
'wpExistingTags' );
429 if ( $existingTags ===
null || $existingTags ===
'' ) {
432 $existingTags = explode(
',', $existingTags );
435 if ( count( $this->ids ) > 1 ) {
437 $tagsToAdd = $tagList;
438 if ( $request->getBool(
'wpRemoveAllTags' ) ) {
439 $tagsToRemove = $existingTags;
441 $tagsToRemove = $request->getArray(
'wpTagsToRemove', [] );
447 $tagsToAdd = array_diff( $tagList, $existingTags );
448 $tagsToRemove = array_diff( $existingTags, $tagList );
451 if ( !$tagsToAdd && !$tagsToRemove ) {
454 $status = $this->
getList()->updateChangeTagsOnAll( $tagsToAdd,
455 $tagsToRemove,
null, $this->reason, $this->
getAuthority() );
458 if ( $status->isGood() ) {
472 $out->setPageTitleMsg( $this->
msg(
'actioncomplete' ) );
476 $this->wasSaved =
true;
477 $this->revList->reloadFromPrimary();
488 $out->setPageTitleMsg( $this->
msg(
'actionfailed' ) );
491 $out->parseAsContent(
492 $status->getWikiText(
'tags-edit-failure',
false, $this->getLanguage() )
500 return $this->
msg(
'tags-edit-title' );
511 class_alias( SpecialEditTags::class,
'SpecialEditTags' );
An error page which can definitely be safely rendered using the OutputPage.
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Class to simplify the use of log pages.
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getSkin()
Shortcut to get the skin 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,...
getUser()
Shortcut to get the User executing this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
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.
Shortcut to construct a special page which is unlisted by default.
General controller for RevDel, used by both SpecialRevisiondelete and ApiRevisionDelete.
static suggestTarget( $typeName, $target, array $ids)
Suggest a target for the revision deletion.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Show an error when the user tries to do something whilst blocked.
Class for generating HTML <select> or <datalist> elements.
Module of static functions for generating XML.
static closeElement( $element)
Shortcut to close an XML element.
static label( $label, $id, $attribs=[])
Convenience function to build an HTML form label.
static openElement( $element, $attribs=null)
This opens an XML element.
static input( $name, $size=false, $value=false, $attribs=[])
Convenience function to build an HTML text input field.
static submitButton( $value, $attribs=[])
Convenience function to build an HTML submit button When $wgUseMediaWikiUIEverywhere is true it will ...
static checkLabel( $label, $name, $id, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox with a label.
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
static fieldset( $legend=false, $content=false, $attribs=[])
Shortcut for creating fieldsets.