MediaWiki  master
SpecialPageFactory.php
Go to the documentation of this file.
1 <?php
26 
27 use Config;
28 use Hooks;
35 use Title;
36 use User;
38 
70  private static $coreList = [
71  // Maintenance Reports
72  'BrokenRedirects' => \BrokenRedirectsPage::class,
73  'Deadendpages' => \DeadendPagesPage::class,
74  'DoubleRedirects' => \DoubleRedirectsPage::class,
75  'Longpages' => \LongPagesPage::class,
76  'Ancientpages' => \AncientPagesPage::class,
77  'Lonelypages' => \LonelyPagesPage::class,
78  'Fewestrevisions' => \FewestrevisionsPage::class,
79  'Withoutinterwiki' => \WithoutInterwikiPage::class,
80  'Protectedpages' => \SpecialProtectedpages::class,
81  'Protectedtitles' => \SpecialProtectedtitles::class,
82  'Shortpages' => \ShortPagesPage::class,
83  'Uncategorizedcategories' => \UncategorizedCategoriesPage::class,
84  'Uncategorizedimages' => \UncategorizedImagesPage::class,
85  'Uncategorizedpages' => \UncategorizedPagesPage::class,
86  'Uncategorizedtemplates' => \UncategorizedTemplatesPage::class,
87  'Unusedcategories' => \UnusedCategoriesPage::class,
88  'Unusedimages' => \UnusedimagesPage::class,
89  'Unusedtemplates' => \UnusedtemplatesPage::class,
90  'Unwatchedpages' => \UnwatchedpagesPage::class,
91  'Wantedcategories' => \WantedCategoriesPage::class,
92  'Wantedfiles' => \WantedFilesPage::class,
93  'Wantedpages' => \WantedPagesPage::class,
94  'Wantedtemplates' => \WantedTemplatesPage::class,
95 
96  // List of pages
97  'Allpages' => \SpecialAllPages::class,
98  'Prefixindex' => \SpecialPrefixindex::class,
99  'Categories' => \SpecialCategories::class,
100  'Listredirects' => \ListredirectsPage::class,
101  'PagesWithProp' => \SpecialPagesWithProp::class,
102  'TrackingCategories' => \SpecialTrackingCategories::class,
103 
104  // Authentication
105  'Userlogin' => \SpecialUserLogin::class,
106  'Userlogout' => \SpecialUserLogout::class,
107  'CreateAccount' => \SpecialCreateAccount::class,
108  'LinkAccounts' => \SpecialLinkAccounts::class,
109  'UnlinkAccounts' => \SpecialUnlinkAccounts::class,
110  'ChangeCredentials' => \SpecialChangeCredentials::class,
111  'RemoveCredentials' => \SpecialRemoveCredentials::class,
112 
113  // Users and rights
114  'Activeusers' => \SpecialActiveUsers::class,
115  'Block' => \SpecialBlock::class,
116  'Unblock' => \SpecialUnblock::class,
117  'BlockList' => \SpecialBlockList::class,
118  'AutoblockList' => \SpecialAutoblockList::class,
119  'ChangePassword' => \SpecialChangePassword::class,
120  'BotPasswords' => \SpecialBotPasswords::class,
121  'PasswordReset' => \SpecialPasswordReset::class,
122  'DeletedContributions' => \DeletedContributionsPage::class,
123  'Preferences' => \SpecialPreferences::class,
124  'ResetTokens' => \SpecialResetTokens::class,
125  'Contributions' => \SpecialContributions::class,
126  'Listgrouprights' => \SpecialListGroupRights::class,
127  'Listgrants' => \SpecialListGrants::class,
128  'Listusers' => \SpecialListUsers::class,
129  'Listadmins' => \SpecialListAdmins::class,
130  'Listbots' => \SpecialListBots::class,
131  'Userrights' => \UserrightsPage::class,
132  'EditWatchlist' => \SpecialEditWatchlist::class,
133  'PasswordPolicies' => \SpecialPasswordPolicies::class,
134 
135  // Recent changes and logs
136  'Newimages' => \SpecialNewFiles::class,
137  'Log' => \SpecialLog::class,
138  'Watchlist' => \SpecialWatchlist::class,
139  'Newpages' => \SpecialNewpages::class,
140  'Recentchanges' => \SpecialRecentChanges::class,
141  'Recentchangeslinked' => \SpecialRecentChangesLinked::class,
142  'Tags' => \SpecialTags::class,
143 
144  // Media reports and uploads
145  'Listfiles' => \SpecialListFiles::class,
146  'Filepath' => \SpecialFilepath::class,
147  'MediaStatistics' => \MediaStatisticsPage::class,
148  'MIMEsearch' => \MIMEsearchPage::class,
149  'FileDuplicateSearch' => \FileDuplicateSearchPage::class,
150  'Upload' => \SpecialUpload::class,
151  'UploadStash' => \SpecialUploadStash::class,
152  'ListDuplicatedFiles' => \ListDuplicatedFilesPage::class,
153 
154  // Data and tools
155  'ApiSandbox' => \SpecialApiSandbox::class,
156  'Statistics' => \SpecialStatistics::class,
157  'Allmessages' => \SpecialAllMessages::class,
158  'Version' => \SpecialVersion::class,
159  'Lockdb' => \SpecialLockdb::class,
160  'Unlockdb' => \SpecialUnlockdb::class,
161 
162  // Redirecting special pages
163  'LinkSearch' => \LinkSearchPage::class,
164  'Randompage' => \RandomPage::class,
165  'RandomInCategory' => \SpecialRandomInCategory::class,
166  'Randomredirect' => \SpecialRandomredirect::class,
167  'Randomrootpage' => \SpecialRandomrootpage::class,
168  'GoToInterwiki' => \SpecialGoToInterwiki::class,
169 
170  // High use pages
171  'Mostlinkedcategories' => \MostlinkedCategoriesPage::class,
172  'Mostimages' => \MostimagesPage::class,
173  'Mostinterwikis' => \MostinterwikisPage::class,
174  'Mostlinked' => \MostlinkedPage::class,
175  'Mostlinkedtemplates' => \MostlinkedTemplatesPage::class,
176  'Mostcategories' => \MostcategoriesPage::class,
177  'Mostrevisions' => \MostrevisionsPage::class,
178 
179  // Page tools
180  'ComparePages' => \SpecialComparePages::class,
181  'Export' => \SpecialExport::class,
182  'Import' => \SpecialImport::class,
183  'Undelete' => \SpecialUndelete::class,
184  'Whatlinkshere' => \SpecialWhatLinksHere::class,
185  'MergeHistory' => \SpecialMergeHistory::class,
186  'ExpandTemplates' => \SpecialExpandTemplates::class,
187 
188  // Other
189  'Booksources' => \SpecialBookSources::class,
190 
191  // Unlisted / redirects
192  'ApiHelp' => \SpecialApiHelp::class,
193  'Blankpage' => \SpecialBlankpage::class,
194  'Diff' => \SpecialDiff::class,
195  'EditTags' => \SpecialEditTags::class,
196  'Emailuser' => \SpecialEmailUser::class,
197  'Movepage' => \MovePageForm::class,
198  'Mycontributions' => \SpecialMycontributions::class,
199  'MyLanguage' => \SpecialMyLanguage::class,
200  'Mypage' => \SpecialMypage::class,
201  'Mytalk' => \SpecialMytalk::class,
202  'Myuploads' => \SpecialMyuploads::class,
203  'AllMyUploads' => \SpecialAllMyUploads::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  'PageLanguageUseDB',
237  'SpecialPages',
238  ];
239 
245  Assert::parameter( count( $options ) === count( self::$constructorOptions ) &&
246  !array_diff( self::$constructorOptions, array_keys( $options ) ),
247  '$options', 'Wrong set of options present' );
248  $this->options = $options;
249  $this->contLang = $contLang;
250  }
251 
258  public function getNames() : array {
259  return array_keys( $this->getPageList() );
260  }
261 
267  private function getPageList() : array {
268  if ( !is_array( $this->list ) ) {
269  $this->list = self::$coreList;
270 
271  if ( !$this->options['DisableInternalSearch'] ) {
272  $this->list['Search'] = \SpecialSearch::class;
273  }
274 
275  if ( $this->options['EmailAuthentication'] ) {
276  $this->list['Confirmemail'] = \EmailConfirmation::class;
277  $this->list['Invalidateemail'] = \EmailInvalidation::class;
278  }
279 
280  if ( $this->options['EnableEmail'] ) {
281  $this->list['ChangeEmail'] = \SpecialChangeEmail::class;
282  }
283 
284  if ( $this->options['EnableJavaScriptTest'] ) {
285  $this->list['JavaScriptTest'] = \SpecialJavaScriptTest::class;
286  }
287 
288  if ( $this->options['PageLanguageUseDB'] ) {
289  $this->list['PageLanguage'] = \SpecialPageLanguage::class;
290  }
291  if ( $this->options['ContentHandlerUseDB'] ) {
292  $this->list['ChangeContentModel'] = \SpecialChangeContentModel::class;
293  }
294 
295  // Add extension special pages
296  $this->list = array_merge( $this->list, $this->options['SpecialPages'] );
297 
298  // This hook can be used to disable unwanted core special pages
299  // or conditionally register special pages.
300  Hooks::run( 'SpecialPage_initList', [ &$this->list ] );
301 
302  }
303 
304  return $this->list;
305  }
306 
313  private function getAliasList() : array {
314  if ( is_null( $this->aliases ) ) {
315  $aliases = $this->contLang->getSpecialPageAliases();
316  $pageList = $this->getPageList();
317 
318  $this->aliases = [];
319  $keepAlias = [];
320 
321  // Force every canonical name to be an alias for itself.
322  foreach ( $pageList as $name => $stuff ) {
323  $caseFoldedAlias = $this->contLang->caseFold( $name );
324  $this->aliases[$caseFoldedAlias] = $name;
325  $keepAlias[$caseFoldedAlias] = 'canonical';
326  }
327 
328  // Check for $aliases being an array since Language::getSpecialPageAliases can return null
329  if ( is_array( $aliases ) ) {
330  foreach ( $aliases as $realName => $aliasList ) {
331  $aliasList = array_values( $aliasList );
332  foreach ( $aliasList as $i => $alias ) {
333  $caseFoldedAlias = $this->contLang->caseFold( $alias );
334 
335  if ( isset( $this->aliases[$caseFoldedAlias] ) &&
336  $realName === $this->aliases[$caseFoldedAlias]
337  ) {
338  // Ignore same-realName conflicts
339  continue;
340  }
341 
342  if ( !isset( $keepAlias[$caseFoldedAlias] ) ) {
343  $this->aliases[$caseFoldedAlias] = $realName;
344  if ( !$i ) {
345  $keepAlias[$caseFoldedAlias] = 'first';
346  }
347  } elseif ( !$i ) {
348  wfWarn( "First alias '$alias' for $realName conflicts with " .
349  "{$keepAlias[$caseFoldedAlias]} alias for " .
350  $this->aliases[$caseFoldedAlias]
351  );
352  }
353  }
354  }
355  }
356  }
357 
358  return $this->aliases;
359  }
360 
369  public function resolveAlias( $alias ) {
370  $bits = explode( '/', $alias, 2 );
371 
372  $caseFoldedAlias = $this->contLang->caseFold( $bits[0] );
373  $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
374  $aliases = $this->getAliasList();
375  if ( !isset( $aliases[$caseFoldedAlias] ) ) {
376  return [ null, null ];
377  }
378  $name = $aliases[$caseFoldedAlias];
379  $par = $bits[1] ?? null; // T4087
380 
381  return [ $name, $par ];
382  }
383 
390  public function exists( $name ) {
391  list( $title, /*...*/ ) = $this->resolveAlias( $name );
392 
393  $specialPageList = $this->getPageList();
394  return isset( $specialPageList[$title] );
395  }
396 
403  public function getPage( $name ) {
404  list( $realName, /*...*/ ) = $this->resolveAlias( $name );
405 
406  $specialPageList = $this->getPageList();
407 
408  if ( isset( $specialPageList[$realName] ) ) {
409  $rec = $specialPageList[$realName];
410 
411  if ( is_callable( $rec ) ) {
412  // Use callback to instantiate the special page
413  $page = $rec();
414  } elseif ( is_string( $rec ) ) {
415  $className = $rec;
416  $page = new $className;
417  } elseif ( $rec instanceof SpecialPage ) {
418  $page = $rec; // XXX: we should deep clone here
419  } else {
420  $page = null;
421  }
422 
423  if ( $page instanceof SpecialPage ) {
424  return $page;
425  }
426 
427  // It's not a classname, nor a callback, nor a legacy constructor array,
428  // nor a special page object. Give up.
429  wfLogWarning( "Cannot instantiate special page $realName: bad spec!" );
430  }
431 
432  return null;
433  }
434 
443  public function getUsablePages( User $user ) : array {
444  $pages = [];
445  foreach ( $this->getPageList() as $name => $rec ) {
446  $page = $this->getPage( $name );
447  if ( $page ) { // not null
448  $page->setContext( RequestContext::getMain() );
449  if ( $page->isListed()
450  && ( !$page->isRestricted() || $page->userCanExecute( $user ) )
451  ) {
452  $pages[$name] = $page;
453  }
454  }
455  }
456 
457  return $pages;
458  }
459 
465  public function getRegularPages() : array {
466  $pages = [];
467  foreach ( $this->getPageList() as $name => $rec ) {
468  $page = $this->getPage( $name );
469  if ( $page && $page->isListed() && !$page->isRestricted() ) {
470  $pages[$name] = $page;
471  }
472  }
473 
474  return $pages;
475  }
476 
484  public function getRestrictedPages( User $user ) : array {
485  $pages = [];
486  foreach ( $this->getPageList() as $name => $rec ) {
487  $page = $this->getPage( $name );
488  if ( $page
489  && $page->isListed()
490  && $page->isRestricted()
491  && $page->userCanExecute( $user )
492  ) {
493  $pages[$name] = $page;
494  }
495  }
496 
497  return $pages;
498  }
499 
515  public function executePath( Title &$title, IContextSource &$context, $including = false,
517  ) {
518  // @todo FIXME: Redirects broken due to this call
519  $bits = explode( '/', $title->getDBkey(), 2 );
520  $name = $bits[0];
521  $par = $bits[1] ?? null; // T4087
522 
523  $page = $this->getPage( $name );
524  if ( !$page ) {
525  $context->getOutput()->setArticleRelated( false );
526  $context->getOutput()->setRobotPolicy( 'noindex,nofollow' );
527 
528  global $wgSend404Code;
529  if ( $wgSend404Code ) {
530  $context->getOutput()->setStatusCode( 404 );
531  }
532 
533  $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
534 
535  return false;
536  }
537 
538  if ( !$including ) {
539  // Narrow DB query expectations for this HTTP request
540  $trxLimits = $context->getConfig()->get( 'TrxProfilerLimits' );
541  $trxProfiler = Profiler::instance()->getTransactionProfiler();
542  if ( $context->getRequest()->wasPosted() && !$page->doesWrites() ) {
543  $trxProfiler->setExpectations( $trxLimits['POST-nonwrite'], __METHOD__ );
544  $context->getRequest()->markAsSafeRequest();
545  }
546  }
547 
548  // Page exists, set the context
549  $page->setContext( $context );
550 
551  if ( !$including ) {
552  // Redirect to canonical alias for GET commands
553  // Not for POST, we'd lose the post data, so it's best to just distribute
554  // the request. Such POST requests are possible for old extensions that
555  // generate self-links without being aware that their default name has
556  // changed.
557  if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) {
558  $query = $context->getRequest()->getQueryValues();
559  unset( $query['title'] );
560  $title = $page->getPageTitle( $par );
561  $url = $title->getFullURL( $query );
562  $context->getOutput()->redirect( $url );
563 
564  return $title;
565  }
566 
567  $context->setTitle( $page->getPageTitle( $par ) );
568  } elseif ( !$page->isIncludable() ) {
569  return false;
570  }
571 
572  $page->including( $including );
573  if ( $linkRenderer ) {
574  $page->setLinkRenderer( $linkRenderer );
575  }
576 
577  // Execute special page
578  $page->run( $par );
579 
580  return true;
581  }
582 
598  public function capturePath(
600  ) {
601  global $wgTitle, $wgOut, $wgRequest, $wgUser, $wgLang;
602  $main = RequestContext::getMain();
603 
604  // Save current globals and main context
605  $glob = [
606  'title' => $wgTitle,
607  'output' => $wgOut,
608  'request' => $wgRequest,
609  'user' => $wgUser,
610  'language' => $wgLang,
611  ];
612  $ctx = [
613  'title' => $main->getTitle(),
614  'output' => $main->getOutput(),
615  'request' => $main->getRequest(),
616  'user' => $main->getUser(),
617  'language' => $main->getLanguage(),
618  ];
619  if ( $main->canUseWikiPage() ) {
620  $ctx['wikipage'] = $main->getWikiPage();
621  }
622 
623  // Override
624  $wgTitle = $title;
625  $wgOut = $context->getOutput();
626  $wgRequest = $context->getRequest();
627  $wgUser = $context->getUser();
628  $wgLang = $context->getLanguage();
629  $main->setTitle( $title );
630  $main->setOutput( $context->getOutput() );
631  $main->setRequest( $context->getRequest() );
632  $main->setUser( $context->getUser() );
633  $main->setLanguage( $context->getLanguage() );
634 
635  // The useful part
636  $ret = $this->executePath( $title, $context, true, $linkRenderer );
637 
638  // Restore old globals and context
639  $wgTitle = $glob['title'];
640  $wgOut = $glob['output'];
641  $wgRequest = $glob['request'];
642  $wgUser = $glob['user'];
643  $wgLang = $glob['language'];
644  $main->setTitle( $ctx['title'] );
645  $main->setOutput( $ctx['output'] );
646  $main->setRequest( $ctx['request'] );
647  $main->setUser( $ctx['user'] );
648  $main->setLanguage( $ctx['language'] );
649  if ( isset( $ctx['wikipage'] ) ) {
650  $main->setWikiPage( $ctx['wikipage'] );
651  }
652 
653  return $ret;
654  }
655 
663  public function getLocalNameFor( $name, $subpage = false ) {
664  $aliases = $this->contLang->getSpecialPageAliases();
665  $aliasList = $this->getAliasList();
666 
667  // Find the first alias that maps back to $name
668  if ( isset( $aliases[$name] ) ) {
669  $found = false;
670  foreach ( $aliases[$name] as $alias ) {
671  $caseFoldedAlias = $this->contLang->caseFold( $alias );
672  $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
673  if ( isset( $aliasList[$caseFoldedAlias] ) &&
674  $aliasList[$caseFoldedAlias] === $name
675  ) {
676  $name = $alias;
677  $found = true;
678  break;
679  }
680  }
681  if ( !$found ) {
682  wfWarn( "Did not find a usable alias for special page '$name'. " .
683  "It seems all defined aliases conflict?" );
684  }
685  } else {
686  // Check if someone misspelled the correct casing
687  if ( is_array( $aliases ) ) {
688  foreach ( $aliases as $n => $values ) {
689  if ( strcasecmp( $name, $n ) === 0 ) {
690  wfWarn( "Found alias defined for $n when searching for " .
691  "special page aliases for $name. Case mismatch?" );
692  return $this->getLocalNameFor( $n, $subpage );
693  }
694  }
695  }
696 
697  wfWarn( "Did not find alias for special page '$name'. " .
698  "Perhaps no aliases are defined for it?" );
699  }
700 
701  if ( $subpage !== false && !is_null( $subpage ) ) {
702  // Make sure it's in dbkey form
703  $subpage = str_replace( ' ', '_', $subpage );
704  $name = "$name/$subpage";
705  }
706 
707  return $this->contLang->ucfirst( $name );
708  }
709 
716  public function getTitleForAlias( $alias ) {
717  list( $name, $subpage ) = $this->resolveAlias( $alias );
718  if ( $name != null ) {
719  return SpecialPage::getTitleFor( $name, $subpage );
720  }
721 
722  return null;
723  }
724 }
getRestrictedPages(User $user)
Return categorised listable special pages which are available for the current user, but not for everyone.
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
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.
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:1585
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:1982
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:1982
static instance()
Singleton.
Definition: Profiler.php:62
executePath(Title &$title, IContextSource &$context, $including=false, LinkRenderer $linkRenderer=null)
Execute a special page path.
__construct(array $options, Language $contLang)
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.
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:48
getConfig()
Get the site configuration.
$wgLang
Definition: Setup.php:875
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
Interface for configuration instances.
Definition: Config.php:28
getDBkey()
Get the main part with underscores.
Definition: Title.php:1001
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:780
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:925
getFullURL( $query='', $query2=false, $proto=PROTO_RELATIVE)
Get a real URL referring to this title, with interwiki link and fragment.
Definition: Title.php:1910
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:82
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.
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:271
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:728
$wgOut
Definition: Setup.php:880
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:1473
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200