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',
'' );
137 if ( $this->targetObj ===
null ) {
138 $output->addWikiMsg(
'undelete-header' );
143 if ( $this->permissionManager->isBlockedFrom( $user, $this->targetObj ) ) {
147 $this->getLanguage(),
156 if ( $this->isAllowed && $this->submitClicked ) {
163 $tagLogPage =
new LogPage(
'tag' );
164 $output->addHTML(
"<h2>" . $tagLogPage->getName()->escaped() .
"</h2>\n" );
165 LogEventsList::showLogExtract(
170 [
'lim' => 25,
'conds' => [],
'useMaster' => $this->wasSaved ]
179 if ( $this->targetObj ) {
181 $this->
getSkin()->setRelevantTitle( $this->targetObj );
187 $this->
msg(
'viewpagelogs' )->text(),
190 'page' => $this->targetObj->getPrefixedText(),
191 'wpfilters' => [
'tag' ],
194 if ( !$this->targetObj->isSpecialPage() ) {
198 $this->
msg(
'pagehist' )->text(),
200 [
'action' =>
'history' ]
206 $this->
msg(
'tags-edit-manage-link' )->text()
218 if ( $this->revList ===
null ) {
220 $this->targetObj, $this->ids );
233 $out->wrapWikiMsg(
"<strong>$1</strong>", [
234 "tags-edit-{$this->typeName}-selected",
235 $this->
getLanguage()->formatNum( count( $this->ids ) ),
236 $this->targetObj->getPrefixedText()
240 $out->addHTML(
"<ul>" );
245 for ( $list->reset(); $list->current(); $list->next() ) {
246 $item = $list->current();
247 if ( !$item->canView() ) {
248 throw new ErrorPageError(
'permissionserrors',
'tags-update-no-permission' );
251 $out->addHTML( $item->getHTML() );
254 if ( !$numRevisions ) {
255 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
258 $out->addHTML(
"</ul>" );
260 $out->wrapWikiMsg(
'<p>$1</p>',
"tags-edit-{$this->typeName}-explanation" );
263 if ( $this->isAllowed ) {
264 $form = Xml::openElement(
'form', [
'method' =>
'post',
265 'action' => $this->
getPageTitle()->getLocalURL( [
'action' =>
'submit' ] ),
266 'id' =>
'mw-revdel-form-revisions' ] ) .
267 Xml::fieldset( $this->
msg(
"tags-edit-{$this->typeName}-legend",
268 count( $this->ids ) )->text() ) .
270 Xml::openElement(
'table' ) .
272 '<td class="mw-label">' .
273 Xml::label( $this->
msg(
'tags-edit-reason' )->text(),
'wpReason' ) .
275 '<td class="mw-input">' .
276 Xml::input(
'wpReason', 60, $this->reason, [
281 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
286 '<td class="mw-submit">' .
287 Xml::submitButton( $this->
msg(
"tags-edit-{$this->typeName}-submit",
288 $numRevisions )->text(), [
'name' =>
'wpSubmit' ] ) .
291 Xml::closeElement(
'table' ) .
292 Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken() ) .
293 Html::hidden(
'target', $this->targetObj->getPrefixedText() ) .
294 Html::hidden(
'type', $this->typeName ) .
295 Html::hidden(
'ids', implode(
',', $this->ids ) ) .
296 Xml::closeElement(
'fieldset' ) .
"\n" .
297 Xml::closeElement(
'form' ) .
"\n";
301 $out->addHTML( $form );
311 if ( $list->length() == 1 ) {
313 $tags = $list->current()->getTags();
315 $tags = explode(
',', $tags );
320 $html =
'<table id="mw-edittags-tags-selector">';
321 $html .=
'<tr><td>' . $this->
msg(
'tags-edit-existing-tags' )->escaped() .
324 $html .= $this->
getLanguage()->commaList( array_map(
'htmlspecialchars', $tags ) );
326 $html .= $this->
msg(
'tags-edit-existing-tags-none' )->parse();
328 $html .=
'</td></tr>';
329 $tagSelect = $this->
getTagSelect( $tags, $this->
msg(
'tags-edit-new-tags' )->plain() );
330 $html .=
'<tr><td>' . $tagSelect[0] .
'</td><td>' . $tagSelect[1];
335 for ( $list->reset(); $list->current(); $list->next() ) {
336 $currentTags = $list->current()->getTags();
337 if ( $currentTags ) {
338 $tags = array_merge( $tags, explode(
',', $currentTags ) );
341 $tags = array_unique( $tags );
343 $html =
'<table id="mw-edittags-tags-selector-multi"><tr><td>';
344 $tagSelect = $this->
getTagSelect( [], $this->
msg(
'tags-edit-add' )->plain() );
345 $html .=
'<p>' . $tagSelect[0] .
'</p>' . $tagSelect[1] .
'</td><td>';
346 $html .= Xml::element(
'p',
null, $this->
msg(
'tags-edit-remove' )->plain() );
347 $html .= Xml::checkLabel( $this->
msg(
'tags-edit-remove-all-tags' )->plain(),
348 'wpRemoveAllTags',
'mw-edittags-remove-all' );
350 foreach ( $tags as $tag ) {
351 $html .= Xml::element(
'br' ) .
"\n" . Xml::checkLabel( $tag,
352 'wpTagsToRemove[]',
'mw-edittags-remove-' . $i++,
false, [
354 'class' =>
'mw-edittags-remove-checkbox',
361 $html .= Html::hidden(
'wpExistingTags', implode(
',', $tags ) );
362 $html .=
'</td></tr></table>';
381 $result[0] = Xml::label( $label,
'mw-edittags-tag-list' );
383 $select =
new XmlSelect(
'wpTagList[]',
'mw-edittags-tag-list', $selectedTags );
384 $select->setAttribute(
'multiple',
'multiple' );
385 $select->setAttribute(
'size',
'8' );
388 $tags = array_unique( array_merge( $tags, $selectedTags ) );
391 $select->addOptions( array_combine( $tags, $tags ) );
393 $result[1] = $select->getHTML();
404 $token = $request->getVal(
'wpEditToken' );
405 if ( $this->submitClicked && !$this->
getUser()->matchEditToken( $token ) ) {
406 $this->
getOutput()->addWikiMsg(
'sessionfailure' );
411 $tagList = $request->getArray(
'wpTagList' );
412 if ( $tagList ===
null ) {
415 $existingTags = $request->getVal(
'wpExistingTags' );
416 if ( $existingTags ===
null || $existingTags ===
'' ) {
419 $existingTags = explode(
',', $existingTags );
422 if ( count( $this->ids ) > 1 ) {
424 $tagsToAdd = $tagList;
425 if ( $request->getBool(
'wpRemoveAllTags' ) ) {
426 $tagsToRemove = $existingTags;
428 $tagsToRemove = $request->getArray(
'wpTagsToRemove' );
434 $tagsToAdd = array_diff( $tagList, $existingTags );
435 $tagsToRemove = array_diff( $existingTags, $tagList );
438 if ( !$tagsToAdd && !$tagsToRemove ) {
439 $status = Status::newFatal(
'tags-edit-none-selected' );
441 $status = $this->
getList()->updateChangeTagsOnAll( $tagsToAdd,
442 $tagsToRemove,
null, $this->reason, $this->
getUser() );
445 if ( $status->isGood() ) {
458 $this->
getOutput()->setPageTitle( $this->
msg(
'actioncomplete' ) );
459 $this->
getOutput()->wrapWikiMsg(
"<div class=\"successbox\">\n$1\n</div>",
460 'tags-edit-success' );
461 $this->wasSaved =
true;
462 $this->revList->reloadFromMaster();
472 $this->
getOutput()->setPageTitle( $this->
msg(
'actionfailed' ) );
473 $this->
getOutput()->wrapWikiTextAsInterface(
474 'errorbox', $status->getWikiText(
'tags-edit-failure',
false, $this->getLanguage() )
480 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.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
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.
MediaWiki Linker LinkRenderer null $linkRenderer
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.