65 parent::__construct(
'EditTags',
'changetags' );
85 $output->addModules( [
'mediawiki.special.edittags' ] );
86 $output->addModuleStyles( [
87 'mediawiki.interface.helpers.styles',
91 $this->submitClicked = $request->wasPosted() && $request->getBool(
'wpSubmit' );
94 $ids = $request->getVal(
'ids' );
95 if (
$ids !==
null ) {
97 $this->ids = explode(
',',
$ids );
100 $this->ids = array_keys( $request->getArray(
'ids', [] ) );
102 $this->ids = array_unique( array_filter( $this->ids ) );
105 if ( count( $this->ids ) == 0 ) {
106 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
109 $this->typeName = $request->getVal(
'type' );
110 $this->targetObj = Title::newFromText( $request->getText(
'target' ) );
113 switch ( $this->typeName ) {
116 $this->typeName =
'logentry';
119 $this->typeName =
'revision';
127 $this->typeName ===
'revision' ?
'revision' :
'logging',
132 $this->isAllowed = $this->permissionManager->userHasRight( $user,
'changetags' );
134 $this->reason = $request->getVal(
'wpReason' );
136 if ( $this->targetObj ===
null ) {
137 $output->addWikiMsg(
'undelete-header' );
144 $this->permissionManager->isBlockedFrom(
153 $this->getLanguage(),
162 if ( $this->isAllowed && $this->submitClicked ) {
169 $tagLogPage =
new LogPage(
'tag' );
170 $output->addHTML(
"<h2>" . $tagLogPage->getName()->escaped() .
"</h2>\n" );
171 LogEventsList::showLogExtract(
176 [
'lim' => 25,
'conds' => [],
'useMaster' => $this->wasSaved ]
185 if ( $this->targetObj ) {
187 $this->
getSkin()->setRelevantTitle( $this->targetObj );
193 $this->
msg(
'viewpagelogs' )->text(),
196 'page' => $this->targetObj->getPrefixedText(),
197 'wpfilters' => [
'tag' ],
200 if ( !$this->targetObj->isSpecialPage() ) {
204 $this->
msg(
'pagehist' )->text(),
206 [
'action' =>
'history' ]
212 $this->
msg(
'tags-edit-manage-link' )->text()
224 if ( $this->revList ===
null ) {
226 $this->targetObj, $this->ids );
239 $out->wrapWikiMsg(
"<strong>$1</strong>", [
240 "tags-edit-{$this->typeName}-selected",
241 $this->
getLanguage()->formatNum( count( $this->ids ) ),
242 $this->targetObj->getPrefixedText()
246 $out->addHTML(
"<ul>" );
251 for ( $list->reset(); $list->current(); $list->next() ) {
252 $item = $list->current();
253 if ( !$item->canView() ) {
254 throw new ErrorPageError(
'permissionserrors',
'tags-update-no-permission' );
257 $out->addHTML( $item->getHTML() );
260 if ( !$numRevisions ) {
261 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
264 $out->addHTML(
"</ul>" );
266 $out->wrapWikiMsg(
'<p>$1</p>',
"tags-edit-{$this->typeName}-explanation" );
269 if ( $this->isAllowed ) {
270 $form = Xml::openElement(
'form', [
'method' =>
'post',
271 'action' => $this->
getPageTitle()->getLocalURL( [
'action' =>
'submit' ] ),
272 'id' =>
'mw-revdel-form-revisions' ] ) .
273 Xml::fieldset( $this->
msg(
"tags-edit-{$this->typeName}-legend",
274 count( $this->ids ) )->text() ) .
276 Xml::openElement(
'table' ) .
278 '<td class="mw-label">' .
279 Xml::label( $this->
msg(
'tags-edit-reason' )->text(),
'wpReason' ) .
281 '<td class="mw-input">' .
282 Xml::input(
'wpReason', 60, $this->reason, [
287 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
292 '<td class="mw-submit">' .
293 Xml::submitButton( $this->
msg(
"tags-edit-{$this->typeName}-submit",
294 $numRevisions )->text(), [
'name' =>
'wpSubmit' ] ) .
297 Xml::closeElement(
'table' ) .
298 Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken() ) .
299 Html::hidden(
'target', $this->targetObj->getPrefixedText() ) .
300 Html::hidden(
'type', $this->typeName ) .
301 Html::hidden(
'ids', implode(
',', $this->ids ) ) .
302 Xml::closeElement(
'fieldset' ) .
"\n" .
303 Xml::closeElement(
'form' ) .
"\n";
307 $out->addHTML( $form );
317 if ( $list->length() == 1 ) {
319 $tags = $list->current()->getTags();
321 $tags = explode(
',', $tags );
326 $html =
'<table id="mw-edittags-tags-selector">';
327 $html .=
'<tr><td>' . $this->
msg(
'tags-edit-existing-tags' )->escaped() .
330 $html .= $this->
getLanguage()->commaList( array_map(
'htmlspecialchars', $tags ) );
332 $html .= $this->
msg(
'tags-edit-existing-tags-none' )->parse();
334 $html .=
'</td></tr>';
335 $tagSelect = $this->
getTagSelect( $tags, $this->
msg(
'tags-edit-new-tags' )->plain() );
336 $html .=
'<tr><td>' . $tagSelect[0] .
'</td><td>' . $tagSelect[1];
341 for ( $list->reset(); $list->current(); $list->next() ) {
342 $currentTags = $list->current()->getTags();
343 if ( $currentTags ) {
344 $tags = array_merge( $tags, explode(
',', $currentTags ) );
347 $tags = array_unique( $tags );
349 $html =
'<table id="mw-edittags-tags-selector-multi"><tr><td>';
350 $tagSelect = $this->
getTagSelect( [], $this->
msg(
'tags-edit-add' )->plain() );
351 $html .=
'<p>' . $tagSelect[0] .
'</p>' . $tagSelect[1] .
'</td><td>';
352 $html .= Xml::element(
'p',
null, $this->
msg(
'tags-edit-remove' )->plain() );
353 $html .= Xml::checkLabel( $this->
msg(
'tags-edit-remove-all-tags' )->plain(),
354 'wpRemoveAllTags',
'mw-edittags-remove-all' );
356 foreach ( $tags as $tag ) {
357 $html .= Xml::element(
'br' ) .
"\n" . Xml::checkLabel( $tag,
358 'wpTagsToRemove[]',
'mw-edittags-remove-' . $i++,
false, [
360 'class' =>
'mw-edittags-remove-checkbox',
367 $html .= Html::hidden(
'wpExistingTags', implode(
',', $tags ) );
368 $html .=
'</td></tr></table>';
387 $result[0] = Xml::label( $label,
'mw-edittags-tag-list' );
389 $select =
new XmlSelect(
'wpTagList[]',
'mw-edittags-tag-list', $selectedTags );
390 $select->setAttribute(
'multiple',
'multiple' );
391 $select->setAttribute(
'size',
'8' );
394 $tags = array_unique( array_merge( $tags, $selectedTags ) );
397 $select->addOptions( array_combine( $tags, $tags ) );
399 $result[1] = $select->getHTML();
410 $token = $request->getVal(
'wpEditToken' );
411 if ( $this->submitClicked && !$this->
getUser()->matchEditToken( $token ) ) {
412 $this->
getOutput()->addWikiMsg(
'sessionfailure' );
417 $tagList = $request->getArray(
'wpTagList' );
418 if ( $tagList ===
null ) {
421 $existingTags = $request->getVal(
'wpExistingTags' );
422 if ( $existingTags ===
null || $existingTags ===
'' ) {
425 $existingTags = explode(
',', $existingTags );
428 if ( count( $this->ids ) > 1 ) {
430 $tagsToAdd = $tagList;
431 if ( $request->getBool(
'wpRemoveAllTags' ) ) {
432 $tagsToRemove = $existingTags;
434 $tagsToRemove = $request->getArray(
'wpTagsToRemove', [] );
440 $tagsToAdd = array_diff( $tagList, $existingTags );
441 $tagsToRemove = array_diff( $existingTags, $tagList );
444 if ( !$tagsToAdd && !$tagsToRemove ) {
445 $status = Status::newFatal(
'tags-edit-none-selected' );
447 $status = $this->
getList()->updateChangeTagsOnAll( $tagsToAdd,
448 $tagsToRemove,
null, $this->reason, $this->
getAuthority() );
451 if ( $status->isGood() ) {
464 $this->
getOutput()->setPageTitle( $this->
msg(
'actioncomplete' ) );
465 $this->
getOutput()->wrapWikiMsg(
"<div class=\"successbox\">\n$1\n</div>",
466 'tags-edit-success' );
467 $this->wasSaved =
true;
468 $this->revList->reloadFromPrimary();
478 $this->
getOutput()->setPageTitle( $this->
msg(
'actionfailed' ) );
479 $this->
getOutput()->wrapWikiTextAsInterface(
480 'errorbox', $status->getWikiText(
'tags-edit-failure',
false, $this->getLanguage() )
486 return $this->
msg(
'tags-edit-title' )->text();
An error page which can definitely be safely rendered using the OutputPage.
Class to simplify the use of log pages.
static suggestTarget( $typeName, $target, array $ids)
Suggest a target for the revision deletion.
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.
getUser()
Shortcut to get the User executing this instance.
getSkin()
Shortcut to get the skin being used for this instance.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
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.
LinkRenderer null $linkRenderer
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getAuthority()
Shortcut to get the Authority executing this instance.
getRequest()
Get the WebRequest being used for this instance.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
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.
Represents a title within MediaWiki.
Shortcut to construct a special page which is unlisted by default.
Show an error when the user tries to do something whilst blocked.
Class for generating HTML <select> or <datalist> elements.