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 ( !is_null(
$ids ) ) {
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 ( is_null( $this->targetObj ) ) {
137 $output->addWikiMsg(
'undelete-header' );
142 if ( $this->permissionManager->isBlockedFrom( $user, $this->targetObj ) ) {
150 if ( $this->isAllowed && $this->submitClicked ) {
157 $tagLogPage =
new LogPage(
'tag' );
158 $output->addHTML(
"<h2>" . $tagLogPage->getName()->escaped() .
"</h2>\n" );
164 [
'lim' => 25,
'conds' => [],
'useMaster' => $this->wasSaved ]
173 if ( $this->targetObj ) {
175 $this->
getSkin()->setRelevantTitle( $this->targetObj );
181 $this->
msg(
'viewpagelogs' )->text(),
184 'page' => $this->targetObj->getPrefixedText(),
185 'wpfilters' => [
'tag' ],
188 if ( !$this->targetObj->isSpecialPage() ) {
192 $this->
msg(
'pagehist' )->text(),
194 [
'action' =>
'history' ]
200 $this->
msg(
'tags-edit-manage-link' )->text()
212 if ( is_null( $this->revList ) ) {
214 $this->targetObj, $this->ids );
227 $out->wrapWikiMsg(
"<strong>$1</strong>", [
228 "tags-edit-{$this->typeName}-selected",
229 $this->
getLanguage()->formatNum( count( $this->ids ) ),
230 $this->targetObj->getPrefixedText()
234 $out->addHTML(
"<ul>" );
239 for ( $list->reset(); $list->current(); $list->next() ) {
240 $item = $list->current();
241 if ( !$item->canView() ) {
242 throw new ErrorPageError(
'permissionserrors',
'tags-update-no-permission' );
245 $out->addHTML( $item->getHTML() );
248 if ( !$numRevisions ) {
249 throw new ErrorPageError(
'tags-edit-nooldid-title',
'tags-edit-nooldid-text' );
252 $out->addHTML(
"</ul>" );
254 $out->wrapWikiMsg(
'<p>$1</p>',
"tags-edit-{$this->typeName}-explanation" );
257 if ( $this->isAllowed ) {
258 $form = Xml::openElement(
'form', [
'method' =>
'post',
259 'action' => $this->
getPageTitle()->getLocalURL( [
'action' =>
'submit' ] ),
260 'id' =>
'mw-revdel-form-revisions' ] ) .
261 Xml::fieldset( $this->
msg(
"tags-edit-{$this->typeName}-legend",
262 count( $this->ids ) )->text() ) .
264 Xml::openElement(
'table' ) .
266 '<td class="mw-label">' .
267 Xml::label( $this->
msg(
'tags-edit-reason' )->text(),
'wpReason' ) .
269 '<td class="mw-input">' .
270 Xml::input(
'wpReason', 60, $this->reason, [
275 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
280 '<td class="mw-submit">' .
281 Xml::submitButton( $this->
msg(
"tags-edit-{$this->typeName}-submit",
282 $numRevisions )->text(), [
'name' =>
'wpSubmit' ] ) .
285 Xml::closeElement(
'table' ) .
286 Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken() ) .
287 Html::hidden(
'target', $this->targetObj->getPrefixedText() ) .
288 Html::hidden(
'type', $this->typeName ) .
289 Html::hidden(
'ids', implode(
',', $this->ids ) ) .
290 Xml::closeElement(
'fieldset' ) .
"\n" .
291 Xml::closeElement(
'form' ) .
"\n";
295 $out->addHTML( $form );
305 if ( $list->length() == 1 ) {
307 $tags = $list->current()->getTags();
309 $tags = explode(
',', $tags );
314 $html =
'<table id="mw-edittags-tags-selector">';
315 $html .=
'<tr><td>' . $this->
msg(
'tags-edit-existing-tags' )->escaped() .
318 $html .= $this->
getLanguage()->commaList( array_map(
'htmlspecialchars', $tags ) );
320 $html .= $this->
msg(
'tags-edit-existing-tags-none' )->parse();
322 $html .=
'</td></tr>';
323 $tagSelect = $this->
getTagSelect( $tags, $this->
msg(
'tags-edit-new-tags' )->plain() );
324 $html .=
'<tr><td>' . $tagSelect[0] .
'</td><td>' . $tagSelect[1];
329 for ( $list->reset(); $list->current(); $list->next() ) {
330 $currentTags = $list->current()->getTags();
331 if ( $currentTags ) {
332 $tags = array_merge( $tags, explode(
',', $currentTags ) );
335 $tags = array_unique( $tags );
337 $html =
'<table id="mw-edittags-tags-selector-multi"><tr><td>';
338 $tagSelect = $this->
getTagSelect( [], $this->
msg(
'tags-edit-add' )->plain() );
339 $html .=
'<p>' . $tagSelect[0] .
'</p>' . $tagSelect[1] .
'</td><td>';
340 $html .= Xml::element(
'p',
null, $this->
msg(
'tags-edit-remove' )->plain() );
341 $html .= Xml::checkLabel( $this->
msg(
'tags-edit-remove-all-tags' )->plain(),
342 'wpRemoveAllTags',
'mw-edittags-remove-all' );
344 foreach ( $tags as $tag ) {
345 $html .= Xml::element(
'br' ) .
"\n" . Xml::checkLabel( $tag,
346 'wpTagsToRemove[]',
'mw-edittags-remove-' . $i++,
false, [
348 'class' =>
'mw-edittags-remove-checkbox',
355 $html .= Html::hidden(
'wpExistingTags', implode(
',', $tags ) );
356 $html .=
'</td></tr></table>';
375 $result[0] = Xml::label( $label,
'mw-edittags-tag-list' );
377 $select =
new XmlSelect(
'wpTagList[]',
'mw-edittags-tag-list', $selectedTags );
378 $select->setAttribute(
'multiple',
'multiple' );
379 $select->setAttribute(
'size',
'8' );
382 $tags = array_unique( array_merge( $tags, $selectedTags ) );
385 $select->addOptions( array_combine( $tags, $tags ) );
387 $result[1] = $select->getHTML();
398 $token = $request->getVal(
'wpEditToken' );
399 if ( $this->submitClicked && !$this->
getUser()->matchEditToken( $token ) ) {
400 $this->
getOutput()->addWikiMsg(
'sessionfailure' );
405 $tagList = $request->getArray(
'wpTagList' );
406 if ( is_null( $tagList ) ) {
409 $existingTags = $request->getVal(
'wpExistingTags' );
410 if ( is_null( $existingTags ) || $existingTags ===
'' ) {
413 $existingTags = explode(
',', $existingTags );
416 if ( count( $this->ids ) > 1 ) {
418 $tagsToAdd = $tagList;
419 if ( $request->getBool(
'wpRemoveAllTags' ) ) {
420 $tagsToRemove = $existingTags;
422 $tagsToRemove = $request->getArray(
'wpTagsToRemove' );
428 $tagsToAdd = array_diff( $tagList, $existingTags );
429 $tagsToRemove = array_diff( $existingTags, $tagList );
432 if ( !$tagsToAdd && !$tagsToRemove ) {
433 $status = Status::newFatal(
'tags-edit-none-selected' );
435 $status = $this->
getList()->updateChangeTagsOnAll( $tagsToAdd,
436 $tagsToRemove,
null, $this->reason, $this->
getUser() );
439 if ( $status->isGood() ) {
452 $this->
getOutput()->setPageTitle( $this->
msg(
'actioncomplete' ) );
453 $this->
getOutput()->wrapWikiMsg(
"<div class=\"successbox\">\n$1\n</div>",
454 'tags-edit-success' );
455 $this->wasSaved =
true;
456 $this->revList->reloadFromMaster();
466 $this->
getOutput()->setPageTitle( $this->
msg(
'actionfailed' ) );
467 $this->
getOutput()->wrapWikiTextAsInterface(
468 'errorbox', $status->getWikiText(
'tags-edit-failure',
false, $this->getLanguage() )
474 return $this->
msg(
'tags-edit-title' )->text();
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.
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.