MediaWiki REL1_39
SpecialRevisionDelete.php
Go to the documentation of this file.
1<?php
26
35 protected $wasSaved = false;
36
38 private $submitClicked;
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
71 private $permissionManager;
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
123 public function __construct( PermissionManager $permissionManager, RepoGroup $repoGroup ) {
124 parent::__construct( 'Revisiondelete' );
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 $restriction = RevisionDeleter::getRestriction( $this->typeName );
179
180 if ( !$this->getAuthority()->isAllowedAny( $restriction, 'deletedhistory' ) ) {
181 throw new PermissionsError( $restriction );
182 }
183
184 # Allow the list type to adjust the passed target
185 $this->targetObj = RevisionDeleter::suggestTarget(
186 $this->typeName,
187 $this->targetObj,
188 $this->ids
189 );
190
191 # We need a target page!
192 if ( $this->targetObj === null ) {
193 $output->addWikiMsg( 'undelete-header' );
194
195 return;
196 }
197
198 // Check blocks
199 $checkReplica = !$this->submitClicked;
200 if (
201 $this->permissionManager->isBlockedFrom(
202 $user,
203 $this->targetObj,
204 $checkReplica
205 )
206 ) {
207 throw new UserBlockedError(
208 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable Block is checked and not null
209 $user->getBlock(),
210 $user,
211 $this->getLanguage(),
212 $request->getIP()
213 );
214 }
215
216 $this->typeLabels = self::UI_LABELS[$this->typeName];
217 $list = $this->getList();
218 $list->reset();
219 $this->mIsAllowed = $this->permissionManager->userHasRight( $user, $restriction );
220 $canViewSuppressedOnly = $this->permissionManager->userHasRight( $user, 'viewsuppressed' ) &&
221 !$this->permissionManager->userHasRight( $user, 'suppressrevision' );
222 $pageIsSuppressed = $list->areAnySuppressed();
223 $this->mIsAllowed = $this->mIsAllowed && !( $canViewSuppressedOnly && $pageIsSuppressed );
224
225 $this->otherReason = $request->getVal( 'wpReason', '' );
226 # Give a link to the logs/hist for this page
227 $this->showConvenienceLinks();
228
229 # Initialise checkboxes
230 $this->checks = [
231 # Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name
232 [ $this->typeLabels['check-label'], 'wpHidePrimary',
233 RevisionDeleter::getRevdelConstant( $this->typeName )
234 ],
235 [ 'revdelete-hide-comment', 'wpHideComment', RevisionRecord::DELETED_COMMENT ],
236 [ 'revdelete-hide-user', 'wpHideUser', RevisionRecord::DELETED_USER ]
237 ];
238 if ( $this->permissionManager->userHasRight( $user, 'suppressrevision' ) ) {
239 $this->checks[] = [ 'revdelete-hide-restricted',
240 'wpHideRestricted', RevisionRecord::DELETED_RESTRICTED ];
241 }
242
243 # Either submit or create our form
244 if ( $this->mIsAllowed && $this->submitClicked ) {
245 $this->submit();
246 } else {
247 $this->showForm();
248 }
249
250 if ( $this->permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
251 # Show relevant lines from the deletion log
252 $deleteLogPage = new LogPage( 'delete' );
253 $output->addHTML( "<h2>" . $deleteLogPage->getName()->escaped() . "</h2>\n" );
254 LogEventsList::showLogExtract(
255 $output,
256 'delete',
257 $this->targetObj,
258 '', /* user */
259 [ 'lim' => 25, 'conds' => $this->getLogQueryCond(), 'useMaster' => $this->wasSaved ]
260 );
261 }
262 # Show relevant lines from the suppression log
263 if ( $this->permissionManager->userHasRight( $user, 'suppressionlog' ) ) {
264 $suppressLogPage = new LogPage( 'suppress' );
265 $output->addHTML( "<h2>" . $suppressLogPage->getName()->escaped() . "</h2>\n" );
266 LogEventsList::showLogExtract(
267 $output,
268 'suppress',
269 $this->targetObj,
270 '',
271 [ 'lim' => 25, 'conds' => $this->getLogQueryCond(), 'useMaster' => $this->wasSaved ]
272 );
273 }
274 }
275
279 protected function showConvenienceLinks() {
280 $linkRenderer = $this->getLinkRenderer();
281 # Give a link to the logs/hist for this page
282 if ( $this->targetObj ) {
283 // Also set header tabs to be for the target.
284 $this->getSkin()->setRelevantTitle( $this->targetObj );
285
286 $links = [];
287 $links[] = $linkRenderer->makeKnownLink(
289 $this->msg( 'viewpagelogs' )->text(),
290 [],
291 [ 'page' => $this->targetObj->getPrefixedText() ]
292 );
293 if ( !$this->targetObj->isSpecialPage() ) {
294 # Give a link to the page history
295 $links[] = $linkRenderer->makeKnownLink(
296 $this->targetObj,
297 $this->msg( 'pagehist' )->text(),
298 [],
299 [ 'action' => 'history' ]
300 );
301 # Link to deleted edits
302 if ( $this->permissionManager->userHasRight( $this->getUser(), 'undelete' ) ) {
303 $undelete = SpecialPage::getTitleFor( 'Undelete' );
304 $links[] = $linkRenderer->makeKnownLink(
305 $undelete,
306 $this->msg( 'deletedhist' )->text(),
307 [],
308 [ 'target' => $this->targetObj->getPrefixedDBkey() ]
309 );
310 }
311 }
312 # Logs themselves don't have histories or archived revisions
313 $this->getOutput()->addSubtitle( $this->getLanguage()->pipeList( $links ) );
314 }
315 }
316
321 protected function getLogQueryCond() {
322 $conds = [];
323 // Revision delete logs for these item
324 $conds['log_type'] = [ 'delete', 'suppress' ];
325 $conds['log_action'] = $this->getList()->getLogAction();
326 $conds['ls_field'] = RevisionDeleter::getRelationType( $this->typeName );
327 // Convert IDs to strings, since ls_value is a text field. This avoids
328 // a fatal error in PostgreSQL: "operator does not exist: text = integer".
329 $conds['ls_value'] = array_map( 'strval', $this->ids );
330
331 return $conds;
332 }
333
341 protected function tryShowFile( $archiveName ) {
342 $repo = $this->repoGroup->getLocalRepo();
343 $oimage = $repo->newFromArchiveName( $this->targetObj, $archiveName );
344 $oimage->load();
345 // Check if user is allowed to see this file
346 if ( !$oimage->exists() ) {
347 $this->getOutput()->addWikiMsg( 'revdelete-no-file' );
348
349 return;
350 }
351 $user = $this->getUser();
352 if ( !$oimage->userCan( File::DELETED_FILE, $user ) ) {
353 if ( $oimage->isDeleted( File::DELETED_RESTRICTED ) ) {
354 throw new PermissionsError( 'suppressrevision' );
355 } else {
356 throw new PermissionsError( 'deletedtext' );
357 }
358 }
359 if ( !$user->matchEditToken( $this->token, $archiveName ) ) {
360 $lang = $this->getLanguage();
361 $this->getOutput()->addWikiMsg( 'revdelete-show-file-confirm',
362 $this->targetObj->getText(),
363 $lang->userDate( $oimage->getTimestamp(), $user ),
364 $lang->userTime( $oimage->getTimestamp(), $user ) );
365 $this->getOutput()->addHTML(
366 Xml::openElement( 'form', [
367 'method' => 'POST',
368 'action' => $this->getPageTitle()->getLocalURL( [
369 'target' => $this->targetObj->getPrefixedDBkey(),
370 'file' => $archiveName,
371 'token' => $user->getEditToken( $archiveName ),
372 ] )
373 ]
374 ) .
375 Xml::submitButton( $this->msg( 'revdelete-show-file-submit' )->text() ) .
376 '</form>'
377 );
378
379 return;
380 }
381 $this->getOutput()->disable();
382 # We mustn't allow the output to be CDN cached, otherwise
383 # if an admin previews a deleted image, and it's cached, then
384 # a user without appropriate permissions can toddle off and
385 # nab the image, and CDN will serve it
386 $this->getRequest()->response()->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
387 $this->getRequest()->response()->header(
388 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate'
389 );
390 $this->getRequest()->response()->header( 'Pragma: no-cache' );
391
392 $key = $oimage->getStorageKey();
393 $path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key;
394 $repo->streamFileWithStatus( $path );
395 }
396
401 protected function getList() {
402 if ( $this->revDelList === null ) {
403 $this->revDelList = RevisionDeleter::createList(
404 $this->typeName, $this->getContext(), $this->targetObj, $this->ids
405 );
406 }
407
408 return $this->revDelList;
409 }
410
415 protected function showForm() {
416 $userAllowed = true;
417
418 // Messages: revdelete-selected-text, revdelete-selected-file, logdelete-selected
419 $out = $this->getOutput();
420 $out->wrapWikiMsg( "<strong>$1</strong>", [ $this->typeLabels['selected'],
421 $this->getLanguage()->formatNum( count( $this->ids ) ), $this->targetObj->getPrefixedText() ] );
422
423 $this->addHelpLink( 'Help:RevisionDelete' );
424 $out->addHTML( "<ul>" );
425
426 $numRevisions = 0;
427 // Live revisions...
428 $list = $this->getList();
429 for ( $list->reset(); $list->current(); $list->next() ) {
430 $item = $list->current();
431
432 if ( !$item->canView() ) {
433 if ( !$this->submitClicked ) {
434 throw new PermissionsError( 'suppressrevision' );
435 }
436 $userAllowed = false;
437 }
438
439 $numRevisions++;
440 $out->addHTML( $item->getHTML() );
441 }
442
443 if ( !$numRevisions ) {
444 throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
445 }
446
447 $out->addHTML( "</ul>" );
448 // Explanation text
449 $this->addUsageText();
450
451 // Normal sysops can always see what they did, but can't always change it
452 if ( !$userAllowed ) {
453 return;
454 }
455
456 // Show form if the user can submit
457 if ( $this->mIsAllowed ) {
458 $suppressAllowed = $this->permissionManager
459 ->userHasRight( $this->getUser(), 'suppressrevision' );
460 $out->addModules( [ 'mediawiki.special.revisionDelete' ] );
461 $out->addModuleStyles( [ 'mediawiki.special',
462 'mediawiki.interface.helpers.styles' ] );
463
464 $dropDownReason = $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->text();
465 // Add additional specific reasons for suppress
466 if ( $suppressAllowed ) {
467 $dropDownReason .= "\n" . $this->msg( 'revdelete-reason-dropdown-suppress' )
468 ->inContentLanguage()->text();
469 }
470
471 $form = Xml::openElement( 'form', [ 'method' => 'post',
472 'action' => $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] ),
473 'id' => 'mw-revdel-form-revisions' ] ) .
474 Xml::fieldset( $this->msg( 'revdelete-legend' )->text() ) .
475 $this->buildCheckBoxes() .
476 Xml::openElement( 'table' ) .
477 "<tr>\n" .
478 '<td class="mw-label">' .
479 Xml::label( $this->msg( 'revdelete-log' )->text(), 'wpRevDeleteReasonList' ) .
480 '</td>' .
481 '<td class="mw-input">' .
482 Xml::listDropDown( 'wpRevDeleteReasonList',
483 $dropDownReason,
484 $this->msg( 'revdelete-reasonotherlist' )->inContentLanguage()->text(),
485 $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' ), 'wpReasonDropDown'
486 ) .
487 '</td>' .
488 "</tr><tr>\n" .
489 '<td class="mw-label">' .
490 Xml::label( $this->msg( 'revdelete-otherreason' )->text(), 'wpReason' ) .
491 '</td>' .
492 '<td class="mw-input">' .
493 Xml::input( 'wpReason', 60, $this->otherReason, [
494 'id' => 'wpReason',
495 // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
496 // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
497 // Unicode codepoints.
498 // "- 155" is to leave room for the 'wpRevDeleteReasonList' value.
499 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT - 155,
500 ] ) .
501 '</td>' .
502 "</tr><tr>\n" .
503 '<td></td>' .
504 '<td class="mw-submit">' .
505 Xml::submitButton( $this->msg( 'revdelete-submit', $numRevisions )->text(),
506 [ 'name' => 'wpSubmit' ] ) .
507 '</td>' .
508 "</tr>\n" .
509 Xml::closeElement( 'table' ) .
510 Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ) .
511 Html::hidden( 'target', $this->targetObj->getPrefixedText() ) .
512 Html::hidden( 'type', $this->typeName ) .
513 Html::hidden( 'ids', implode( ',', $this->ids ) ) .
514 Xml::closeElement( 'fieldset' ) . "\n" .
515 Xml::closeElement( 'form' ) . "\n";
516 // Show link to edit the dropdown reasons
517 if ( $this->permissionManager->userHasRight( $this->getUser(), 'editinterface' ) ) {
518 $link = '';
519 $linkRenderer = $this->getLinkRenderer();
520 if ( $suppressAllowed ) {
521 $link .= $linkRenderer->makeKnownLink(
522 $this->msg( 'revdelete-reason-dropdown-suppress' )->inContentLanguage()->getTitle(),
523 $this->msg( 'revdelete-edit-reasonlist-suppress' )->text(),
524 [],
525 [ 'action' => 'edit' ]
526 );
527 $link .= $this->msg( 'pipe-separator' )->escaped();
528 }
529 $link .= $linkRenderer->makeKnownLink(
530 $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->getTitle(),
531 $this->msg( 'revdelete-edit-reasonlist' )->text(),
532 [],
533 [ 'action' => 'edit' ]
534 );
535 $form .= Xml::tags( 'p', [ 'class' => 'mw-revdel-editreasons' ], $link ) . "\n";
536 }
537 } else {
538 $form = '';
539 }
540 $out->addHTML( $form );
541 }
542
547 protected function addUsageText() {
548 // Messages: revdelete-text-text, revdelete-text-file, logdelete-text
549 $this->getOutput()->wrapWikiMsg(
550 "<strong>$1</strong>\n$2", $this->typeLabels['text'],
551 'revdelete-text-others'
552 );
553
554 if ( $this->permissionManager->userHasRight( $this->getUser(), 'suppressrevision' ) ) {
555 $this->getOutput()->addWikiMsg( 'revdelete-suppress-text' );
556 }
557
558 if ( $this->mIsAllowed ) {
559 $this->getOutput()->addWikiMsg( 'revdelete-confirm' );
560 }
561 }
562
566 protected function buildCheckBoxes() {
567 $html = '<table>';
568 // If there is just one item, use checkboxes
569 $list = $this->getList();
570 if ( $list->length() == 1 ) {
571 $list->reset();
572 $bitfield = $list->current()->getBits(); // existing field
573
574 if ( $this->submitClicked ) {
575 $bitfield = RevisionDeleter::extractBitfield( $this->extractBitParams(), $bitfield );
576 }
577
578 foreach ( $this->checks as $item ) {
579 // Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
580 // revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
581 list( $message, $name, $field ) = $item;
582 $innerHTML = Xml::checkLabel(
583 $this->msg( $message )->text(),
584 $name,
585 $name,
586 (bool)( $bitfield & $field )
587 );
588
589 if ( $field == RevisionRecord::DELETED_RESTRICTED ) {
590 $innerHTML = "<b>$innerHTML</b>";
591 }
592
593 $line = Xml::tags( 'td', [ 'class' => 'mw-input' ], $innerHTML );
594 $html .= "<tr>$line</tr>\n";
595 }
596 } else {
597 // Otherwise, use tri-state radios
598 $html .= '<tr>';
599 $html .= '<th class="mw-revdel-checkbox">'
600 . $this->msg( 'revdelete-radio-same' )->escaped() . '</th>';
601 $html .= '<th class="mw-revdel-checkbox">'
602 . $this->msg( 'revdelete-radio-unset' )->escaped() . '</th>';
603 $html .= '<th class="mw-revdel-checkbox">'
604 . $this->msg( 'revdelete-radio-set' )->escaped() . '</th>';
605 $html .= "<th></th></tr>\n";
606 foreach ( $this->checks as $item ) {
607 // Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
608 // revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
609 list( $message, $name, $field ) = $item;
610 // If there are several items, use third state by default...
611 if ( $this->submitClicked ) {
612 $selected = $this->getRequest()->getInt( $name, 0 /* unchecked */ );
613 } else {
614 $selected = -1; // use existing field
615 }
616 $line = '<td class="mw-revdel-checkbox">' . Xml::radio( $name, '-1', $selected == -1 ) . '</td>';
617 $line .= '<td class="mw-revdel-checkbox">' . Xml::radio( $name, '0', $selected == 0 ) . '</td>';
618 $line .= '<td class="mw-revdel-checkbox">' . Xml::radio( $name, '1', $selected == 1 ) . '</td>';
619 $label = $this->msg( $message )->escaped();
620 if ( $field == RevisionRecord::DELETED_RESTRICTED ) {
621 $label = "<b>$label</b>";
622 }
623 $line .= "<td>$label</td>";
624 $html .= "<tr>$line</tr>\n";
625 }
626 }
627
628 $html .= '</table>';
629
630 return $html;
631 }
632
638 protected function submit() {
639 # Check edit token on submission
640 $token = $this->getRequest()->getVal( 'wpEditToken' );
641 if ( $this->submitClicked && !$this->getUser()->matchEditToken( $token ) ) {
642 $this->getOutput()->addWikiMsg( 'sessionfailure' );
643
644 return false;
645 }
646 $bitParams = $this->extractBitParams();
647 // from dropdown
648 $listReason = $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' );
649 $comment = $listReason;
650 if ( $comment === 'other' ) {
651 $comment = $this->otherReason;
652 } elseif ( $this->otherReason !== '' ) {
653 // Entry from drop down menu + additional comment
654 $comment .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
655 . $this->otherReason;
656 }
657 # Can the user set this field?
658 if ( $bitParams[RevisionRecord::DELETED_RESTRICTED] == 1
659 && !$this->permissionManager->userHasRight( $this->getUser(), 'suppressrevision' )
660 ) {
661 throw new PermissionsError( 'suppressrevision' );
662 }
663 # If the save went through, go to success message...
664 $status = $this->save( $bitParams, $comment );
665 if ( $status->isGood() ) {
666 $this->success();
667
668 return true;
669 } else {
670 # ...otherwise, bounce back to form...
671 $this->failure( $status );
672 }
673
674 return false;
675 }
676
680 protected function success() {
681 // Messages: revdelete-success, logdelete-success
682 $out = $this->getOutput();
683 $out->setPageTitle( $this->msg( 'actioncomplete' ) );
684 $out->addHTML(
685 Html::successBox(
686 $out->msg( $this->typeLabels['success'] )->parse()
687 )
688 );
689 $this->wasSaved = true;
690 $this->revDelList->reloadFromPrimary();
691 $this->showForm();
692 }
693
698 protected function failure( $status ) {
699 // Messages: revdelete-failure, logdelete-failure
700 $out = $this->getOutput();
701 $out->setPageTitle( $this->msg( 'actionfailed' ) );
702 $out->addHTML(
703 Html::errorBox(
704 $out->parseAsContent(
705 $status->getWikiText( $this->typeLabels['failure'], false, $this->getLanguage() )
706 )
707 )
708 );
709 $this->showForm();
710 }
711
717 protected function extractBitParams() {
718 $bitfield = [];
719 foreach ( $this->checks as $item ) {
720 list( /* message */, $name, $field ) = $item;
721 $val = $this->getRequest()->getInt( $name, 0 /* unchecked */ );
722 if ( $val < -1 || $val > 1 ) {
723 $val = -1; // -1 for existing value
724 }
725 $bitfield[$field] = $val;
726 }
727 if ( !isset( $bitfield[RevisionRecord::DELETED_RESTRICTED] ) ) {
728 $bitfield[RevisionRecord::DELETED_RESTRICTED] = 0;
729 }
730
731 return $bitfield;
732 }
733
740 protected function save( array $bitPars, $reason ) {
741 return $this->getList()->setVisibility(
742 [ 'value' => $bitPars, 'comment' => $reason ]
743 );
744 }
745
746 protected function getGroupName() {
747 return 'pagetools';
748 }
749}
An error page which can definitely be safely rendered using the OutputPage.
Class to simplify the use of log pages.
Definition LogPage.php:39
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:29
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.
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.
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.
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.
save(array $bitPars, $reason)
Do the write operations.
success()
Report that the submit operation succeeded.
addUsageText()
Show some introductory text.
bool $wasSaved
Was the DB modified in this request.
getLogQueryCond()
Get the condition used for fetching log snippets.
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.
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...
extractBitParams()
Put together an array that contains -1, 0, or the *_deleted const for each bit.
getList()
Get the list object for this request.
Represents a title within MediaWiki.
Definition Title.php:49
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