MediaWiki  master
SpecialPageFactory.php
Go to the documentation of this file.
1 <?php
26 
27 use Hooks;
35 use Title;
36 use User;
37 
69  private static $coreList = [
70  // Maintenance Reports
71  'BrokenRedirects' => \BrokenRedirectsPage::class,
72  'Deadendpages' => \DeadendPagesPage::class,
73  'DoubleRedirects' => \DoubleRedirectsPage::class,
74  'Longpages' => \LongPagesPage::class,
75  'Ancientpages' => \AncientPagesPage::class,
76  'Lonelypages' => \LonelyPagesPage::class,
77  'Fewestrevisions' => \FewestrevisionsPage::class,
78  'Withoutinterwiki' => \WithoutInterwikiPage::class,
79  'Protectedpages' => \SpecialProtectedpages::class,
80  'Protectedtitles' => \SpecialProtectedtitles::class,
81  'Shortpages' => \ShortPagesPage::class,
82  'Uncategorizedcategories' => \UncategorizedCategoriesPage::class,
83  'Uncategorizedimages' => \UncategorizedImagesPage::class,
84  'Uncategorizedpages' => \UncategorizedPagesPage::class,
85  'Uncategorizedtemplates' => \UncategorizedTemplatesPage::class,
86  'Unusedcategories' => \UnusedCategoriesPage::class,
87  'Unusedimages' => \UnusedimagesPage::class,
88  'Unusedtemplates' => \UnusedtemplatesPage::class,
89  'Unwatchedpages' => \UnwatchedpagesPage::class,
90  'Wantedcategories' => \WantedCategoriesPage::class,
91  'Wantedfiles' => \WantedFilesPage::class,
92  'Wantedpages' => \WantedPagesPage::class,
93  'Wantedtemplates' => \WantedTemplatesPage::class,
94 
95  // List of pages
96  'Allpages' => \SpecialAllPages::class,
97  'Prefixindex' => \SpecialPrefixindex::class,
98  'Categories' => \SpecialCategories::class,
99  'Listredirects' => \ListredirectsPage::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' => \SpecialBlock::class,
115  'Unblock' => \SpecialUnblock::class,
116  'BlockList' => \SpecialBlockList::class,
117  'AutoblockList' => \SpecialAutoblockList::class,
118  'ChangePassword' => \SpecialChangePassword::class,
119  'BotPasswords' => \SpecialBotPasswords::class,
120  'PasswordReset' => \SpecialPasswordReset::class,
121  'DeletedContributions' => \DeletedContributionsPage::class,
122  'Preferences' => \SpecialPreferences::class,
123  'ResetTokens' => \SpecialResetTokens::class,
124  'Contributions' => \SpecialContributions::class,
125  'Listgrouprights' => \SpecialListGroupRights::class,
126  'Listgrants' => \SpecialListGrants::class,
127  'Listusers' => \SpecialListUsers::class,
128  'Listadmins' => \SpecialListAdmins::class,
129  'Listbots' => \SpecialListBots::class,
130  'Userrights' => \UserrightsPage::class,
131  'EditWatchlist' => \SpecialEditWatchlist::class,
132  'PasswordPolicies' => \SpecialPasswordPolicies::class,
133 
134  // Recent changes and logs
135  'Newimages' => \SpecialNewFiles::class,
136  'Log' => \SpecialLog::class,
137  'Watchlist' => \SpecialWatchlist::class,
138  'Newpages' => \SpecialNewpages::class,
139  'Recentchanges' => \SpecialRecentChanges::class,
140  'Recentchangeslinked' => \SpecialRecentChangesLinked::class,
141  'Tags' => \SpecialTags::class,
142 
143  // Media reports and uploads
144  'Listfiles' => \SpecialListFiles::class,
145  'Filepath' => \SpecialFilepath::class,
146  'MediaStatistics' => \MediaStatisticsPage::class,
147  'MIMEsearch' => \MIMEsearchPage::class,
148  'FileDuplicateSearch' => \FileDuplicateSearchPage::class,
149  'Upload' => \SpecialUpload::class,
150  'UploadStash' => \SpecialUploadStash::class,
151  'ListDuplicatedFiles' => \ListDuplicatedFilesPage::class,
152 
153  // Data and tools
154  'ApiSandbox' => \SpecialApiSandbox::class,
155  'Statistics' => \SpecialStatistics::class,
156  'Allmessages' => \SpecialAllMessages::class,
157  'Version' => \SpecialVersion::class,
158  'Lockdb' => \SpecialLockdb::class,
159  'Unlockdb' => \SpecialUnlockdb::class,
160 
161  // Redirecting special pages
162  'LinkSearch' => \LinkSearchPage::class,
163  'Randompage' => \RandomPage::class,
164  'RandomInCategory' => \SpecialRandomInCategory::class,
165  'Randomredirect' => \SpecialRandomredirect::class,
166  'Randomrootpage' => \SpecialRandomrootpage::class,
167  'GoToInterwiki' => \SpecialGoToInterwiki::class,
168 
169  // High use pages
170  'Mostlinkedcategories' => \MostlinkedCategoriesPage::class,
171  'Mostimages' => \MostimagesPage::class,
172  'Mostinterwikis' => \MostinterwikisPage::class,
173  'Mostlinked' => \MostlinkedPage::class,
174  'Mostlinkedtemplates' => \MostlinkedTemplatesPage::class,
175  'Mostcategories' => \MostcategoriesPage::class,
176  'Mostrevisions' => \MostrevisionsPage::class,
177 
178  // Page tools
179  'ComparePages' => \SpecialComparePages::class,
180  'Export' => \SpecialExport::class,
181  'Import' => \SpecialImport::class,
182  'Undelete' => \SpecialUndelete::class,
183  'Whatlinkshere' => \SpecialWhatLinksHere::class,
184  'MergeHistory' => \SpecialMergeHistory::class,
185  'ExpandTemplates' => \SpecialExpandTemplates::class,
186 
187  // Other
188  'Booksources' => \SpecialBookSources::class,
189 
190  // Unlisted / redirects
191  'ApiHelp' => \SpecialApiHelp::class,
192  'Blankpage' => \SpecialBlankpage::class,
193  'Diff' => \SpecialDiff::class,
194  'EditTags' => \SpecialEditTags::class,
195  'Emailuser' => \SpecialEmailUser::class,
196  'Movepage' => \MovePageForm::class,
197  'Mycontributions' => \SpecialMycontributions::class,
198  'MyLanguage' => \SpecialMyLanguage::class,
199  'Mypage' => \SpecialMypage::class,
200  'Mytalk' => \SpecialMytalk::class,
201  'Myuploads' => \SpecialMyuploads::class,
202  'AllMyUploads' => \SpecialAllMyUploads::class,
203  'NewSection' => \SpecialNewSection::class,
204  'PermanentLink' => \SpecialPermanentLink::class,
205  'Redirect' => \SpecialRedirect::class,
206  'Revisiondelete' => \SpecialRevisionDelete::class,
207  'RunJobs' => \SpecialRunJobs::class,
208  'Specialpages' => \SpecialSpecialpages::class,
209  'PageData' => \SpecialPageData::class,
210  ];
211 
213  private $list;
214 
216  private $aliases;
217 
219  private $options;
220 
222  private $contLang;
223 
230  public static $constructorOptions = [
231  'ContentHandlerUseDB',
232  'DisableInternalSearch',
233  'EmailAuthentication',
234  'EnableEmail',
235  'EnableJavaScriptTest',
236  'EnableSpecialMute',
237  'PageLanguageUseDB',
238  'SpecialPages',
239  ];
240 
246  $options->assertRequiredOptions( self::$constructorOptions );
247  $this->options = $options;
248  $this->contLang = $contLang;
249  }
250 
257  public function getNames() : array {
258  return array_keys( $this->getPageList() );
259  }
260 
266  private function getPageList() : array {
267  if ( !is_array( $this->list ) ) {
268  $this->list = self::$coreList;
269 
270  if ( !$this->options->get( 'DisableInternalSearch' ) ) {
271  $this->list['Search'] = \SpecialSearch::class;
272  }
273 
274  if ( $this->options->get( 'EmailAuthentication' ) ) {
275  $this->list['Confirmemail'] = \EmailConfirmation::class;
276  $this->list['Invalidateemail'] = \EmailInvalidation::class;
277  }
278 
279  if ( $this->options->get( 'EnableEmail' ) ) {
280  $this->list['ChangeEmail'] = \SpecialChangeEmail::class;
281  }
282 
283  if ( $this->options->get( 'EnableJavaScriptTest' ) ) {
284  $this->list['JavaScriptTest'] = \SpecialJavaScriptTest::class;
285  }
286 
287  if ( $this->options->get( 'EnableSpecialMute' ) ) {
288  $this->list['Mute'] = \SpecialMute::class;
289  }
290 
291  if ( $this->options->get( 'PageLanguageUseDB' ) ) {
292  $this->list['PageLanguage'] = \SpecialPageLanguage::class;
293  }
294 
295  if ( $this->options->get( 'ContentHandlerUseDB' ) ) {
296  $this->list['ChangeContentModel'] = \SpecialChangeContentModel::class;
297  }
298 
299  // Add extension special pages
300  $this->list = array_merge( $this->list, $this->options->get( 'SpecialPages' ) );
301 
302  // This hook can be used to disable unwanted core special pages
303  // or conditionally register special pages.
304  Hooks::run( 'SpecialPage_initList', [ &$this->list ] );
305 
306  }
307 
308  return $this->list;
309  }
310 
317  private function getAliasList() : array {
318  if ( is_null( $this->aliases ) ) {
319  $aliases = $this->contLang->getSpecialPageAliases();
320  $pageList = $this->getPageList();
321 
322  $this->aliases = [];
323  $keepAlias = [];
324 
325  // Force every canonical name to be an alias for itself.
326  foreach ( $pageList as $name => $stuff ) {
327  $caseFoldedAlias = $this->contLang->caseFold( $name );
328  $this->aliases[$caseFoldedAlias] = $name;
329  $keepAlias[$caseFoldedAlias] = 'canonical';
330  }
331 
332  // Check for $aliases being an array since Language::getSpecialPageAliases can return null
333  if ( is_array( $aliases ) ) {
334  foreach ( $aliases as $realName => $aliasList ) {
335  $aliasList = array_values( $aliasList );
336  foreach ( $aliasList as $i => $alias ) {
337  $caseFoldedAlias = $this->contLang->caseFold( $alias );
338 
339  if ( isset( $this->aliases[$caseFoldedAlias] ) &&
340  $realName === $this->aliases[$caseFoldedAlias]
341  ) {
342  // Ignore same-realName conflicts
343  continue;
344  }
345 
346  if ( !isset( $keepAlias[$caseFoldedAlias] ) ) {
347  $this->aliases[$caseFoldedAlias] = $realName;
348  if ( !$i ) {
349  $keepAlias[$caseFoldedAlias] = 'first';
350  }
351  } elseif ( !$i ) {
352  wfWarn( "First alias '$alias' for $realName conflicts with " .
353  "{$keepAlias[$caseFoldedAlias]} alias for " .
354  $this->aliases[$caseFoldedAlias]
355  );
356  }
357  }
358  }
359  }
360  }
361 
362  return $this->aliases;
363  }
364 
373  public function resolveAlias( $alias ) {
374  $bits = explode( '/', $alias, 2 );
375 
376  $caseFoldedAlias = $this->contLang->caseFold( $bits[0] );
377  $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
378  $aliases = $this->getAliasList();
379  if ( !isset( $aliases[$caseFoldedAlias] ) ) {
380  return [ null, null ];
381  }
382  $name = $aliases[$caseFoldedAlias];
383  $par = $bits[1] ?? null; // T4087
384 
385  return [ $name, $par ];
386  }
387 
394  public function exists( $name ) {
395  list( $title, /*...*/ ) = $this->resolveAlias( $name );
396 
397  $specialPageList = $this->getPageList();
398  return isset( $specialPageList[$title] );
399  }
400 
407  public function getPage( $name ) {
408  list( $realName, /*...*/ ) = $this->resolveAlias( $name );
409 
410  $specialPageList = $this->getPageList();
411 
412  if ( isset( $specialPageList[$realName] ) ) {
413  $rec = $specialPageList[$realName];
414 
415  if ( is_callable( $rec ) ) {
416  // Use callback to instantiate the special page
417  $page = $rec();
418  } elseif ( is_string( $rec ) ) {
419  $className = $rec;
420  $page = new $className;
421  } elseif ( $rec instanceof SpecialPage ) {
422  $page = $rec; // XXX: we should deep clone here
423  } else {
424  $page = null;
425  }
426 
427  if ( $page instanceof SpecialPage ) {
428  return $page;
429  }
430 
431  // It's not a classname, nor a callback, nor a legacy constructor array,
432  // nor a special page object. Give up.
433  wfLogWarning( "Cannot instantiate special page $realName: bad spec!" );
434  }
435 
436  return null;
437  }
438 
447  public function getUsablePages( User $user ) : array {
448  $pages = [];
449  foreach ( $this->getPageList() as $name => $rec ) {
450  $page = $this->getPage( $name );
451  if ( $page ) { // not null
452  $page->setContext( RequestContext::getMain() );
453  if ( $page->isListed()
454  && ( !$page->isRestricted() || $page->userCanExecute( $user ) )
455  ) {
456  $pages[$name] = $page;
457  }
458  }
459  }
460 
461  return $pages;
462  }
463 
469  public function getRegularPages() : array {
470  $pages = [];
471  foreach ( $this->getPageList() as $name => $rec ) {
472  $page = $this->getPage( $name );
473  if ( $page && $page->isListed() && !$page->isRestricted() ) {
474  $pages[$name] = $page;
475  }
476  }
477 
478  return $pages;
479  }
480 
488  public function getRestrictedPages( User $user ) : array {
489  $pages = [];
490  foreach ( $this->getPageList() as $name => $rec ) {
491  $page = $this->getPage( $name );
492  if ( $page
493  && $page->isListed()
494  && $page->isRestricted()
495  && $page->userCanExecute( $user )
496  ) {
497  $pages[$name] = $page;
498  }
499  }
500 
501  return $pages;
502  }
503 
519  public function executePath( Title &$title, IContextSource &$context, $including = false,
521  ) {
522  // @todo FIXME: Redirects broken due to this call
523  $bits = explode( '/', $title->getDBkey(), 2 );
524  $name = $bits[0];
525  $par = $bits[1] ?? null; // T4087
526 
527  $page = $this->getPage( $name );
528  if ( !$page ) {
529  $context->getOutput()->setArticleRelated( false );
530  $context->getOutput()->setRobotPolicy( 'noindex,nofollow' );
531 
532  global $wgSend404Code;
533  if ( $wgSend404Code ) {
534  $context->getOutput()->setStatusCode( 404 );
535  }
536 
537  $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
538 
539  return false;
540  }
541 
542  if ( !$including ) {
543  // Narrow DB query expectations for this HTTP request
544  $trxLimits = $context->getConfig()->get( 'TrxProfilerLimits' );
545  $trxProfiler = Profiler::instance()->getTransactionProfiler();
546  if ( $context->getRequest()->wasPosted() && !$page->doesWrites() ) {
547  $trxProfiler->setExpectations( $trxLimits['POST-nonwrite'], __METHOD__ );
548  $context->getRequest()->markAsSafeRequest();
549  }
550  }
551 
552  // Page exists, set the context
553  $page->setContext( $context );
554 
555  if ( !$including ) {
556  // Redirect to canonical alias for GET commands
557  // Not for POST, we'd lose the post data, so it's best to just distribute
558  // the request. Such POST requests are possible for old extensions that
559  // generate self-links without being aware that their default name has
560  // changed.
561  if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) {
562  $query = $context->getRequest()->getQueryValues();
563  unset( $query['title'] );
564  $title = $page->getPageTitle( $par );
565  $url = $title->getFullURL( $query );
566  $context->getOutput()->redirect( $url );
567 
568  return $title;
569  }
570 
571  $context->setTitle( $page->getPageTitle( $par ) );
572  } elseif ( !$page->isIncludable() ) {
573  return false;
574  }
575 
576  $page->including( $including );
577  if ( $linkRenderer ) {
578  $page->setLinkRenderer( $linkRenderer );
579  }
580 
581  // Execute special page
582  $page->run( $par );
583 
584  return true;
585  }
586 
602  public function capturePath(
604  ) {
605  global $wgTitle, $wgOut, $wgRequest, $wgUser, $wgLang;
606  $main = RequestContext::getMain();
607 
608  // Save current globals and main context
609  $glob = [
610  'title' => $wgTitle,
611  'output' => $wgOut,
612  'request' => $wgRequest,
613  'user' => $wgUser,
614  'language' => $wgLang,
615  ];
616  $ctx = [
617  'title' => $main->getTitle(),
618  'output' => $main->getOutput(),
619  'request' => $main->getRequest(),
620  'user' => $main->getUser(),
621  'language' => $main->getLanguage(),
622  ];
623  if ( $main->canUseWikiPage() ) {
624  $ctx['wikipage'] = $main->getWikiPage();
625  }
626 
627  // Override
628  $wgTitle = $title;
629  $wgOut = $context->getOutput();
630  $wgRequest = $context->getRequest();
631  $wgUser = $context->getUser();
632  $wgLang = $context->getLanguage();
633  $main->setTitle( $title );
634  $main->setOutput( $context->getOutput() );
635  $main->setRequest( $context->getRequest() );
636  $main->setUser( $context->getUser() );
637  $main->setLanguage( $context->getLanguage() );
638 
639  // The useful part
640  $ret = $this->executePath( $title, $context, true, $linkRenderer );
641 
642  // Restore old globals and context
643  $wgTitle = $glob['title'];
644  $wgOut = $glob['output'];
645  $wgRequest = $glob['request'];
646  $wgUser = $glob['user'];
647  $wgLang = $glob['language'];
648  $main->setTitle( $ctx['title'] );
649  $main->setOutput( $ctx['output'] );
650  $main->setRequest( $ctx['request'] );
651  $main->setUser( $ctx['user'] );
652  $main->setLanguage( $ctx['language'] );
653  if ( isset( $ctx['wikipage'] ) ) {
654  $main->setWikiPage( $ctx['wikipage'] );
655  }
656 
657  return $ret;
658  }
659 
667  public function getLocalNameFor( $name, $subpage = false ) {
668  $aliases = $this->contLang->getSpecialPageAliases();
669  $aliasList = $this->getAliasList();
670 
671  // Find the first alias that maps back to $name
672  if ( isset( $aliases[$name] ) ) {
673  $found = false;
674  foreach ( $aliases[$name] as $alias ) {
675  $caseFoldedAlias = $this->contLang->caseFold( $alias );
676  $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
677  if ( isset( $aliasList[$caseFoldedAlias] ) &&
678  $aliasList[$caseFoldedAlias] === $name
679  ) {
680  $name = $alias;
681  $found = true;
682  break;
683  }
684  }
685  if ( !$found ) {
686  wfWarn( "Did not find a usable alias for special page '$name'. " .
687  "It seems all defined aliases conflict?" );
688  }
689  } else {
690  // Check if someone misspelled the correct casing
691  if ( is_array( $aliases ) ) {
692  foreach ( $aliases as $n => $values ) {
693  if ( strcasecmp( $name, $n ) === 0 ) {
694  wfWarn( "Found alias defined for $n when searching for " .
695  "special page aliases for $name. Case mismatch?" );
696  return $this->getLocalNameFor( $n, $subpage );
697  }
698  }
699  }
700 
701  wfWarn( "Did not find alias for special page '$name'. " .
702  "Perhaps no aliases are defined for it?" );
703  }
704 
705  if ( $subpage !== false && !is_null( $subpage ) ) {
706  // Make sure it's in dbkey form
707  $subpage = str_replace( ' ', '_', $subpage );
708  $name = "$name/$subpage";
709  }
710 
711  return $this->contLang->ucfirst( $name );
712  }
713 
720  public function getTitleForAlias( $alias ) {
721  list( $name, $subpage ) = $this->resolveAlias( $alias );
722  if ( $name != null ) {
723  return SpecialPage::getTitleFor( $name, $subpage );
724  }
725 
726  return null;
727  }
728 }
getRestrictedPages(User $user)
Return categorised listable special pages which are available for the current user, but not for everyone.
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
return true to allow those checks to and false if checking is done remove or add to the links of a group of changes in EnhancedChangesList Hook subscribers can return false to omit this line from recentchanges use this to change the tables headers change it to an object instance and return false override the list derivative used $groups Array of ChangesListFilterGroup objects(added in 1.34) 'FileDeleteComplete' null for the local wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1535
capturePath(Title $title, IContextSource $context, LinkRenderer $linkRenderer=null)
Just like executePath() but will override global variables and execute the page in "inclusion" mode...
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:1983
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing after in associative array form before processing starts Return false to skip default processing and return $ret $linkRenderer
Definition: hooks.txt:1983
static instance()
Singleton.
Definition: Profiler.php:62
executePath(Title &$title, IContextSource &$context, $including=false, LinkRenderer $linkRenderer=null)
Execute a special page path.
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
getUsablePages(User $user)
Return categorised listable special pages which are available for the current user, and everyone.
A class for passing options to services.
exists( $name)
Check if a given name exist as a special page or as a special page alias.
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
getConfig()
Get the site configuration.
$wgLang
Definition: Setup.php:922
Class that generates HTML links for pages.
Factory for handling the special page list and generating SpecialPage objects.
static getMain()
Get the RequestContext object associated with the main request.
IContextSource $context
Definition: MediaWiki.php:38
getDBkey()
Get the main part with underscores.
Definition: Title.php:1021
getPageList()
Get the special page list as an array.
getLocalNameFor( $name, $subpage=false)
Get the local name for a specified canonical name.
getNames()
Returns a list of canonical special page names.
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not null
Definition: hooks.txt:773
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:918
getFullURL( $query='', $query2=false, $proto=PROTO_RELATIVE)
Get a real URL referring to this title, with interwiki link and fragment.
Definition: Title.php:1974
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don&#39;t need a full Title object...
Definition: SpecialPage.php:83
getRegularPages()
Return categorised listable special pages for all users.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
static array $list
Special page name => class name.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys, without regard for order.
__construct(ServiceOptions $options, Language $contLang)
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
static $coreList
List of special page names to the subclass of SpecialPage which handles them.
Using a hook running we can avoid having all this option specific stuff in our mainline code Using the function We ve cleaned up the code here by removing clumps of infrequently used code and moving them off somewhere else It s much easier for someone working with this code to see what s _really_ going and make changes or fix bugs In we can take all the code that deals with the little used title reversing options(say) and put it in one place. Instead of having little title-reversing if-blocks spread all over the codebase in showAnArticle
getTitleForAlias( $alias)
Get a title for a given alias.
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
resolveAlias( $alias)
Given a special page name with a possible subpage, return an array where the first element is the spe...
getPage( $name)
Find the object with a given name and return it (or NULL)
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:277
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:776
$wgOut
Definition: Setup.php:927
if(! $wgRequest->checkUrlExtension()) if(isset( $_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] !='') $wgTitle
Definition: api.php:57
getAliasList()
Initialise and return the list of special page aliases.
$wgSend404Code
Some web hosts attempt to rewrite all responses with a 404 (not found) status code, mangling or hiding MediaWiki&#39;s output.
static array $constructorOptions
TODO Make this a const when HHVM support is dropped (T192166)
return true to allow those checks to and false if checking is done & $user
Definition: hooks.txt:1460
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200