52 private $submitClicked;
73 parent::__construct(
'EditTags',
'changetags' );
75 $this->permissionManager = $permissionManager;
76 $this->changeTagsStore = $changeTagsStore;
94 $output->addModules( [
'mediawiki.misc-authed-curate' ] );
95 $output->addModuleStyles( [
96 'mediawiki.interface.helpers.styles',
100 $this->submitClicked = $request->wasPosted() && $request->getBool(
'wpSubmit' );
103 $ids = $request->getVal(
'ids' );
104 if ( $ids !==
null ) {
106 $this->ids = explode(
',', $ids );
109 $this->ids = array_keys( $request->getArray(
'ids', [] ) );
111 $this->ids = array_unique( array_filter( $this->ids ) );
114 if ( count( $this->ids ) == 0 ) {
115 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
118 $this->typeName = $request->getVal(
'type' );
119 $this->targetObj = Title::newFromText( $request->getText(
'target' ) );
121 switch ( $this->typeName ) {
124 $this->typeName =
'logentry';
127 $this->typeName =
'revision';
134 $this->targetObj = RevisionDeleter::suggestTarget(
135 $this->typeName ===
'revision' ?
'revision' :
'logging',
140 $this->reason = $request->getVal(
'wpReason',
'' );
142 if ( $this->targetObj ===
null ) {
143 $output->addWikiMsg(
'undelete-header' );
148 $checkReplica = !$this->submitClicked;
150 $this->permissionManager->isBlockedFrom(
160 $this->getLanguage(),
169 if ( $this->submitClicked ) {
176 $tagLogPage =
new LogPage(
'tag' );
177 $output->addHTML(
"<h2>" . $tagLogPage->getName()->escaped() .
"</h2>\n" );
178 LogEventsList::showLogExtract(
183 [
'lim' => 25,
'conds' => [],
'useMaster' => $this->wasSaved ]
192 if ( $this->targetObj ) {
194 $this->
getSkin()->setRelevantTitle( $this->targetObj );
198 $links[] = $linkRenderer->makeKnownLink(
200 $this->
msg(
'viewpagelogs' )->text(),
203 'page' => $this->targetObj->getPrefixedText(),
204 'wpfilters' => [
'tag' ],
207 if ( !$this->targetObj->isSpecialPage() ) {
209 $links[] = $linkRenderer->makeKnownLink(
211 $this->
msg(
'pagehist' )->text(),
213 [
'action' =>
'history' ]
217 $links[] = $linkRenderer->makeKnownLink(
219 $this->
msg(
'tags-edit-manage-link' )->text()
231 if ( $this->revList ===
null ) {
233 $this->targetObj, $this->ids );
236 return $this->revList;
246 $out->wrapWikiMsg(
"<strong>$1</strong>", [
247 "tags-edit-{$this->typeName}-selected",
248 $this->
getLanguage()->formatNum( count( $this->ids ) ),
249 $this->targetObj->getPrefixedText()
253 $out->addHTML(
"<ul>" );
258 for ( $list->reset(); $list->current(); $list->next() ) {
259 $item = $list->current();
260 if ( !$item->canView() ) {
261 throw new ErrorPageError(
'permissionserrors',
'tags-update-no-permission' );
264 $out->addHTML( $item->getHTML() );
267 if ( !$numRevisions ) {
268 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
271 $out->addHTML(
"</ul>" );
273 $out->wrapWikiMsg(
'<p>$1</p>',
"tags-edit-{$this->typeName}-explanation" );
276 $form = Html::openElement(
'form', [
'method' =>
'post',
277 'action' => $this->
getPageTitle()->getLocalURL( [
'action' =>
'submit' ] ),
278 'id' =>
'mw-revdel-form-revisions' ] ) .
279 Html::openElement(
'fieldset' ) .
282 $this->
msg(
"tags-edit-{$this->typeName}-legend", count( $this->ids ) )->text()
285 Html::openElement(
'table' ) .
287 '<td class="mw-label">' .
288 Html::label( $this->
msg(
'tags-edit-reason' )->text(),
'wpReason' ) .
290 '<td class="mw-input">' .
291 Html::element(
'input', [
'name' =>
'wpReason',
'size' => 60,
'value' => $this->reason,
296 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
301 '<td class="mw-submit">' .
302 Html::submitButton( $this->
msg(
"tags-edit-{$this->typeName}-submit",
303 $numRevisions )->text(), [
'name' =>
'wpSubmit' ] ) .
306 Html::closeElement(
'table' ) .
307 Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken() ) .
308 Html::hidden(
'target', $this->targetObj->getPrefixedText() ) .
309 Html::hidden(
'type', $this->typeName ) .
310 Html::hidden(
'ids', implode(
',', $this->ids ) ) .
311 Html::closeElement(
'fieldset' ) .
"\n" .
312 Html::closeElement(
'form' ) .
"\n";
314 $out->addHTML( $form );
324 if ( $list->length() == 1 ) {
326 $tags = $list->current()->getTags();
328 $tags = explode(
',', $tags );
333 $html =
'<table id="mw-edittags-tags-selector">';
334 $html .=
'<tr><td>' . $this->
msg(
'tags-edit-existing-tags' )->escaped() .
337 $html .= $this->
getLanguage()->commaList( array_map(
'htmlspecialchars', $tags ) );
339 $html .= $this->
msg(
'tags-edit-existing-tags-none' )->parse();
341 $html .=
'</td></tr>';
342 $tagSelect = $this->
getTagSelect( $tags, $this->
msg(
'tags-edit-new-tags' )->plain() );
343 $html .=
'<tr><td>' . $tagSelect[0] .
'</td><td>' . $tagSelect[1];
348 for ( $list->reset(); $list->current(); $list->next() ) {
349 $currentTags = $list->current()->getTags();
350 if ( $currentTags ) {
351 $tags = array_merge( $tags, explode(
',', $currentTags ) );
354 $tags = array_unique( $tags );
356 $html =
'<table id="mw-edittags-tags-selector-multi"><tr><td>';
357 $tagSelect = $this->
getTagSelect( [], $this->
msg(
'tags-edit-add' )->plain() );
358 $html .=
'<p>' . $tagSelect[0] .
'</p>' . $tagSelect[1] .
'</td><td>';
359 $html .=
Html::element(
'p', [], $this->
msg(
'tags-edit-remove' )->plain() );
361 'type' =>
'checkbox',
'name' =>
'wpRemoveAllTags',
'value' =>
'1',
362 'id' =>
'mw-edittags-remove-all'
364 . Html::label( $this->
msg(
'tags-edit-remove-all-tags' )->plain(),
'mw-edittags-remove-all' );
366 foreach ( $tags as $tag ) {
367 $id =
'mw-edittags-remove-' . $i++;
369 'type' =>
'checkbox',
'name' =>
'wpTagsToRemove[]',
'value' => $tag,
370 'class' =>
'mw-edittags-remove-checkbox',
'id' => $id,
371 ] ) .
' ' . Html::label( $tag, $id );
377 $html .= Html::hidden(
'wpExistingTags', implode(
',', $tags ) );
378 $html .=
'</td></tr></table>';
397 $result[0] = Html::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 ) {
452 $status = Status::newFatal(
'tags-edit-none-selected' );
454 $status = $this->
getList()->updateChangeTagsOnAll( $tagsToAdd,
455 $tagsToRemove,
null, $this->reason, $this->
getAuthority() );
458 if ( $status->isGood() ) {
472 $out->setPageTitleMsg( $this->
msg(
'actioncomplete' ) );
474 Html::successBox( $out->msg(
'tags-edit-success' )->parse() )
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' );
509class_alias( SpecialEditTags::class,
'SpecialEditTags' );
An error page which can definitely be safely rendered using the OutputPage.
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 By default the message key is the canonical name of...
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.