MediaWiki REL1_37
SpecialRevisionDelete.php
Go to the documentation of this file.
1<?php
26
35 protected $wasSaved = false;
36
39
41 private $ids;
42
44 private $archiveName;
45
47 private $token;
48
50 private $targetObj;
51
53 private $typeName;
54
56 private $checks;
57
59 private $typeLabels;
60
62 private $revDelList;
63
65 private $mIsAllowed;
66
68 private $otherReason;
69
72
74 private $repoGroup;
75
79 private const UI_LABELS = [
80 'revision' => [
81 'check-label' => 'revdelete-hide-text',
82 'success' => 'revdelete-success',
83 'failure' => 'revdelete-failure',
84 'text' => 'revdelete-text-text',
85 'selected' => 'revdelete-selected-text',
86 ],
87 'archive' => [
88 'check-label' => 'revdelete-hide-text',
89 'success' => 'revdelete-success',
90 'failure' => 'revdelete-failure',
91 'text' => 'revdelete-text-text',
92 'selected' => 'revdelete-selected-text',
93 ],
94 'oldimage' => [
95 'check-label' => 'revdelete-hide-image',
96 'success' => 'revdelete-success',
97 'failure' => 'revdelete-failure',
98 'text' => 'revdelete-text-file',
99 'selected' => 'revdelete-selected-file',
100 ],
101 'filearchive' => [
102 'check-label' => 'revdelete-hide-image',
103 'success' => 'revdelete-success',
104 'failure' => 'revdelete-failure',
105 'text' => 'revdelete-text-file',
106 'selected' => 'revdelete-selected-file',
107 ],
108 'logging' => [
109 'check-label' => 'revdelete-hide-name',
110 'success' => 'logdelete-success',
111 'failure' => 'logdelete-failure',
112 'text' => 'logdelete-text',
113 'selected' => 'logdelete-selected',
114 ],
115 ];
116
124 parent::__construct( 'Revisiondelete', 'deleterevision' );
125
126 $this->permissionManager = $permissionManager;
127 $this->repoGroup = $repoGroup;
128 }
129
130 public function doesWrites() {
131 return true;
132 }
133
134 public function execute( $par ) {
136
137 $this->checkPermissions();
138 $this->checkReadOnly();
139
140 $output = $this->getOutput();
141 $user = $this->getUser();
142
143 $this->setHeaders();
144 $this->outputHeader();
145 $request = $this->getRequest();
146 $this->submitClicked = $request->wasPosted() && $request->getBool( 'wpSubmit' );
147 # Handle our many different possible input types.
148 $ids = $request->getVal( 'ids' );
149 if ( $ids !== null ) {
150 # Allow CSV, for backwards compatibility, or a single ID for show/hide links
151 $this->ids = explode( ',', $ids );
152 } else {
153 # Array input
154 $this->ids = array_keys( $request->getArray( 'ids', [] ) );
155 }
156 // $this->ids = array_map( 'intval', $this->ids );
157 $this->ids = array_unique( array_filter( $this->ids ) );
158
159 $this->typeName = $request->getVal( 'type' );
160 $this->targetObj = Title::newFromText( $request->getText( 'target' ) );
161
162 # For reviewing deleted files...
163 $this->archiveName = $request->getVal( 'file' );
164 $this->token = $request->getVal( 'token' );
165 if ( $this->archiveName && $this->targetObj ) {
166 $this->tryShowFile( $this->archiveName );
167
168 return;
169 }
170
171 $this->typeName = RevisionDeleter::getCanonicalTypeName( $this->typeName );
172
173 # No targets?
174 if ( !$this->typeName || count( $this->ids ) == 0 ) {
175 throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
176 }
177
178 # Allow the list type to adjust the passed target
179 $this->targetObj = RevisionDeleter::suggestTarget(
180 $this->typeName,
181 $this->targetObj,
182 $this->ids
183 );
184
185 # We need a target page!
186 if ( $this->targetObj === null ) {
187 $output->addWikiMsg( 'undelete-header' );
188
189 return;
190 }
191
192 // Check blocks
193 $checkReplica = !$this->submitClicked;
194 if (
195 $this->permissionManager->isBlockedFrom(
196 $user,
197 $this->targetObj,
198 $checkReplica
199 )
200 ) {
201 throw new UserBlockedError(
202 $user->getBlock(),
203 $user,
204 $this->getLanguage(),
205 $request->getIP()
206 );
207 }
208
209 $this->typeLabels = self::UI_LABELS[$this->typeName];
210 $list = $this->getList();
211 $list->reset();
212 $this->mIsAllowed = $this->permissionManager->userHasRight( $user,
213 RevisionDeleter::getRestriction( $this->typeName ) );
214 $canViewSuppressedOnly = $this->permissionManager->userHasRight( $user, 'viewsuppressed' ) &&
215 !$this->permissionManager->userHasRight( $user, 'suppressrevision' );
216 $pageIsSuppressed = $list->areAnySuppressed();
217 $this->mIsAllowed = $this->mIsAllowed && !( $canViewSuppressedOnly && $pageIsSuppressed );
218
219 $this->otherReason = $request->getVal( 'wpReason' );
220 # Give a link to the logs/hist for this page
221 $this->showConvenienceLinks();
222
223 # Initialise checkboxes
224 $this->checks = [
225 # Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name
226 [ $this->typeLabels['check-label'], 'wpHidePrimary',
227 RevisionDeleter::getRevdelConstant( $this->typeName )
228 ],
229 [ 'revdelete-hide-comment', 'wpHideComment', RevisionRecord::DELETED_COMMENT ],
230 [ 'revdelete-hide-user', 'wpHideUser', RevisionRecord::DELETED_USER ]
231 ];
232 if ( $this->permissionManager->userHasRight( $user, 'suppressrevision' ) ) {
233 $this->checks[] = [ 'revdelete-hide-restricted',
234 'wpHideRestricted', RevisionRecord::DELETED_RESTRICTED ];
235 }
236
237 # Either submit or create our form
238 if ( $this->mIsAllowed && $this->submitClicked ) {
239 $this->submit();
240 } else {
241 $this->showForm();
242 }
243
244 if ( $this->permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
245 # Show relevant lines from the deletion log
246 $deleteLogPage = new LogPage( 'delete' );
247 $output->addHTML( "<h2>" . $deleteLogPage->getName()->escaped() . "</h2>\n" );
248 LogEventsList::showLogExtract(
249 $output,
250 'delete',
251 $this->targetObj,
252 '', /* user */
253 [ 'lim' => 25, 'conds' => $this->getLogQueryCond(), 'useMaster' => $this->wasSaved ]
254 );
255 }
256 # Show relevant lines from the suppression log
257 if ( $this->permissionManager->userHasRight( $user, 'suppressionlog' ) ) {
258 $suppressLogPage = new LogPage( 'suppress' );
259 $output->addHTML( "<h2>" . $suppressLogPage->getName()->escaped() . "</h2>\n" );
260 LogEventsList::showLogExtract(
261 $output,
262 'suppress',
263 $this->targetObj,
264 '',
265 [ 'lim' => 25, 'conds' => $this->getLogQueryCond(), 'useMaster' => $this->wasSaved ]
266 );
267 }
268 }
269
273 protected function showConvenienceLinks() {
275 # Give a link to the logs/hist for this page
276 if ( $this->targetObj ) {
277 // Also set header tabs to be for the target.
278 $this->getSkin()->setRelevantTitle( $this->targetObj );
279
280 $links = [];
281 $links[] = $linkRenderer->makeKnownLink(
283 $this->msg( 'viewpagelogs' )->text(),
284 [],
285 [ 'page' => $this->targetObj->getPrefixedText() ]
286 );
287 if ( !$this->targetObj->isSpecialPage() ) {
288 # Give a link to the page history
289 $links[] = $linkRenderer->makeKnownLink(
290 $this->targetObj,
291 $this->msg( 'pagehist' )->text(),
292 [],
293 [ 'action' => 'history' ]
294 );
295 # Link to deleted edits
296 if ( $this->permissionManager->userHasRight( $this->getUser(), 'undelete' ) ) {
297 $undelete = SpecialPage::getTitleFor( 'Undelete' );
298 $links[] = $linkRenderer->makeKnownLink(
299 $undelete,
300 $this->msg( 'deletedhist' )->text(),
301 [],
302 [ 'target' => $this->targetObj->getPrefixedDBkey() ]
303 );
304 }
305 }
306 # Logs themselves don't have histories or archived revisions
307 $this->getOutput()->addSubtitle( $this->getLanguage()->pipeList( $links ) );
308 }
309 }
310
315 protected function getLogQueryCond() {
316 $conds = [];
317 // Revision delete logs for these item
318 $conds['log_type'] = [ 'delete', 'suppress' ];
319 $conds['log_action'] = $this->getList()->getLogAction();
320 $conds['ls_field'] = RevisionDeleter::getRelationType( $this->typeName );
321 // Convert IDs to strings, since ls_value is a text field. This avoids
322 // a fatal error in PostgreSQL: "operator does not exist: text = integer".
323 $conds['ls_value'] = array_map( 'strval', $this->ids );
324
325 return $conds;
326 }
327
335 protected function tryShowFile( $archiveName ) {
336 $repo = $this->repoGroup->getLocalRepo();
337 $oimage = $repo->newFromArchiveName( $this->targetObj, $archiveName );
338 $oimage->load();
339 // Check if user is allowed to see this file
340 if ( !$oimage->exists() ) {
341 $this->getOutput()->addWikiMsg( 'revdelete-no-file' );
342
343 return;
344 }
345 $user = $this->getUser();
346 if ( !$oimage->userCan( File::DELETED_FILE, $user ) ) {
347 if ( $oimage->isDeleted( File::DELETED_RESTRICTED ) ) {
348 throw new PermissionsError( 'suppressrevision' );
349 } else {
350 throw new PermissionsError( 'deletedtext' );
351 }
352 }
353 if ( !$user->matchEditToken( $this->token, $archiveName ) ) {
354 $lang = $this->getLanguage();
355 $this->getOutput()->addWikiMsg( 'revdelete-show-file-confirm',
356 $this->targetObj->getText(),
357 $lang->userDate( $oimage->getTimestamp(), $user ),
358 $lang->userTime( $oimage->getTimestamp(), $user ) );
359 $this->getOutput()->addHTML(
360 Xml::openElement( 'form', [
361 'method' => 'POST',
362 'action' => $this->getPageTitle()->getLocalURL( [
363 'target' => $this->targetObj->getPrefixedDBkey(),
364 'file' => $archiveName,
365 'token' => $user->getEditToken( $archiveName ),
366 ] )
367 ]
368 ) .
369 Xml::submitButton( $this->msg( 'revdelete-show-file-submit' )->text() ) .
370 '</form>'
371 );
372
373 return;
374 }
375 $this->getOutput()->disable();
376 # We mustn't allow the output to be CDN cached, otherwise
377 # if an admin previews a deleted image, and it's cached, then
378 # a user without appropriate permissions can toddle off and
379 # nab the image, and CDN will serve it
380 $this->getRequest()->response()->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
381 $this->getRequest()->response()->header(
382 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate'
383 );
384 $this->getRequest()->response()->header( 'Pragma: no-cache' );
385
386 $key = $oimage->getStorageKey();
387 $path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key;
388 $repo->streamFileWithStatus( $path );
389 }
390
395 protected function getList() {
396 if ( $this->revDelList === null ) {
397 $this->revDelList = RevisionDeleter::createList(
398 $this->typeName, $this->getContext(), $this->targetObj, $this->ids
399 );
400 }
401
402 return $this->revDelList;
403 }
404
409 protected function showForm() {
410 $userAllowed = true;
411
412 // Messages: revdelete-selected-text, revdelete-selected-file, logdelete-selected
413 $out = $this->getOutput();
414 $out->wrapWikiMsg( "<strong>$1</strong>", [ $this->typeLabels['selected'],
415 $this->getLanguage()->formatNum( count( $this->ids ) ), $this->targetObj->getPrefixedText() ] );
416
417 $this->addHelpLink( 'Help:RevisionDelete' );
418 $out->addHTML( "<ul>" );
419
420 $numRevisions = 0;
421 // Live revisions...
422 $list = $this->getList();
423 for ( $list->reset(); $list->current(); $list->next() ) {
424 $item = $list->current();
425
426 if ( !$item->canView() ) {
427 if ( !$this->submitClicked ) {
428 throw new PermissionsError( 'suppressrevision' );
429 }
430 $userAllowed = false;
431 }
432
433 $numRevisions++;
434 $out->addHTML( $item->getHTML() );
435 }
436
437 if ( !$numRevisions ) {
438 throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
439 }
440
441 $out->addHTML( "</ul>" );
442 // Explanation text
443 $this->addUsageText();
444
445 // Normal sysops can always see what they did, but can't always change it
446 if ( !$userAllowed ) {
447 return;
448 }
449
450 // Show form if the user can submit
451 if ( $this->mIsAllowed ) {
452 $suppressAllowed = $this->permissionManager
453 ->userHasRight( $this->getUser(), 'suppressrevision' );
454 $out->addModules( [ 'mediawiki.special.revisionDelete' ] );
455 $out->addModuleStyles( [ 'mediawiki.special',
456 'mediawiki.interface.helpers.styles' ] );
457
458 $dropDownReason = $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->text();
459 // Add additional specific reasons for suppress
460 if ( $suppressAllowed ) {
461 $dropDownReason .= "\n" . $this->msg( 'revdelete-reason-dropdown-suppress' )
462 ->inContentLanguage()->text();
463 }
464
465 $form = Xml::openElement( 'form', [ 'method' => 'post',
466 'action' => $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] ),
467 'id' => 'mw-revdel-form-revisions' ] ) .
468 Xml::fieldset( $this->msg( 'revdelete-legend' )->text() ) .
469 $this->buildCheckBoxes() .
470 Xml::openElement( 'table' ) .
471 "<tr>\n" .
472 '<td class="mw-label">' .
473 Xml::label( $this->msg( 'revdelete-log' )->text(), 'wpRevDeleteReasonList' ) .
474 '</td>' .
475 '<td class="mw-input">' .
476 Xml::listDropDown( 'wpRevDeleteReasonList',
477 $dropDownReason,
478 $this->msg( 'revdelete-reasonotherlist' )->inContentLanguage()->text(),
479 $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' ), 'wpReasonDropDown'
480 ) .
481 '</td>' .
482 "</tr><tr>\n" .
483 '<td class="mw-label">' .
484 Xml::label( $this->msg( 'revdelete-otherreason' )->text(), 'wpReason' ) .
485 '</td>' .
486 '<td class="mw-input">' .
487 Xml::input( 'wpReason', 60, $this->otherReason, [
488 'id' => 'wpReason',
489 // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
490 // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
491 // Unicode codepoints.
492 // "- 155" is to leave room for the 'wpRevDeleteReasonList' value.
493 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT - 155,
494 ] ) .
495 '</td>' .
496 "</tr><tr>\n" .
497 '<td></td>' .
498 '<td class="mw-submit">' .
499 Xml::submitButton( $this->msg( 'revdelete-submit', $numRevisions )->text(),
500 [ 'name' => 'wpSubmit' ] ) .
501 '</td>' .
502 "</tr>\n" .
503 Xml::closeElement( 'table' ) .
504 Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ) .
505 Html::hidden( 'target', $this->targetObj->getPrefixedText() ) .
506 Html::hidden( 'type', $this->typeName ) .
507 Html::hidden( 'ids', implode( ',', $this->ids ) ) .
508 Xml::closeElement( 'fieldset' ) . "\n" .
509 Xml::closeElement( 'form' ) . "\n";
510 // Show link to edit the dropdown reasons
511 if ( $this->permissionManager->userHasRight( $this->getUser(), 'editinterface' ) ) {
512 $link = '';
514 if ( $suppressAllowed ) {
516 $this->msg( 'revdelete-reason-dropdown-suppress' )->inContentLanguage()->getTitle(),
517 $this->msg( 'revdelete-edit-reasonlist-suppress' )->text(),
518 [],
519 [ 'action' => 'edit' ]
520 );
521 $link .= $this->msg( 'pipe-separator' )->escaped();
522 }
524 $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->getTitle(),
525 $this->msg( 'revdelete-edit-reasonlist' )->text(),
526 [],
527 [ 'action' => 'edit' ]
528 );
529 $form .= Xml::tags( 'p', [ 'class' => 'mw-revdel-editreasons' ], $link ) . "\n";
530 }
531 } else {
532 $form = '';
533 }
534 $out->addHTML( $form );
535 }
536
541 protected function addUsageText() {
542 // Messages: revdelete-text-text, revdelete-text-file, logdelete-text
543 $this->getOutput()->wrapWikiMsg(
544 "<strong>$1</strong>\n$2", $this->typeLabels['text'],
545 'revdelete-text-others'
546 );
547
548 if ( $this->permissionManager->userHasRight( $this->getUser(), 'suppressrevision' ) ) {
549 $this->getOutput()->addWikiMsg( 'revdelete-suppress-text' );
550 }
551
552 if ( $this->mIsAllowed ) {
553 $this->getOutput()->addWikiMsg( 'revdelete-confirm' );
554 }
555 }
556
560 protected function buildCheckBoxes() {
561 $html = '<table>';
562 // If there is just one item, use checkboxes
563 $list = $this->getList();
564 if ( $list->length() == 1 ) {
565 $list->reset();
566 $bitfield = $list->current()->getBits(); // existing field
567
568 if ( $this->submitClicked ) {
569 $bitfield = RevisionDeleter::extractBitfield( $this->extractBitParams(), $bitfield );
570 }
571
572 foreach ( $this->checks as $item ) {
573 // Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
574 // revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
575 list( $message, $name, $field ) = $item;
576 $innerHTML = Xml::checkLabel(
577 $this->msg( $message )->text(),
578 $name,
579 $name,
580 $bitfield & $field
581 );
582
583 if ( $field == RevisionRecord::DELETED_RESTRICTED ) {
584 $innerHTML = "<b>$innerHTML</b>";
585 }
586
587 $line = Xml::tags( 'td', [ 'class' => 'mw-input' ], $innerHTML );
588 $html .= "<tr>$line</tr>\n";
589 }
590 } else {
591 // Otherwise, use tri-state radios
592 $html .= '<tr>';
593 $html .= '<th class="mw-revdel-checkbox">'
594 . $this->msg( 'revdelete-radio-same' )->escaped() . '</th>';
595 $html .= '<th class="mw-revdel-checkbox">'
596 . $this->msg( 'revdelete-radio-unset' )->escaped() . '</th>';
597 $html .= '<th class="mw-revdel-checkbox">'
598 . $this->msg( 'revdelete-radio-set' )->escaped() . '</th>';
599 $html .= "<th></th></tr>\n";
600 foreach ( $this->checks as $item ) {
601 // Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
602 // revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
603 list( $message, $name, $field ) = $item;
604 // If there are several items, use third state by default...
605 if ( $this->submitClicked ) {
606 $selected = $this->getRequest()->getInt( $name, 0 /* unchecked */ );
607 } else {
608 $selected = -1; // use existing field
609 }
610 $line = '<td class="mw-revdel-checkbox">' . Xml::radio( $name, -1, $selected == -1 ) . '</td>';
611 $line .= '<td class="mw-revdel-checkbox">' . Xml::radio( $name, 0, $selected == 0 ) . '</td>';
612 $line .= '<td class="mw-revdel-checkbox">' . Xml::radio( $name, 1, $selected == 1 ) . '</td>';
613 $label = $this->msg( $message )->escaped();
614 if ( $field == RevisionRecord::DELETED_RESTRICTED ) {
615 $label = "<b>$label</b>";
616 }
617 $line .= "<td>$label</td>";
618 $html .= "<tr>$line</tr>\n";
619 }
620 }
621
622 $html .= '</table>';
623
624 return $html;
625 }
626
632 protected function submit() {
633 # Check edit token on submission
634 $token = $this->getRequest()->getVal( 'wpEditToken' );
635 if ( $this->submitClicked && !$this->getUser()->matchEditToken( $token ) ) {
636 $this->getOutput()->addWikiMsg( 'sessionfailure' );
637
638 return false;
639 }
640 $bitParams = $this->extractBitParams();
641 // from dropdown
642 $listReason = $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' );
643 $comment = $listReason;
644 if ( $comment === 'other' ) {
645 $comment = $this->otherReason;
646 } elseif ( $this->otherReason !== '' ) {
647 // Entry from drop down menu + additional comment
648 $comment .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
650 }
651 # Can the user set this field?
652 if ( $bitParams[RevisionRecord::DELETED_RESTRICTED] == 1
653 && !$this->permissionManager->userHasRight( $this->getUser(), 'suppressrevision' )
654 ) {
655 throw new PermissionsError( 'suppressrevision' );
656 }
657 # If the save went through, go to success message...
658 $status = $this->save( $bitParams, $comment );
659 if ( $status->isGood() ) {
660 $this->success();
661
662 return true;
663 } else {
664 # ...otherwise, bounce back to form...
665 $this->failure( $status );
666 }
667
668 return false;
669 }
670
674 protected function success() {
675 // Messages: revdelete-success, logdelete-success
676 $this->getOutput()->setPageTitle( $this->msg( 'actioncomplete' ) );
677 $this->getOutput()->wrapWikiMsg(
678 "<div class=\"successbox\">\n$1\n</div>",
679 $this->typeLabels['success']
680 );
681 $this->wasSaved = true;
682 $this->revDelList->reloadFromPrimary();
683 $this->showForm();
684 }
685
690 protected function failure( $status ) {
691 // Messages: revdelete-failure, logdelete-failure
692 $this->getOutput()->setPageTitle( $this->msg( 'actionfailed' ) );
693 $this->getOutput()->wrapWikiTextAsInterface(
694 'errorbox',
695 $status->getWikiText( $this->typeLabels['failure'], false, $this->getLanguage() )
696 );
697 $this->showForm();
698 }
699
705 protected function extractBitParams() {
706 $bitfield = [];
707 foreach ( $this->checks as $item ) {
708 list( /* message */, $name, $field ) = $item;
709 $val = $this->getRequest()->getInt( $name, 0 /* unchecked */ );
710 if ( $val < -1 || $val > 1 ) {
711 $val = -1; // -1 for existing value
712 }
713 $bitfield[$field] = $val;
714 }
715 if ( !isset( $bitfield[RevisionRecord::DELETED_RESTRICTED] ) ) {
716 $bitfield[RevisionRecord::DELETED_RESTRICTED] = 0;
717 }
718
719 return $bitfield;
720 }
721
728 protected function save( array $bitPars, $reason ) {
729 return $this->getList()->setVisibility(
730 [ 'value' => $bitPars, 'comment' => $reason ]
731 );
732 }
733
734 protected function getGroupName() {
735 return 'pagetools';
736 }
737}
An error page which can definitely be safely rendered using the OutputPage.
Class to simplify the use of log pages.
Definition LogPage.php:38
makeKnownLink( $target, $text=null, array $extraAttribs=[], array $query=[])
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Page revision base class.
Show an error when a user tries to do something they do not have the necessary permissions for.
Prioritized list of file repositories.
Definition RepoGroup.php:33
static getCanonicalTypeName( $typeName)
Gets the canonical type name, if any.
static getRelationType( $typeName)
Get DB field name for URL param... Future code for other things may also track other types of revisio...
static suggestTarget( $typeName, $target, array $ids)
Suggest a target for the revision deletion.
static extractBitfield(array $bitPars, $oldfield)
Put together a rev_deleted bitfield.
static getRevdelConstant( $typeName)
Get the revision deletion constant for the RevDel type.
static getRestriction( $typeName)
Get the user right required for the RevDel type.
static createList( $typeName, IContextSource $context, PageIdentity $page, array $ids)
Instantiate the appropriate list class for a given list of IDs.
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.
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.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Special page allowing users with the appropriate permissions to view and hide revisions.
string $token
Edit token for securing image views against XSS.
bool $mIsAllowed
Whether user is allowed to perform the action.
const UI_LABELS
UI labels for each type.
showForm()
Show a list of items that we will operate on, and show a form with checkboxes which will allow the us...
tryShowFile( $archiveName)
Show a deleted file version requested by the visitor.
string $archiveName
Archive name, for reviewing deleted files.
save(array $bitPars, $reason)
Do the write operations.
success()
Report that the submit operation succeeded.
addUsageText()
Show some introductory text.
array $typeLabels
UI Labels about the current type.
bool $wasSaved
Was the DB modified in this request.
getLogQueryCond()
Get the condition used for fetching log snippets.
PermissionManager $permissionManager
RevDelList $revDelList
RevDelList object, storing the list of items to be deleted/undeleted.
showConvenienceLinks()
Show some useful links in the subtitle.
doesWrites()
Indicates whether this special page may perform database writes.
execute( $par)
Default execute method Checks user permissions.
array $checks
Array of checkbox specs (message, name, deletion bits)
failure( $status)
Report that the submit operation failed.
__construct(PermissionManager $permissionManager, RepoGroup $repoGroup)
submit()
UI entry point for form submission.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Title $targetObj
Title object for target parameter.
extractBitParams()
Put together an array that contains -1, 0, or the *_deleted const for each bit.
bool $submitClicked
True if the submit button was clicked, and the form was posted.
string $typeName
Deletion type, may be revision, archive, oldimage, filearchive, logging.
getList()
Get the list object for this request.
array $ids
Target ID list.
Represents a title within MediaWiki.
Definition Title.php:48
Shortcut to construct a special page which is unlisted by default.
Show an error when the user tries to do something whilst blocked.
$line
Definition mcc.php:119
if(!isset( $args[0])) $lang