MediaWiki fundraising/REL1_35
SpecialPageFactory.php
Go to the documentation of this file.
1<?php
25namespace MediaWiki\SpecialPage;
26
28use Language;
33use Profiler;
35use SpecialPage;
36use Title;
37use User;
38use Wikimedia\ObjectFactory;
39
69 private const CORE_LIST = [
70 // Maintenance Reports
71 'BrokenRedirects' => \SpecialBrokenRedirects::class,
72 'Deadendpages' => \SpecialDeadendPages::class,
73 'DoubleRedirects' => \SpecialDoubleRedirects::class,
74 'Longpages' => \SpecialLongPages::class,
75 'Ancientpages' => \SpecialAncientPages::class,
76 'Lonelypages' => \SpecialLonelyPages::class,
77 'Fewestrevisions' => \SpecialFewestRevisions::class,
78 'Withoutinterwiki' => \SpecialWithoutInterwiki::class,
79 'Protectedpages' => \SpecialProtectedpages::class,
80 'Protectedtitles' => \SpecialProtectedtitles::class,
81 'Shortpages' => \SpecialShortPages::class,
82 'Uncategorizedcategories' => \SpecialUncategorizedCategories::class,
83 'Uncategorizedimages' => \SpecialUncategorizedImages::class,
84 'Uncategorizedpages' => \SpecialUncategorizedPages::class,
85 'Uncategorizedtemplates' => \SpecialUncategorizedTemplates::class,
86 'Unusedcategories' => \SpecialUnusedCategories::class,
87 'Unusedimages' => \SpecialUnusedImages::class,
88 'Unusedtemplates' => \SpecialUnusedTemplates::class,
89 'Unwatchedpages' => \SpecialUnwatchedPages::class,
90 'Wantedcategories' => \SpecialWantedCategories::class,
91 'Wantedfiles' => \WantedFilesPage::class,
92 'Wantedpages' => \WantedPagesPage::class,
93 'Wantedtemplates' => \SpecialWantedTemplates::class,
94
95 // List of pages
96 'Allpages' => \SpecialAllPages::class,
97 'Prefixindex' => \SpecialPrefixindex::class,
98 'Categories' => \SpecialCategories::class,
99 'Listredirects' => \SpecialListRedirects::class,
100 'PagesWithProp' => \SpecialPagesWithProp::class,
101 'TrackingCategories' => \SpecialTrackingCategories::class,
102
103 // Authentication
104 'Userlogin' => \SpecialUserLogin::class,
105 'Userlogout' => \SpecialUserLogout::class,
106 'CreateAccount' => \SpecialCreateAccount::class,
107 'LinkAccounts' => \SpecialLinkAccounts::class,
108 'UnlinkAccounts' => \SpecialUnlinkAccounts::class,
109 'ChangeCredentials' => \SpecialChangeCredentials::class,
110 'RemoveCredentials' => \SpecialRemoveCredentials::class,
111
112 // Users and rights
113 'Activeusers' => \SpecialActiveUsers::class,
114 'Block' => [
115 'class' => \SpecialBlock::class,
116 'services' => [
117 'PermissionManager'
118 ]
119 ],
120 'Unblock' => \SpecialUnblock::class,
121 'BlockList' => \SpecialBlockList::class,
122 'AutoblockList' => \SpecialAutoblockList::class,
123 'ChangePassword' => \SpecialChangePassword::class,
124 'BotPasswords' => \SpecialBotPasswords::class,
125 'PasswordReset' => \SpecialPasswordReset::class,
126 'DeletedContributions' => \SpecialDeletedContributions::class,
127 'Preferences' => \SpecialPreferences::class,
128 'ResetTokens' => \SpecialResetTokens::class,
129 'Contributions' => \SpecialContributions::class,
130 'Listgrouprights' => \SpecialListGroupRights::class,
131 'Listgrants' => \SpecialListGrants::class,
132 'Listusers' => \SpecialListUsers::class,
133 'Listadmins' => \SpecialListAdmins::class,
134 'Listbots' => \SpecialListBots::class,
135 'Userrights' => \UserrightsPage::class,
136 'EditWatchlist' => [
137 'class' => \SpecialEditWatchlist::class,
138 'services' => [
139 'WatchedItemStore'
140 ]
141 ],
142 'PasswordPolicies' => \SpecialPasswordPolicies::class,
143
144 // Recent changes and logs
145 'Newimages' => \SpecialNewFiles::class,
146 'Log' => \SpecialLog::class,
147 'Watchlist' => \SpecialWatchlist::class,
148 'Newpages' => \SpecialNewpages::class,
149 'Recentchanges' => \SpecialRecentChanges::class,
150 'Recentchangeslinked' => \SpecialRecentChangesLinked::class,
151 'Tags' => \SpecialTags::class,
152
153 // Media reports and uploads
154 'Listfiles' => \SpecialListFiles::class,
155 'Filepath' => \SpecialFilepath::class,
156 'MediaStatistics' => \SpecialMediaStatistics::class,
157 'MIMEsearch' => \SpecialMIMESearch::class,
158 'FileDuplicateSearch' => \SpecialFileDuplicateSearch::class,
159 'Upload' => \SpecialUpload::class,
160 'UploadStash' => \SpecialUploadStash::class,
161 'ListDuplicatedFiles' => \SpecialListDuplicatedFiles::class,
162
163 // Data and tools
164 'ApiSandbox' => \SpecialApiSandbox::class,
165 'Statistics' => \SpecialStatistics::class,
166 'Allmessages' => \SpecialAllMessages::class,
167 'Version' => \SpecialVersion::class,
168 'Lockdb' => \SpecialLockdb::class,
169 'Unlockdb' => \SpecialUnlockdb::class,
170
171 // Redirecting special pages
172 'LinkSearch' => \SpecialLinkSearch::class,
173 'Randompage' => \RandomPage::class,
174 'RandomInCategory' => \SpecialRandomInCategory::class,
175 'Randomredirect' => \SpecialRandomredirect::class,
176 'Randomrootpage' => \SpecialRandomrootpage::class,
177 'GoToInterwiki' => \SpecialGoToInterwiki::class,
178
179 // High use pages
180 'Mostlinkedcategories' => \SpecialMostLinkedCategories::class,
181 'Mostimages' => \MostimagesPage::class,
182 'Mostinterwikis' => \SpecialMostInterwikis::class,
183 'Mostlinked' => \SpecialMostLinked::class,
184 'Mostlinkedtemplates' => \SpecialMostLinkedTemplates::class,
185 'Mostcategories' => \SpecialMostCategories::class,
186 'Mostrevisions' => \SpecialMostRevisions::class,
187
188 // Page tools
189 'ComparePages' => \SpecialComparePages::class,
190 'Export' => \SpecialExport::class,
191 'Import' => \SpecialImport::class,
192 'Undelete' => \SpecialUndelete::class,
193 'Whatlinkshere' => \SpecialWhatLinksHere::class,
194 'MergeHistory' => \SpecialMergeHistory::class,
195 'ExpandTemplates' => \SpecialExpandTemplates::class,
196 'ChangeContentModel' => [
197 'class' => \SpecialChangeContentModel::class,
198 'services' => [
199 'ContentHandlerFactory',
200 ],
201 ],
202
203 // Other
204 'Booksources' => \SpecialBookSources::class,
205
206 // Unlisted / redirects
207 'ApiHelp' => \SpecialApiHelp::class,
208 'Blankpage' => \SpecialBlankpage::class,
209 'Diff' => \SpecialDiff::class,
210 'EditPage' => \SpecialEditPage::class,
211 'EditTags' => [
212 'class' => \SpecialEditTags::class,
213 'services' => [
214 'PermissionManager',
215 ],
216 ],
217 'Emailuser' => \SpecialEmailUser::class,
218 'Movepage' => \MovePageForm::class,
219 'Mycontributions' => \SpecialMycontributions::class,
220 'MyLanguage' => \SpecialMyLanguage::class,
221 'Mypage' => \SpecialMypage::class,
222 'Mytalk' => \SpecialMytalk::class,
223 'PageHistory' => \SpecialPageHistory::class,
224 'PageInfo' => \SpecialPageInfo::class,
225 'Purge' => \SpecialPurge::class,
226 'Myuploads' => \SpecialMyuploads::class,
227 'AllMyUploads' => \SpecialAllMyUploads::class,
228 'NewSection' => \SpecialNewSection::class,
229 'PermanentLink' => \SpecialPermanentLink::class,
230 'Redirect' => \SpecialRedirect::class,
231 'Revisiondelete' => [
232 'class' => \SpecialRevisionDelete::class,
233 'services' => [
234 'PermissionManager',
235 'RepoGroup',
236 ],
237 ],
238 'RunJobs' => \SpecialRunJobs::class,
239 'Specialpages' => \SpecialSpecialpages::class,
240 'PageData' => \SpecialPageData::class,
241 ];
242
244 private $list;
245
247 private $aliases;
248
250 private $options;
251
253 private $contLang;
254
257
260
262 private $hookRunner;
263
268 public const CONSTRUCTOR_OPTIONS = [
269 'DisableInternalSearch',
270 'EmailAuthentication',
271 'EnableEmail',
272 'EnableJavaScriptTest',
273 'EnableSpecialMute',
274 'PageLanguageUseDB',
275 'SpecialPages',
276 ];
277
284 public function __construct(
287 ObjectFactory $objectFactory,
289 ) {
290 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
291 $this->options = $options;
292 $this->contLang = $contLang;
293 $this->objectFactory = $objectFactory;
294 $this->hookContainer = $hookContainer;
295 $this->hookRunner = new HookRunner( $hookContainer );
296 }
297
304 public function getNames() : array {
305 return array_keys( $this->getPageList() );
306 }
307
313 private function getPageList() : array {
314 if ( !is_array( $this->list ) ) {
315 $this->list = self::CORE_LIST;
316
317 if ( !$this->options->get( 'DisableInternalSearch' ) ) {
318 $this->list['Search'] = \SpecialSearch::class;
319 }
320
321 if ( $this->options->get( 'EmailAuthentication' ) ) {
322 $this->list['Confirmemail'] = \SpecialConfirmEmail::class;
323 $this->list['Invalidateemail'] = \SpecialEmailInvalidate::class;
324 }
325
326 if ( $this->options->get( 'EnableEmail' ) ) {
327 $this->list['ChangeEmail'] = \SpecialChangeEmail::class;
328 }
329
330 if ( $this->options->get( 'EnableJavaScriptTest' ) ) {
331 $this->list['JavaScriptTest'] = \SpecialJavaScriptTest::class;
332 }
333
334 if ( $this->options->get( 'EnableSpecialMute' ) ) {
335 $this->list['Mute'] = \SpecialMute::class;
336 }
337
338 if ( $this->options->get( 'PageLanguageUseDB' ) ) {
339 $this->list['PageLanguage'] = \SpecialPageLanguage::class;
340 }
341
342 // Add extension special pages
343 $this->list = array_merge( $this->list, $this->options->get( 'SpecialPages' ) );
344
345 // This hook can be used to disable unwanted core special pages
346 // or conditionally register special pages.
347 $this->hookRunner->onSpecialPage_initList( $this->list );
348 }
349
350 return $this->list;
351 }
352
359 private function getAliasList() : array {
360 if ( $this->aliases === null ) {
361 $aliases = $this->contLang->getSpecialPageAliases();
362 $pageList = $this->getPageList();
363
364 $this->aliases = [];
365 $keepAlias = [];
366
367 // Force every canonical name to be an alias for itself.
368 foreach ( $pageList as $name => $stuff ) {
369 $caseFoldedAlias = $this->contLang->caseFold( $name );
370 $this->aliases[$caseFoldedAlias] = $name;
371 $keepAlias[$caseFoldedAlias] = 'canonical';
372 }
373
374 // Check for $aliases being an array since Language::getSpecialPageAliases can return null
375 if ( is_array( $aliases ) ) {
376 foreach ( $aliases as $realName => $aliasList ) {
377 $aliasList = array_values( $aliasList );
378 foreach ( $aliasList as $i => $alias ) {
379 $caseFoldedAlias = $this->contLang->caseFold( $alias );
380
381 if ( isset( $this->aliases[$caseFoldedAlias] ) &&
382 $realName === $this->aliases[$caseFoldedAlias]
383 ) {
384 // Ignore same-realName conflicts
385 continue;
386 }
387
388 if ( !isset( $keepAlias[$caseFoldedAlias] ) ) {
389 $this->aliases[$caseFoldedAlias] = $realName;
390 if ( !$i ) {
391 $keepAlias[$caseFoldedAlias] = 'first';
392 }
393 } elseif ( !$i ) {
394 wfWarn( "First alias '$alias' for $realName conflicts with " .
395 "{$keepAlias[$caseFoldedAlias]} alias for " .
396 $this->aliases[$caseFoldedAlias]
397 );
398 }
399 }
400 }
401 }
402 }
403
404 return $this->aliases;
405 }
406
415 public function resolveAlias( $alias ) {
416 $bits = explode( '/', $alias, 2 );
417
418 $caseFoldedAlias = $this->contLang->caseFold( $bits[0] );
419 $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
420 $aliases = $this->getAliasList();
421 if ( !isset( $aliases[$caseFoldedAlias] ) ) {
422 return [ null, null ];
423 }
424 $name = $aliases[$caseFoldedAlias];
425 $par = $bits[1] ?? null; // T4087
426
427 return [ $name, $par ];
428 }
429
436 public function exists( $name ) {
437 list( $title, /*...*/ ) = $this->resolveAlias( $name );
438
439 $specialPageList = $this->getPageList();
440 return isset( $specialPageList[$title] );
441 }
442
449 public function getPage( $name ) {
450 list( $realName, /*...*/ ) = $this->resolveAlias( $name );
451
452 $specialPageList = $this->getPageList();
453
454 if ( isset( $specialPageList[$realName] ) ) {
455 $rec = $specialPageList[$realName];
456
457 if ( $rec instanceof SpecialPage ) {
459 "A SpecialPage instance for $realName was found in " .
460 '$wgSpecialPages or came from a SpecialPage_initList hook handler, ' .
461 'this was deprecated in MediaWiki 1.34',
462 '1.34'
463 );
464
465 $page = $rec; // XXX: we should deep clone here
466 } elseif ( is_array( $rec ) || is_string( $rec ) || is_callable( $rec ) ) {
467 $page = $this->objectFactory->createObject(
468 $rec,
469 [
470 'allowClassName' => true,
471 'allowCallable' => true
472 ]
473 );
474 } else {
475 $page = null;
476 }
477
478 if ( $page instanceof SpecialPage ) {
479 $page->setHookContainer( $this->hookContainer );
480 return $page;
481 }
482
483 // It's not a classname, nor a callback, nor a legacy constructor array,
484 // nor a special page object. Give up.
485 wfLogWarning( "Cannot instantiate special page $realName: bad spec!" );
486 }
487
488 return null;
489 }
490
499 public function getUsablePages( User $user ) : array {
500 $pages = [];
501 foreach ( $this->getPageList() as $name => $rec ) {
502 $page = $this->getPage( $name );
503 if ( $page ) { // not null
504 $page->setContext( RequestContext::getMain() );
505 if ( $page->isListed()
506 && ( !$page->isRestricted() || $page->userCanExecute( $user ) )
507 ) {
508 $pages[$name] = $page;
509 }
510 }
511 }
512
513 return $pages;
514 }
515
521 public function getRegularPages() : array {
522 $pages = [];
523 foreach ( $this->getPageList() as $name => $rec ) {
524 $page = $this->getPage( $name );
525 if ( $page && $page->isListed() && !$page->isRestricted() ) {
526 $pages[$name] = $page;
527 }
528 }
529
530 return $pages;
531 }
532
540 public function getRestrictedPages( User $user ) : array {
541 $pages = [];
542 foreach ( $this->getPageList() as $name => $rec ) {
543 $page = $this->getPage( $name );
544 if ( $page
545 && $page->isListed()
546 && $page->isRestricted()
547 && $page->userCanExecute( $user )
548 ) {
549 $pages[$name] = $page;
550 }
551 }
552
553 return $pages;
554 }
555
571 public function executePath( Title &$title, IContextSource &$context, $including = false,
572 LinkRenderer $linkRenderer = null
573 ) {
574 // @todo FIXME: Redirects broken due to this call
575 $bits = explode( '/', $title->getDBkey(), 2 );
576 $name = $bits[0];
577 $par = $bits[1] ?? null; // T4087
578
579 $page = $this->getPage( $name );
580 if ( !$page ) {
581 $context->getOutput()->setArticleRelated( false );
582 $context->getOutput()->setRobotPolicy( 'noindex,nofollow' );
583
584 global $wgSend404Code;
585 if ( $wgSend404Code ) {
586 $context->getOutput()->setStatusCode( 404 );
587 }
588
589 $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
590
591 return false;
592 }
593
594 if ( !$including ) {
595 // Narrow DB query expectations for this HTTP request
596 $trxLimits = $context->getConfig()->get( 'TrxProfilerLimits' );
597 $trxProfiler = Profiler::instance()->getTransactionProfiler();
598 if ( $context->getRequest()->wasPosted() && !$page->doesWrites() ) {
599 $trxProfiler->setExpectations( $trxLimits['POST-nonwrite'], __METHOD__ );
600 $context->getRequest()->markAsSafeRequest();
601 }
602 }
603
604 // Page exists, set the context
605 $page->setContext( $context );
606
607 if ( !$including ) {
608 // Redirect to canonical alias for GET commands
609 // Not for POST, we'd lose the post data, so it's best to just distribute
610 // the request. Such POST requests are possible for old extensions that
611 // generate self-links without being aware that their default name has
612 // changed.
613 if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) {
614 $query = $context->getRequest()->getQueryValues();
615 unset( $query['title'] );
616 $title = $page->getPageTitle( $par );
617 $url = $title->getFullURL( $query );
618 $context->getOutput()->redirect( $url );
619
620 return $title;
621 }
622
623 // @phan-suppress-next-line PhanUndeclaredMethod
624 $context->setTitle( $page->getPageTitle( $par ) );
625 } elseif ( !$page->isIncludable() ) {
626 return false;
627 }
628
629 $page->including( $including );
630 if ( $linkRenderer ) {
631 $page->setLinkRenderer( $linkRenderer );
632 }
633
634 // Execute special page
635 $page->run( $par );
636
637 return true;
638 }
639
655 public function capturePath(
656 Title $title, IContextSource $context, LinkRenderer $linkRenderer = null
657 ) {
658 global $wgTitle, $wgOut, $wgRequest, $wgUser, $wgLang;
659 $main = RequestContext::getMain();
660
661 // Save current globals and main context
662 $glob = [
663 'title' => $wgTitle,
664 'output' => $wgOut,
665 'request' => $wgRequest,
666 'user' => $wgUser,
667 'language' => $wgLang,
668 ];
669 $ctx = [
670 'title' => $main->getTitle(),
671 'output' => $main->getOutput(),
672 'request' => $main->getRequest(),
673 'user' => $main->getUser(),
674 'language' => $main->getLanguage(),
675 ];
676 if ( $main->canUseWikiPage() ) {
677 $ctx['wikipage'] = $main->getWikiPage();
678 }
679
680 // Override
682 $wgOut = $context->getOutput();
683 $wgRequest = $context->getRequest();
684 $wgUser = $context->getUser();
685 $wgLang = $context->getLanguage();
686 $main->setTitle( $title );
687 $main->setOutput( $context->getOutput() );
688 $main->setRequest( $context->getRequest() );
689 $main->setUser( $context->getUser() );
690 $main->setLanguage( $context->getLanguage() );
691
692 // The useful part
693 $ret = $this->executePath( $title, $context, true, $linkRenderer );
694
695 // Restore old globals and context
696 $wgTitle = $glob['title'];
697 $wgOut = $glob['output'];
698 $wgRequest = $glob['request'];
699 $wgUser = $glob['user'];
700 $wgLang = $glob['language'];
701 $main->setTitle( $ctx['title'] );
702 $main->setOutput( $ctx['output'] );
703 $main->setRequest( $ctx['request'] );
704 $main->setUser( $ctx['user'] );
705 $main->setLanguage( $ctx['language'] );
706 if ( isset( $ctx['wikipage'] ) ) {
707 $main->setWikiPage( $ctx['wikipage'] );
708 }
709
710 return $ret;
711 }
712
720 public function getLocalNameFor( $name, $subpage = false ) {
721 $aliases = $this->contLang->getSpecialPageAliases();
722 $aliasList = $this->getAliasList();
723
724 // Find the first alias that maps back to $name
725 if ( isset( $aliases[$name] ) ) {
726 $found = false;
727 foreach ( $aliases[$name] as $alias ) {
728 $caseFoldedAlias = $this->contLang->caseFold( $alias );
729 $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
730 if ( isset( $aliasList[$caseFoldedAlias] ) &&
731 $aliasList[$caseFoldedAlias] === $name
732 ) {
733 $name = $alias;
734 $found = true;
735 break;
736 }
737 }
738 if ( !$found ) {
739 wfWarn( "Did not find a usable alias for special page '$name'. " .
740 "It seems all defined aliases conflict?" );
741 }
742 } else {
743 // Check if someone misspelled the correct casing
744 if ( is_array( $aliases ) ) {
745 foreach ( $aliases as $n => $values ) {
746 if ( strcasecmp( $name, $n ) === 0 ) {
747 wfWarn( "Found alias defined for $n when searching for " .
748 "special page aliases for $name. Case mismatch?" );
749 return $this->getLocalNameFor( $n, $subpage );
750 }
751 }
752 }
753
754 wfWarn( "Did not find alias for special page '$name'. " .
755 "Perhaps no aliases are defined for it?" );
756 }
757
758 if ( $subpage !== false && $subpage !== null ) {
759 // Make sure it's in dbkey form
760 $subpage = str_replace( ' ', '_', $subpage );
761 $name = "$name/$subpage";
762 }
763
764 return $this->contLang->ucfirst( $name );
765 }
766
773 public function getTitleForAlias( $alias ) {
774 list( $name, $subpage ) = $this->resolveAlias( $alias );
775 if ( $name != null ) {
776 return SpecialPage::getTitleFor( $name, $subpage );
777 }
778
779 return null;
780 }
781}
782
784class_alias( SpecialPageFactory::class, 'MediaWiki\\Special\\SpecialPageFactory' );
$wgSend404Code
Some web hosts attempt to rewrite all responses with a 404 (not found) status code,...
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
$wgOut
Definition Setup.php:786
$wgTitle
Definition Setup.php:799
if(! $wgDBerrorLogTZ) $wgRequest
Definition Setup.php:643
$wgLang
Definition Setup.php:781
return[ 'abap'=> true, 'abl'=> true, 'abnf'=> true, 'aconf'=> true, 'actionscript'=> true, 'actionscript3'=> true, 'ada'=> true, 'ada2005'=> true, 'ada95'=> true, 'adl'=> true, 'agda'=> true, 'aheui'=> true, 'ahk'=> true, 'alloy'=> true, 'ambienttalk'=> true, 'ambienttalk/2'=> true, 'ampl'=> true, 'antlr'=> true, 'antlr-actionscript'=> true, 'antlr-as'=> true, 'antlr-c#'=> true, 'antlr-cpp'=> true, 'antlr-csharp'=> true, 'antlr-java'=> true, 'antlr-objc'=> true, 'antlr-perl'=> true, 'antlr-python'=> true, 'antlr-rb'=> true, 'antlr-ruby'=> true, 'apache'=> true, 'apacheconf'=> true, 'apl'=> true, 'applescript'=> true, 'arduino'=> true, 'arexx'=> true, 'arrow'=> true, 'as'=> true, 'as3'=> true, 'asm'=> true, 'aspectj'=> true, 'aspx-cs'=> true, 'aspx-vb'=> true, 'asy'=> true, 'asymptote'=> true, 'at'=> true, 'augeas'=> true, 'autohotkey'=> true, 'autoit'=> true, 'awk'=> true, 'b3d'=> true, 'bare'=> true, 'basemake'=> true, 'bash'=> true, 'basic'=> true, 'bat'=> true, 'batch'=> true, 'bbcbasic'=> true, 'bbcode'=> true, 'bc'=> true, 'befunge'=> true, 'bf'=> true, 'bib'=> true, 'bibtex'=> true, 'blitzbasic'=> true, 'blitzmax'=> true, 'bmax'=> true, 'bnf'=> true, 'boa'=> true, 'boo'=> true, 'boogie'=> true, 'bplus'=> true, 'brainfuck'=> true, 'bro'=> true, 'bsdmake'=> true, 'bst'=> true, 'bst-pybtex'=> true, 'bugs'=> true, 'c'=> true, 'c#'=> true, 'c++'=> true, 'c++-objdumb'=> true, 'c-objdump'=> true, 'ca65'=> true, 'cadl'=> true, 'camkes'=> true, 'capdl'=> true, 'capnp'=> true, 'cbmbas'=> true, 'ceylon'=> true, 'cf3'=> true, 'cfc'=> true, 'cfengine3'=> true, 'cfg'=> true, 'cfm'=> true, 'cfs'=> true, 'chai'=> true, 'chaiscript'=> true, 'chapel'=> true, 'charmci'=> true, 'cheetah'=> true, 'chpl'=> true, 'cirru'=> true, 'cl'=> true, 'clay'=> true, 'clean'=> true, 'clipper'=> true, 'clj'=> true, 'cljs'=> true, 'clojure'=> true, 'clojurescript'=> true, 'cmake'=> true, 'cobol'=> true, 'cobolfree'=> true, 'coffee'=> true, 'coffee-script'=> true, 'coffeescript'=> true, 'common-lisp'=> true, 'componentpascal'=> true, 'console'=> true, 'control'=> true, 'coq'=> true, 'cp'=> true, 'cpp'=> true, 'cpp-objdump'=> true, 'cpsa'=> true, 'cr'=> true, 'crmsh'=> true, 'croc'=> true, 'cry'=> true, 'cryptol'=> true, 'crystal'=> true, 'csh'=> true, 'csharp'=> true, 'csound'=> true, 'csound-csd'=> true, 'csound-document'=> true, 'csound-orc'=> true, 'csound-sco'=> true, 'csound-score'=> true, 'css'=> true, 'css+django'=> true, 'css+erb'=> true, 'css+genshi'=> true, 'css+genshitext'=> true, 'css+jinja'=> true, 'css+lasso'=> true, 'css+mako'=> true, 'css+mozpreproc'=> true, 'css+myghty'=> true, 'css+php'=> true, 'css+ruby'=> true, 'css+smarty'=> true, 'cu'=> true, 'cucumber'=> true, 'cuda'=> true, 'cxx-objdump'=> true, 'cypher'=> true, 'cython'=> true, 'd'=> true, 'd-objdump'=> true, 'dart'=> true, 'dasm16'=> true, 'debcontrol'=> true, 'debsources'=> true, 'delphi'=> true, 'devicetree'=> true, 'dg'=> true, 'diff'=> true, 'django'=> true, 'dmesg'=> true, 'do'=> true, 'docker'=> true, 'dockerfile'=> true, 'dosbatch'=> true, 'doscon'=> true, 'dosini'=> true, 'dpatch'=> true, 'dtd'=> true, 'dts'=> true, 'duby'=> true, 'duel'=> true, 'dylan'=> true, 'dylan-console'=> true, 'dylan-lid'=> true, 'dylan-repl'=> true, 'earl-grey'=> true, 'earlgrey'=> true, 'easytrieve'=> true, 'ebnf'=> true, 'ec'=> true, 'ecl'=> true, 'eg'=> true, 'eiffel'=> true, 'elisp'=> true, 'elixir'=> true, 'elm'=> true, 'emacs'=> true, 'emacs-lisp'=> true, 'email'=> true, 'eml'=> true, 'erb'=> true, 'erl'=> true, 'erlang'=> true, 'evoque'=> true, 'ex'=> true, 'execline'=> true, 'exs'=> true, 'extempore'=> true, 'ezhil'=> true, 'f#'=> true, 'factor'=> true, 'fan'=> true, 'fancy'=> true, 'felix'=> true, 'fennel'=> true, 'fish'=> true, 'fishshell'=> true, 'flatline'=> true, 'flo'=> true, 'floscript'=> true, 'flx'=> true, 'fnl'=> true, 'forth'=> true, 'fortran'=> true, 'fortranfixed'=> true, 'foxpro'=> true, 'freefem'=> true, 'fsharp'=> true, 'fstar'=> true, 'fy'=> true, 'gap'=> true, 'gas'=> true, 'gawk'=> true, 'gd'=> true, 'gdscript'=> true, 'genshi'=> true, 'genshitext'=> true, 'gherkin'=> true, 'glsl'=> true, 'gnuplot'=> true, 'go'=> true, 'golo'=> true, 'gooddata-cl'=> true, 'gosu'=> true, 'groff'=> true, 'groovy'=> true, 'gst'=> true, 'haml'=> true, 'handlebars'=> true, 'haskell'=> true, 'haxe'=> true, 'haxeml'=> true, 'hexdump'=> true, 'hlsl'=> true, 'hs'=> true, 'hsa'=> true, 'hsail'=> true, 'hspec'=> true, 'html'=> true, 'html+cheetah'=> true, 'html+django'=> true, 'html+erb'=> true, 'html+evoque'=> true, 'html+genshi'=> true, 'html+handlebars'=> true, 'html+jinja'=> true, 'html+kid'=> true, 'html+lasso'=> true, 'html+mako'=> true, 'html+myghty'=> true, 'html+ng2'=> true, 'html+php'=> true, 'html+ruby'=> true, 'html+smarty'=> true, 'html+spitfire'=> true, 'html+twig'=> true, 'html+velocity'=> true, 'htmlcheetah'=> true, 'htmldjango'=> true, 'http'=> true, 'hx'=> true, 'hxml'=> true, 'hxsl'=> true, 'hy'=> true, 'hybris'=> true, 'hylang'=> true, 'i6'=> true, 'i6t'=> true, 'i7'=> true, 'icon'=> true, 'idl'=> true, 'idl4'=> true, 'idr'=> true, 'idris'=> true, 'iex'=> true, 'igor'=> true, 'igorpro'=> true, 'ik'=> true, 'inform6'=> true, 'inform7'=> true, 'ini'=> true, 'io'=> true, 'ioke'=> true, 'irb'=> true, 'irc'=> true, 'isabelle'=> true, 'j'=> true, 'jade'=> true, 'jags'=> true, 'jasmin'=> true, 'jasminxt'=> true, 'java'=> true, 'javascript'=> true, 'javascript+cheetah'=> true, 'javascript+django'=> true, 'javascript+erb'=> true, 'javascript+genshi'=> true, 'javascript+genshitext'=> true, 'javascript+jinja'=> true, 'javascript+lasso'=> true, 'javascript+mako'=> true, 'javascript+mozpreproc'=> true, 'javascript+myghty'=> true, 'javascript+php'=> true, 'javascript+ruby'=> true, 'javascript+smarty'=> true, 'javascript+spitfire'=> true, 'jbst'=> true, 'jcl'=> true, 'jinja'=> true, 'jl'=> true, 'jlcon'=> true, 'jproperties'=> true, 'js'=> true, 'js+cheetah'=> true, 'js+django'=> true, 'js+erb'=> true, 'js+genshi'=> true, 'js+genshitext'=> true, 'js+jinja'=> true, 'js+lasso'=> true, 'js+mako'=> true, 'js+myghty'=> true, 'js+php'=> true, 'js+ruby'=> true, 'js+smarty'=> true, 'js+spitfire'=> true, 'jsgf'=> true, 'json'=> true, 'json-ld'=> true, 'json-object'=> true, 'jsonld'=> true, 'jsonml+bst'=> true, 'jsp'=> true, 'julia'=> true, 'juttle'=> true, 'kal'=> true, 'kconfig'=> true, 'kernel-config'=> true, 'kid'=> true, 'kmsg'=> true, 'koka'=> true, 'kotlin'=> true, 'ksh'=> true, 'lagda'=> true, 'lasso'=> true, 'lassoscript'=> true, 'latex'=> true, 'lcry'=> true, 'lcryptol'=> true, 'lean'=> true, 'less'=> true, 'lhaskell'=> true, 'lhs'=> true, 'lid'=> true, 'lidr'=> true, 'lidris'=> true, 'lighttpd'=> true, 'lighty'=> true, 'limbo'=> true, 'linux-config'=> true, 'liquid'=> true, 'lisp'=> true, 'literate-agda'=> true, 'literate-cryptol'=> true, 'literate-haskell'=> true, 'literate-idris'=> true, 'live-script'=> true, 'livescript'=> true, 'llvm'=> true, 'llvm-mir'=> true, 'llvm-mir-body'=> true, 'logos'=> true, 'logtalk'=> true, 'lsl'=> true, 'lua'=> true, 'm2'=> true, 'make'=> true, 'makefile'=> true, 'mako'=> true, 'man'=> true, 'maql'=> true, 'mask'=> true, 'mason'=> true, 'mathematica'=> true, 'matlab'=> true, 'matlabsession'=> true, 'mawk'=> true, 'md'=> true, 'menuconfig'=> true, 'mf'=> true, 'mime'=> true, 'minid'=> true, 'miniscript'=> true, 'mma'=> true, 'modelica'=> true, 'modula2'=> true, 'moin'=> true, 'monkey'=> true, 'monte'=> true, 'moo'=> true, 'moocode'=> true, 'moon'=> true, 'moonscript'=> true, 'mosel'=> true, 'mozhashpreproc'=> true, 'mozpercentpreproc'=> true, 'mq4'=> true, 'mq5'=> true, 'mql'=> true, 'mql4'=> true, 'mql5'=> true, 'ms'=> true, 'msc'=> true, 'mscgen'=> true, 'mupad'=> true, 'mxml'=> true, 'myghty'=> true, 'mysql'=> true, 'nasm'=> true, 'nawk'=> true, 'nb'=> true, 'ncl'=> true, 'nemerle'=> true, 'nesc'=> true, 'newlisp'=> true, 'newspeak'=> true, 'ng2'=> true, 'nginx'=> true, 'nim'=> true, 'nimrod'=> true, 'nit'=> true, 'nix'=> true, 'nixos'=> true, 'notmuch'=> true, 'nroff'=> true, 'nsh'=> true, 'nsi'=> true, 'nsis'=> true, 'numpy'=> true, 'nusmv'=> true, 'obj-c'=> true, 'obj-c++'=> true, 'obj-j'=> true, 'objc'=> true, 'objc++'=> true, 'objdump'=> true, 'objdump-nasm'=> true, 'objective-c'=> true, 'objective-c++'=> true, 'objective-j'=> true, 'objectivec'=> true, 'objectivec++'=> true, 'objectivej'=> true, 'objectpascal'=> true, 'objj'=> true, 'ocaml'=> true, 'octave'=> true, 'odin'=> true, 'ooc'=> true, 'opa'=> true, 'openbugs'=> true, 'openedge'=> true, 'pacmanconf'=> true, 'pan'=> true, 'parasail'=> true, 'pas'=> true, 'pascal'=> true, 'pawn'=> true, 'pcmk'=> true, 'peg'=> true, 'perl'=> true, 'perl6'=> true, 'php'=> true, 'php3'=> true, 'php4'=> true, 'php5'=> true, 'pig'=> true, 'pike'=> true, 'pkgconfig'=> true, 'pl'=> true, 'pl6'=> true, 'plpgsql'=> true, 'po'=> true, 'pointless'=> true, 'pony'=> true, 'posh'=> true, 'postgres'=> true, 'postgres-console'=> true, 'postgresql'=> true, 'postgresql-console'=> true, 'postscr'=> true, 'postscript'=> true, 'pot'=> true, 'pov'=> true, 'powershell'=> true, 'praat'=> true, 'progress'=> true, 'prolog'=> true, 'promql'=> true, 'properties'=> true, 'proto'=> true, 'protobuf'=> true, 'ps1'=> true, 'ps1con'=> true, 'psm1'=> true, 'psql'=> true, 'psysh'=> true, 'pug'=> true, 'puppet'=> true, 'py'=> true, 'py2'=> true, 'py2tb'=> true, 'py3'=> true, 'py3tb'=> true, 'pycon'=> true, 'pypy'=> true, 'pypylog'=> true, 'pyrex'=> true, 'pytb'=> true, 'python'=> true, 'python2'=> true, 'python3'=> true, 'pyx'=> true, 'qbasic'=> true, 'qbs'=> true, 'qml'=> true, 'qvt'=> true, 'qvto'=> true, 'r'=> true, 'racket'=> true, 'ragel'=> true, 'ragel-c'=> true, 'ragel-cpp'=> true, 'ragel-d'=> true, 'ragel-em'=> true, 'ragel-java'=> true, 'ragel-objc'=> true, 'ragel-rb'=> true, 'ragel-ruby'=> true, 'raku'=> true, 'raw'=> true, 'rb'=> true, 'rbcon'=> true, 'rconsole'=> true, 'rd'=> true, 'reason'=> true, 'reasonml'=> true, 'rebol'=> true, 'red'=> true, 'red/system'=> true, 'redcode'=> true, 'registry'=> true, 'resource'=> true, 'resourcebundle'=> true, 'rest'=> true, 'restructuredtext'=> true, 'rexx'=> true, 'rhtml'=> true, 'ride'=> true, 'rkt'=> true, 'rnc'=> true, 'rng-compact'=> true, 'roboconf-graph'=> true, 'roboconf-instances'=> true, 'robotframework'=> true, 'rout'=> true, 'rql'=> true, 'rs'=> true, 'rsl'=> true, 'rst'=> true, 'rts'=> true, 'ruby'=> true, 'rust'=> true, 's'=> true, 'sage'=> true, 'salt'=> true, 'sarl'=> true, 'sas'=> true, 'sass'=> true, 'sbatch'=> true, 'sc'=> true, 'scala'=> true, 'scaml'=> true, 'scd'=> true, 'scdoc'=> true, 'scheme'=> true, 'scilab'=> true, 'scm'=> true, 'scss'=> true, 'sgf'=> true, 'sh'=> true, 'shell'=> true, 'shell-session'=> true, 'shen'=> true, 'shex'=> true, 'shexc'=> true, 'sieve'=> true, 'silver'=> true, 'singularity'=> true, 'slash'=> true, 'slim'=> true, 'sls'=> true, 'slurm'=> true, 'smali'=> true, 'smalltalk'=> true, 'smarty'=> true, 'sml'=> true, 'snobol'=> true, 'snowball'=> true, 'solidity'=> true, 'sources.list'=> true, 'sourceslist'=> true, 'sp'=> true, 'sparql'=> true, 'spec'=> true, 'spitfire'=> true, 'splus'=> true, 'sql'=> true, 'sqlite3'=> true, 'squeak'=> true, 'squid'=> true, 'squid.conf'=> true, 'squidconf'=> true, 'ssp'=> true, 'st'=> true, 'stan'=> true, 'stata'=> true, 'supercollider'=> true, 'sv'=> true, 'swift'=> true, 'swig'=> true, 'systemverilog'=> true, 't-sql'=> true, 'tads3'=> true, 'tap'=> true, 'tasm'=> true, 'tcl'=> true, 'tcsh'=> true, 'tcshcon'=> true, 'tea'=> true, 'teraterm'=> true, 'teratermmacro'=> true, 'termcap'=> true, 'terminfo'=> true, 'terraform'=> true, 'tex'=> true, 'text'=> true, 'tf'=> true, 'thrift'=> true, 'tid'=> true, 'tnt'=> true, 'todotxt'=> true, 'toml'=> true, 'trac-wiki'=> true, 'trafficscript'=> true, 'treetop'=> true, 'ts'=> true, 'tsql'=> true, 'ttl'=> true, 'turtle'=> true, 'twig'=> true, 'typescript'=> true, 'typoscript'=> true, 'typoscriptcssdata'=> true, 'typoscripthtmldata'=> true, 'ucode'=> true, 'udiff'=> true, 'unicon'=> true, 'urbiscript'=> true, 'usd'=> true, 'usda'=> true, 'v'=> true, 'vala'=> true, 'vapi'=> true, 'vb.net'=> true, 'vbnet'=> true, 'vbscript'=> true, 'vcl'=> true, 'vclsnippet'=> true, 'vclsnippets'=> true, 'vctreestatus'=> true, 'velocity'=> true, 'verilog'=> true, 'vfp'=> true, 'vgl'=> true, 'vhdl'=> true, 'vim'=> true, 'wdiff'=> true, 'webidl'=> true, 'whiley'=> true, 'winbatch'=> true, 'winbugs'=> true, 'x10'=> true, 'xbase'=> true, 'xml'=> true, 'xml+cheetah'=> true, 'xml+django'=> true, 'xml+erb'=> true, 'xml+evoque'=> true, 'xml+genshi'=> true, 'xml+jinja'=> true, 'xml+kid'=> true, 'xml+lasso'=> true, 'xml+mako'=> true, 'xml+myghty'=> true, 'xml+php'=> true, 'xml+ruby'=> true, 'xml+smarty'=> true, 'xml+spitfire'=> true, 'xml+velocity'=> true, 'xorg.conf'=> true, 'xq'=> true, 'xql'=> true, 'xqm'=> true, 'xquery'=> true, 'xqy'=> true, 'xslt'=> true, 'xten'=> true, 'xtend'=> true, 'xul+mozpreproc'=> true, 'yaml'=> true, 'yaml+jinja'=> true, 'yang'=> true, 'zeek'=> true, 'zephir'=> true, 'zig'=> true, 'zsh'=> true,]
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition Language.php:41
A class for passing options to services.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Class that generates HTML links for pages.
Factory for handling the special page list and generating SpecialPage objects.
__construct(ServiceOptions $options, Language $contLang, ObjectFactory $objectFactory, HookContainer $hookContainer)
getRegularPages()
Return categorised listable special pages for all users.
getTitleForAlias( $alias)
Get a title for a given alias.
executePath(Title &$title, IContextSource &$context, $including=false, LinkRenderer $linkRenderer=null)
Execute a special page path.
exists( $name)
Check if a given name exist as a special page or as a special page alias.
const CORE_LIST
List of special page names to the subclass of SpecialPage which handles them.
getPage( $name)
Find the object with a given name and return it (or NULL)
getRestrictedPages(User $user)
Return categorised listable special pages which are available for the current user,...
resolveAlias( $alias)
Given a special page name with a possible subpage, return an array where the first element is the spe...
getPageList()
Get the special page list as an array.
array $list
Special page name => class name.
getNames()
Returns a list of canonical special page names.
capturePath(Title $title, IContextSource $context, LinkRenderer $linkRenderer=null)
Just like executePath() but will override global variables and execute the page in "inclusion" mode.
getLocalNameFor( $name, $subpage=false)
Get the local name for a specified canonical name.
getUsablePages(User $user)
Return categorised listable special pages which are available for the current user,...
getAliasList()
Initialise and return the list of special page aliases.
Profiler base class that defines the interface and some shared functionality.
Definition Profiler.php:33
Group all the pieces relevant to the context of a request into one instance @newable.
Parent class for all special pages.
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,...
Represents a title within MediaWiki.
Definition Title.php:42
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:60
Interface for objects which can provide a MediaWiki context on request.
getConfig()
Get the site configuration.
if($IP===false)
Definition status.php:5