21 namespace MediaWiki\Specials;
45 use OOUI\ButtonInputWidget;
46 use OOUI\CheckboxInputWidget;
47 use OOUI\DropdownInputWidget;
49 use OOUI\FieldsetLayout;
53 use OOUI\TextInputWidget;
95 private $watch =
false;
138 parent::__construct(
'Movepage' );
139 $this->movePageFactory = $movePageFactory;
140 $this->permManager = $permManager;
141 $this->userOptionsLookup = $userOptionsLookup;
142 $this->dbProvider = $dbProvider;
143 $this->contentHandlerFactory = $contentHandlerFactory;
144 $this->nsInfo = $nsInfo;
145 $this->linkBatchFactory = $linkBatchFactory;
146 $this->repoGroup = $repoGroup;
147 $this->wikiPageFactory = $wikiPageFactory;
148 $this->searchEngineFactory = $searchEngineFactory;
149 $this->watchlistManager = $watchlistManager;
150 $this->restrictionStore = $restrictionStore;
166 $target = $par ?? $request->getText(
'target' );
167 $oldTitleText = $request->getText(
'wpOldTitle', $target );
170 if ( !$this->oldTitle ) {
174 $this->
getOutput()->addBacklinkSubtitle( $this->oldTitle );
176 if ( !$this->oldTitle->exists() ) {
180 $newTitleTextMain = $request->getText(
'wpNewTitleMain' );
181 $newTitleTextNs = $request->getInt(
'wpNewTitleNs', $this->oldTitle->getNamespace() );
184 $newTitleText_bc = $request->getText(
'wpNewTitle' );
185 $this->newTitle = strlen( $newTitleText_bc ) > 0
190 $isSubmit = $request->getRawVal(
'action' ) ===
'submit' && $request->wasPosted();
192 $reasonList = $request->getText(
'wpReasonList',
'other' );
193 $reason = $request->getText(
'wpReason' );
194 if ( $reasonList ===
'other' ) {
197 $this->reason = $reasonList . $this->
msg(
'colon-separator' )->inContentLanguage()->text() .
$reason;
199 $this->reason = $reasonList;
204 $this->moveTalk = $request->getBool(
'wpMovetalk', $def );
205 $this->fixRedirects = $request->getBool(
'wpFixRedirects', $def );
206 $this->leaveRedirect = $request->getBool(
'wpLeaveRedirect', $def );
208 $this->moveSubpages = $request->getBool(
'wpMovesubpages', $def );
209 $this->deleteAndMove = $request->getBool(
'wpDeleteAndMove' );
210 $this->moveOverShared = $request->getBool(
'wpMoveOverSharedFile' );
211 $this->watch = $request->getCheck(
'wpWatch' ) && $user->isRegistered();
215 if ( $isSubmit && $user->matchEditToken( $request->getVal(
'wpEditToken' ) ) ) {
217 $permErrors = $this->permManager->getPermissionErrors(
'move', $user, $this->oldTitle,
218 PermissionManager::RIGOR_SECURE );
227 $permErrors = $this->permManager->getPermissionErrors(
'move', $user, $this->oldTitle,
228 PermissionManager::RIGOR_FULL );
245 protected function showForm( $err, $isPermError =
false ) {
246 $this->
getSkin()->setRelevantTitle( $this->oldTitle );
249 $out->setPageTitleMsg( $this->
msg(
'move-page' )->plaintextParams( $this->oldTitle->getPrefixedText() ) );
250 $out->addModuleStyles( [
252 'mediawiki.interface.helpers.styles'
254 $out->addModules(
'mediawiki.misc-authed-ooui' );
257 $handlerSupportsRedirects = $this->contentHandlerFactory
258 ->getContentHandler( $this->oldTitle->getContentModel() )
259 ->supportsRedirects();
262 $out->addWikiMsg(
'movepagetext' );
264 $out->addWikiMsg( $handlerSupportsRedirects ?
265 'movepagetext-noredirectfixer' :
266 'movepagetext-noredirectsupport' );
269 if ( $this->oldTitle->getNamespace() ===
NS_USER && !$this->oldTitle->isSubpage() ) {
272 $out->msg(
'moveuserpage-warning' )->parse(),
273 'mw-moveuserpage-warning'
276 } elseif ( $this->oldTitle->getNamespace() ===
NS_CATEGORY ) {
279 $out->msg(
'movecategorypage-warning' )->parse(),
280 'mw-movecategorypage-warning'
292 # Show the current title as a default
293 # when the form is first opened.
295 } elseif ( !count( $err ) ) {
296 # If a title was supplied, probably from the move log revert
297 # link, check for validity. We can then show some diagnostic
298 # information and save a click.
299 $mp = $this->movePageFactory->newMovePage( $this->oldTitle,
$newTitle );
300 $status = $mp->isValidMove();
301 $status->merge( $mp->probablyCanMove( $this->getAuthority() ) );
302 if ( $status->getErrors() ) {
303 $err = $status->getErrorsArray();
307 if ( count( $err ) == 1 && isset( $err[0][0] ) ) {
308 if ( $err[0][0] ==
'articleexists'
309 && $this->permManager->quickUserCan(
'delete', $user,
$newTitle )
318 } elseif ( $err[0][0] ==
'redirectexists' && (
320 $this->permManager->quickUserCan(
'delete-redirect', $user,
$newTitle ) ||
321 $this->permManager->quickUserCan(
'delete', $user,
$newTitle ) )
330 } elseif ( $err[0][0] ==
'file-exists-sharedrepo'
331 && $this->permManager->userHasRight( $user,
'reupload-shared' )
343 $oldTalk = $this->oldTitle->getTalkPage();
344 $oldTitleSubpages = $this->oldTitle->hasSubpages();
345 $oldTitleTalkSubpages = $this->oldTitle->getTalkPage()->hasSubpages();
347 $canMoveSubpage = ( $oldTitleSubpages || $oldTitleTalkSubpages ) &&
348 $this->permManager->quickUserCan(
354 # We also want to be able to move assoc. subpage talk-pages even if base page
355 # has no associated talk page, so || with $oldTitleTalkSubpages.
356 $considerTalk = !$this->oldTitle->isTalkPage() &&
358 || ( $oldTitleTalkSubpages && $canMoveSubpage ) );
361 $queryBuilder = $this->dbProvider->getReplicaDatabase()->newSelectQueryBuilder()
364 ->where( [
'rd_namespace' => $this->oldTitle->getNamespace() ] )
365 ->andWhere( [
'rd_title' => $this->oldTitle->getDBkey() ] )
366 ->andWhere( [
'rd_interwiki' => [
'',
null ] ] );
368 $hasRedirects = (bool)$queryBuilder->caller( __METHOD__ )->fetchField();
370 $hasRedirects =
false;
373 if ( count( $err ) ) {
374 '@phan-var array[] $err';
375 if ( $isPermError ) {
376 $action_desc = $this->
msg(
'action-move' )->plain();
377 $errMsgHtml = $this->
msg(
'permissionserrorstext-withaction',
378 count( $err ), $action_desc )->parseAsBlock();
380 $errMsgHtml = $this->
msg(
'cannotmove', count( $err ) )->parseAsBlock();
383 if ( count( $err ) == 1 ) {
385 $errMsgName = array_shift( $errMsg );
387 if ( $errMsgName ==
'hookaborted' ) {
388 $errMsgHtml .=
"<p>{$errMsg[0]}</p>\n";
390 $errMsgHtml .= $this->
msg( $errMsgName, $errMsg )->parseAsBlock();
395 foreach ( $err as $errMsg ) {
396 if ( $errMsg[0] ==
'hookaborted' ) {
397 $errStr[] = $errMsg[1];
399 $errMsgName = array_shift( $errMsg );
400 $errStr[] = $this->
msg( $errMsgName, $errMsg )->parse();
404 $errMsgHtml .=
'<ul><li>' . implode(
"</li>\n<li>", $errStr ) .
"</li></ul>\n";
409 if ( $this->restrictionStore->isProtected( $this->oldTitle,
'move' ) ) {
410 # Is the title semi-protected?
411 if ( $this->restrictionStore->isSemiProtected( $this->oldTitle,
'move' ) ) {
412 $noticeMsg =
'semiprotectedpagemovewarning';
414 # Then it must be protected based on static groups (regular)
415 $noticeMsg =
'protectedpagemovewarning';
422 [
'lim' => 1,
'msgKey' => $noticeMsg ]
429 $immovableNamespaces = [];
430 foreach ( $this->
getLanguage()->getNamespaces() as $nsId => $_ ) {
431 if ( !$this->nsInfo->isMovable( $nsId ) ) {
432 $immovableNamespaces[] = $nsId;
439 $fields[] =
new FieldLayout(
441 'id' =>
'wpNewTitle',
443 'id' =>
'wpNewTitleNs',
444 'name' =>
'wpNewTitleNs',
446 'exclude' => $immovableNamespaces,
449 'id' =>
'wpNewTitleMain',
450 'name' =>
'wpNewTitleMain',
453 'suggestions' =>
false,
458 'label' => $this->msg(
'newtitle' )->text(),
464 $this->
msg(
'movepage-reason-dropdown' )->inContentLanguage()->text(),
465 [
'other' => $this->
msg(
'movereasonotherlist' )->text() ]
469 $fields[] =
new FieldLayout(
470 new DropdownInputWidget( [
471 'name' =>
'wpReasonList',
472 'inputId' =>
'wpReasonList',
475 'options' => $options,
478 'label' => $this->
msg(
'movereason' )->text(),
486 $fields[] =
new FieldLayout(
487 new TextInputWidget( [
488 'name' =>
'wpReason',
492 'value' => $this->reason,
495 'label' => $this->
msg(
'moveotherreason' )->text(),
500 if ( $considerTalk ) {
501 $fields[] =
new FieldLayout(
502 new CheckboxInputWidget( [
503 'name' =>
'wpMovetalk',
504 'id' =>
'wpMovetalk',
506 'selected' => $this->moveTalk,
509 'label' => $this->
msg(
'movetalk' )->text(),
510 'help' =>
new HtmlSnippet( $this->
msg(
'movepagetalktext' )->parseAsBlock() ),
511 'helpInline' =>
true,
513 'id' =>
'wpMovetalk-field',
518 if ( $this->permManager->userHasRight( $user,
'suppressredirect' ) ) {
519 if ( $handlerSupportsRedirects ) {
526 $fields[] =
new FieldLayout(
527 new CheckboxInputWidget( [
528 'name' =>
'wpLeaveRedirect',
529 'id' =>
'wpLeaveRedirect',
531 'selected' => $isChecked,
532 'disabled' => $isDisabled,
535 'label' => $this->
msg(
'move-leave-redirect' )->text(),
541 if ( $hasRedirects ) {
542 $fields[] =
new FieldLayout(
543 new CheckboxInputWidget( [
544 'name' =>
'wpFixRedirects',
545 'id' =>
'wpFixRedirects',
547 'selected' => $this->fixRedirects,
550 'label' => $this->
msg(
'fix-double-redirects' )->text(),
556 if ( $canMoveSubpage ) {
558 $fields[] =
new FieldLayout(
559 new CheckboxInputWidget( [
560 'name' =>
'wpMovesubpages',
561 'id' =>
'wpMovesubpages',
563 'selected' => $this->moveSubpages,
566 'label' =>
new HtmlSnippet(
568 ( $this->oldTitle->hasSubpages()
570 :
'move-talk-subpages' )
571 )->numParams( $maximumMovedPages )->params( $maximumMovedPages )->parse()
578 # Don't allow watching if user is not logged in
579 if ( $user->isRegistered() ) {
580 $watchChecked = ( $this->watch || $this->userOptionsLookup->getBoolOption( $user,
'watchmoves' )
581 || $this->watchlistManager->isWatched( $user, $this->oldTitle ) );
582 $fields[] =
new FieldLayout(
583 new CheckboxInputWidget( [
585 'id' =>
'watch', # ew
587 'selected' => $watchChecked,
590 'label' => $this->
msg(
'move-watch' )->text(),
598 $hiddenFields .=
Html::hidden(
'wpMoveOverSharedFile',
'1' );
602 $fields[] =
new FieldLayout(
603 new CheckboxInputWidget( [
604 'name' =>
'wpDeleteAndMove',
605 'id' =>
'wpDeleteAndMove',
609 'label' => $this->
msg(
'delete_and_move_confirm' )->text(),
615 $fields[] =
new FieldLayout(
616 new ButtonInputWidget( [
618 'value' => $this->
msg(
'movepagebtn' )->text(),
619 'label' => $this->
msg(
'movepagebtn' )->text(),
620 'flags' => [
'primary',
'progressive' ],
628 $fieldset =
new FieldsetLayout( [
629 'label' => $this->
msg(
'move-page-legend' )->text(),
630 'id' =>
'mw-movepage-table',
634 $form =
new FormLayout( [
636 'action' => $this->
getPageTitle()->getLocalURL(
'action=submit' ),
639 $form->appendContent(
643 Html::hidden(
'wpOldTitle', $this->oldTitle->getPrefixedText() ) .
650 'classes' => [
'movepage-wrapper' ],
657 if ( $this->
getAuthority()->isAllowed(
'editinterface' ) ) {
659 $this->
msg(
'movepage-reason-dropdown' )->inContentLanguage()->
getTitle(),
660 $this->
msg(
'movepage-edit-reasonlist' )->text(),
662 [
'action' =>
'edit' ]
664 $out->addHTML(
Html::rawElement(
'p', [
'class' =>
'mw-movepage-editreasons' ], $link ) );
667 $this->showLogFragment( $this->oldTitle );
668 $this->showSubpages( $this->oldTitle );
671 private function doSubmit() {
674 if ( $user->pingLimiter(
'move' ) ) {
681 # don't allow moving to pages with # in
682 if ( !$nt || $nt->hasFragment() ) {
683 $this->
showForm( [ [
'badtitletext' ] ] );
688 # Show a warning if the target file exists on a shared repo
689 if ( $nt->getNamespace() ===
NS_FILE
690 && !( $this->moveOverShared && $this->permManager->userHasRight( $user,
'reupload-shared' ) )
691 && !$this->repoGroup->getLocalRepo()->findFile( $nt )
692 && $this->repoGroup->findFile( $nt )
694 $this->
showForm( [ [
'file-exists-sharedrepo' ] ] );
699 # Delete to make way if requested
700 if ( $this->deleteAndMove ) {
701 $redir2 = $nt->isSingleRevRedirect();
703 $permErrors = $this->permManager->getPermissionErrors(
704 $redir2 ?
'delete-redirect' :
'delete',
707 if ( count( $permErrors ) ) {
709 if ( count( $this->permManager->getPermissionErrors(
'delete', $user, $nt ) ) ) {
712 $this->
showForm( $permErrors,
true );
722 $this->
showForm( $permErrors,
true );
727 $page = $this->wikiPageFactory->newFromTitle( $nt );
730 if ( $page->isBatchedDelete( 5 ) ) {
731 $this->
showForm( [ [
'movepage-delete-first' ] ] );
736 $reason = $this->
msg(
'delete_and_move_reason', $ot )->inContentLanguage()->text();
739 if ( $nt->getNamespace() ===
NS_FILE ) {
740 $file = $this->repoGroup->getLocalRepo()->newFile( $nt );
741 $file->load( File::READ_LATEST );
742 if (
$file->exists() ) {
748 $deletionLog = $redir2 ?
'delete_redir2' :
'delete';
749 $deleteStatus = $page->doDeleteArticleReal(
750 $reason, $user,
false,
null, $error,
751 null, [], $deletionLog
753 if ( !$deleteStatus->isGood() ) {
754 $this->
showForm( $deleteStatus->getErrorsArray() );
760 $handler = $this->contentHandlerFactory->getContentHandler( $ot->getContentModel() );
762 if ( !$handler->supportsRedirects() ) {
763 $createRedirect =
false;
764 } elseif ( $this->permManager->userHasRight( $user,
'suppressredirect' ) ) {
767 $createRedirect =
true;
770 # Do the actual move.
771 $mp = $this->movePageFactory->newMovePage( $ot, $nt );
773 # check whether the requested actions are permitted / possible
774 $userPermitted = $mp->authorizeMove( $this->
getAuthority(), $this->reason )->isOK();
775 if ( $ot->isTalkPage() || $nt->isTalkPage() ) {
776 $this->moveTalk =
false;
778 if ( $this->moveSubpages ) {
779 $this->moveSubpages = $this->permManager->userCan(
'move-subpages', $user, $ot );
782 $status = $mp->moveIfAllowed( $this->
getAuthority(), $this->reason, $createRedirect );
783 if ( !$status->isOK() ) {
784 $this->
showForm( $status->getErrorsArray(), !$userPermitted );
789 $this->fixRedirects ) {
794 $out->setPageTitleMsg( $this->
msg(
'pagemovedsub' ) );
797 $oldLink = $linkRenderer->makeLink(
800 [
'id' =>
'movepage-oldlink' ],
801 [
'redirect' =>
'no' ]
803 $newLink = $linkRenderer->makeKnownLink(
806 [
'id' =>
'movepage-newlink' ]
808 $oldText = $ot->getPrefixedText();
809 $newText = $nt->getPrefixedText();
811 if ( $status->getValue()[
'redirectRevision'] !==
null ) {
812 $msgName =
'movepage-moved-redirect';
814 $msgName =
'movepage-moved-noredirect';
817 $out->addHTML( $this->
msg(
'movepage-moved' )->rawParams( $oldLink,
818 $newLink )->params( $oldText, $newText )->parseAsBlock() );
819 $out->addWikiMsg( $msgName );
821 $this->
getHookRunner()->onSpecialMovepageAfterMove( $this, $ot, $nt );
838 $dbr = $this->dbProvider->getReplicaDatabase();
839 if ( $this->moveSubpages && (
840 $this->nsInfo->hasSubpages( $nt->getNamespace() ) || (
842 && $this->nsInfo->hasSubpages( $nt->getTalkPage()->getNamespace() )
846 'page_title' . $dbr->buildLike( $ot->getDBkey() .
'/', $dbr->anyString() )
847 .
' OR page_title = ' . $dbr->addQuotes( $ot->getDBkey() )
849 $conds[
'page_namespace'] = [];
850 if ( $this->nsInfo->hasSubpages( $nt->getNamespace() ) ) {
851 $conds[
'page_namespace'][] = $ot->getNamespace();
853 if ( $this->moveTalk &&
854 $this->nsInfo->hasSubpages( $nt->getTalkPage()->getNamespace() )
856 $conds[
'page_namespace'][] = $ot->getTalkPage()->getNamespace();
858 } elseif ( $this->moveTalk ) {
860 'page_namespace' => $ot->getTalkPage()->getNamespace(),
861 'page_title' => $ot->getDBkey()
869 if ( $conds !==
null ) {
871 $dbr->newSelectQueryBuilder()
872 ->select( [
'page_id',
'page_namespace',
'page_title' ] )
875 ->caller( __METHOD__ )->fetchResultSet()
881 foreach ( $extraPages as $oldSubpage ) {
882 if ( $ot->equals( $oldSubpage ) || $nt->equals( $oldSubpage ) ) {
883 # Already did this one.
887 $newPageName = preg_replace(
888 '#^' . preg_quote( $ot->getDBkey(),
'#' ) .
'#',
890 $oldSubpage->getDBkey()
893 if ( $oldSubpage->isSubpage() && ( $ot->isTalkPage() xor $nt->isTalkPage() ) ) {
895 $newNs = $nt->getNamespace();
896 } elseif ( $oldSubpage->isTalkPage() ) {
897 $newNs = $nt->getTalkPage()->getNamespace();
899 $newNs = $nt->getSubjectPage()->getNamespace();
902 # T16385: we need makeTitleSafe because the new page names may
903 # be longer than 255 characters.
905 if ( !$newSubpage ) {
906 $oldLink = $linkRenderer->makeKnownLink( $oldSubpage );
907 $extraOutput[] = $this->
msg(
'movepage-page-unmoved' )->rawParams( $oldLink )
912 $mp = $this->movePageFactory->newMovePage( $oldSubpage, $newSubpage );
913 # This was copy-pasted from Renameuser, bleh.
914 if ( $newSubpage->exists() && !$mp->isValidMove()->isOK() ) {
915 $link = $linkRenderer->makeKnownLink( $newSubpage );
916 $extraOutput[] = $this->
msg(
'movepage-page-exists' )->rawParams( $link )->escaped();
918 $status = $mp->moveIfAllowed( $this->
getAuthority(), $this->reason, $createRedirect );
920 if ( $status->isOK() ) {
921 if ( $this->fixRedirects ) {
924 $oldLink = $linkRenderer->makeLink(
928 [
'redirect' =>
'no' ]
931 $newLink = $linkRenderer->makeKnownLink( $newSubpage );
932 $extraOutput[] = $this->
msg(
'movepage-page-moved' )
933 ->rawParams( $oldLink, $newLink )->escaped();
938 if ( $count >= $maximumMovedPages ) {
939 $extraOutput[] = $this->
msg(
'movepage-max-pages' )
940 ->numParams( $maximumMovedPages )->escaped();
944 $oldLink = $linkRenderer->makeKnownLink( $oldSubpage );
945 $newLink = $linkRenderer->makeLink( $newSubpage );
946 $extraOutput[] = $this->
msg(
'movepage-page-unmoved' )
947 ->rawParams( $oldLink, $newLink )->escaped();
952 if ( $extraOutput !== [] ) {
953 $out->addHTML(
"<ul>\n<li>" . implode(
"</li>\n<li>", $extraOutput ) .
"</li>\n</ul>" );
956 # Deal with watches (we don't watch subpages)
957 $this->watchlistManager->setWatch( $this->watch, $this->
getAuthority(), $ot );
958 $this->watchlistManager->setWatch( $this->watch, $this->
getAuthority(), $nt );
961 private function showLogFragment( $title ) {
962 $moveLogPage =
new LogPage(
'move' );
964 $out->addHTML(
Xml::element(
'h2',
null, $moveLogPage->getName()->text() ) );
974 private function showSubpages( $title ) {
975 $nsHasSubpages = $this->nsInfo->hasSubpages( $title->getNamespace() );
976 $subpages = $title->getSubpages();
977 $count = $subpages instanceof TitleArray ? $subpages->count() : 0;
979 $titleIsTalk = $title->isTalkPage();
980 $subpagesTalk = $title->getTalkPage()->getSubpages();
981 $countTalk = $subpagesTalk instanceof TitleArray ? $subpagesTalk->count() : 0;
982 $totalCount = $count + $countTalk;
984 if ( !$nsHasSubpages && $countTalk == 0 ) {
990 [
'movesubpage', ( $titleIsTalk ? $count : $totalCount ) ]
993 if ( $nsHasSubpages ) {
994 $this->showSubpagesList( $subpages, $count,
'movesubpagetext',
true );
997 if ( !$titleIsTalk && $countTalk > 0 ) {
998 $this->showSubpagesList( $subpagesTalk, $countTalk,
'movesubpagetalktext' );
1002 private function showSubpagesList( $subpages, $pagecount, $wikiMsg, $noSubpageMsg =
false ) {
1006 if ( $pagecount == 0 && $noSubpageMsg ) {
1007 $out->addWikiMsg(
'movenosubpage' );
1011 $out->addWikiMsg( $wikiMsg, $this->
getLanguage()->formatNum( $pagecount ) );
1012 $out->addHTML(
"<ul>\n" );
1014 $linkBatch = $this->linkBatchFactory->newLinkBatch( $subpages );
1015 $linkBatch->setCaller( __METHOD__ );
1016 $linkBatch->execute();
1019 foreach ( $subpages as $subpage ) {
1020 $link = $linkRenderer->makeLink( $subpage );
1021 $out->addHTML(
"<li>$link</li>\n" );
1023 $out->addHTML(
"</ul>\n" );
1035 return $this->
prefixSearchString( $search, $limit, $offset, $this->searchEngineFactory );
1047 class_alias( SpecialMovePage::class,
'MovePageForm' );
Defer callable updates to run later in the PHP process.
static addCallableUpdate( $callable, $stage=self::POSTSEND, $dbw=null)
Add an update to the pending update queue that invokes the specified callback when run.
Fix any double redirects after moving a page.
static fixRedirects( $reason, $redirTitle)
Insert jobs into the job queue to fix redirects to the given title.
An error page which can definitely be safely rendered using the OutputPage.
Implements some public methods and some protected utility functions which are required by multiple ch...
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Class to simplify the use of log pages.
A class containing constants representing the names of configuration variables.
const FixDoubleRedirects
Name constant for the FixDoubleRedirects setting, for use with Config::get()
const MaximumMovedPages
Name constant for the MaximumMovedPages setting, for use with Config::get()
Service for creating WikiPage objects.
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.
getUser()
Shortcut to get the User executing this instance.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
prefixSearchString( $search, $limit, $offset, SearchEngineFactory $searchEngineFactory=null)
Perform a regular substring search for prefixSearchSubpages.
getPageTitle( $subpage=false)
Get a self-referential title object.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getConfig()
Shortcut to get main config object.
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 Per default the message key is the canonical name o...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Shortcut to construct a special page which is unlisted by default.
Implement Special:Movepage for changing page titles.
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
showForm( $err, $isPermError=false)
Show the form.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
string $reason
Text input.
__construct(MovePageFactory $movePageFactory, PermissionManager $permManager, UserOptionsLookup $userOptionsLookup, IConnectionProvider $dbProvider, IContentHandlerFactory $contentHandlerFactory, NamespaceInfo $nsInfo, LinkBatchFactory $linkBatchFactory, RepoGroup $repoGroup, WikiPageFactory $wikiPageFactory, SearchEngineFactory $searchEngineFactory, WatchlistManager $watchlistManager, RestrictionStore $restrictionStore)
execute( $par)
Default execute method Checks user permissions.
doesWrites()
Indicates whether this special page may perform database writes.
Show an error when a user tries to do something they do not have the necessary permissions for.
Prioritized list of file repositories.
Factory class for SearchEngine.
A collection of static methods to play with strings.
static escapeRegexReplacement( $string)
Escape a string to make it suitable for inclusion in a preg_replace() replacement parameter.
Show an error when the user hits a rate limit.
Module of static functions for generating XML.
static listDropDownOptions( $list, $params=[])
Build options for a drop-down box from a textual list.
static listDropDownOptionsOoui( $options)
Convert options for a drop-down box into a format accepted by OOUI\DropdownInputWidget etc.
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Service for page rename actions.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.