MediaWiki  master
MediaWikiServices.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki;
4 
7 use Config;
14 use Hooks;
47 use Parser;
71 
108 class MediaWikiServices extends ServiceContainer {
109 
113  private static $instance = null;
114 
129  public static function getInstance() {
130  if ( self::$instance === null ) {
131  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
132  // but some information from the global scope has to be injected here,
133  // even if it's just a file name or database credentials to load
134  // configuration from.
135  $bootstrapConfig = new GlobalVarConfig();
136  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
137  }
138 
139  return self::$instance;
140  }
141 
155  public static function forceGlobalInstance( MediaWikiServices $services ) {
156  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
157  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
158  }
159 
160  $old = self::getInstance();
161  self::$instance = $services;
162 
163  return $old;
164  }
165 
205  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
206  if ( self::$instance === null ) {
207  // no global instance yet, nothing to reset
208  return;
209  }
210 
211  self::failIfResetNotAllowed( __METHOD__ );
212 
213  if ( $bootstrapConfig === null ) {
214  $bootstrapConfig = self::$instance->getBootstrapConfig();
215  }
216 
217  $oldInstance = self::$instance;
218 
219  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
220  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
221 
222  if ( $quick === 'quick' ) {
223  self::$instance->salvage( $oldInstance );
224  } else {
225  $oldInstance->destroy();
226  }
227  }
228 
238  private function salvage( self $other ) {
239  foreach ( $this->getServiceNames() as $name ) {
240  // The service could be new in the new instance and not registered in the
241  // other instance (e.g. an extension that was loaded after the instantiation of
242  // the other instance. Skip this service in this case. See T143974
243  try {
244  $oldService = $other->peekService( $name );
245  } catch ( NoSuchServiceException $e ) {
246  continue;
247  }
248 
249  if ( $oldService instanceof SalvageableService ) {
251  $newService = $this->getService( $name );
252  $newService->salvage( $oldService );
253  }
254  }
255 
256  $other->destroy();
257  }
258 
274  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
275  $instance = new self( $bootstrapConfig );
276 
277  // Load the default wiring from the specified files.
278  if ( $loadWiring === 'load' ) {
279  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
280  $instance->loadWiringFiles( $wiringFiles );
281  }
282 
283  // Provide a traditional hook point to allow extensions to configure services.
284  Hooks::run( 'MediaWikiServices', [ $instance ] );
285 
286  return $instance;
287  }
288 
304  public static function disableStorageBackend() {
305  // TODO: also disable some Caches, JobQueues, etc
306  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
307  $services = self::getInstance();
308 
309  foreach ( $destroy as $name ) {
310  $services->disableService( $name );
311  }
312 
314  }
315 
328  public static function resetChildProcessServices() {
329  // NOTE: for now, just reset everything. Since we don't know the interdependencies
330  // between services, we can't do this more selectively at this time.
331  self::resetGlobalInstance();
332 
333  // Child, reseed because there is no bug in PHP:
334  // https://bugs.php.net/bug.php?id=42465
335  mt_srand( getmypid() );
336  }
337 
359  public function resetServiceForTesting( $name, $destroy = true ) {
360  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
361  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
362  }
363 
364  $this->resetService( $name, $destroy );
365  }
366 
394  public static function failIfResetNotAllowed( $method ) {
395  if ( !defined( 'MW_PHPUNIT_TEST' )
396  && !defined( 'MW_PARSER_TEST' )
397  && !defined( 'MEDIAWIKI_INSTALL' )
398  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
399  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
400  ) {
401  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
402  }
403  }
404 
410  public function __construct( Config $config ) {
411  parent::__construct();
412 
413  // Register the given Config object as the bootstrap config service.
414  $this->defineService( 'BootstrapConfig', function () use ( $config ) {
415  return $config;
416  } );
417  }
418 
419  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
420 
425  public function getActorMigration() {
426  return $this->getService( 'ActorMigration' );
427  }
428 
433  public function getBlobStore() {
434  return $this->getService( '_SqlBlobStore' );
435  }
436 
441  public function getBlobStoreFactory() {
442  return $this->getService( 'BlobStoreFactory' );
443  }
444 
449  public function getBlockManager() : BlockManager {
450  return $this->getService( 'BlockManager' );
451  }
452 
457  public function getBlockRestrictionStore() : BlockRestrictionStore {
458  return $this->getService( 'BlockRestrictionStore' );
459  }
460 
474  public function getBootstrapConfig() {
475  return $this->getService( 'BootstrapConfig' );
476  }
477 
482  public function getChangeTagDefStore() {
483  return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
484  }
485 
490  public function getCommentStore() {
491  return $this->getService( 'CommentStore' );
492  }
493 
498  public function getConfigFactory() {
499  return $this->getService( 'ConfigFactory' );
500  }
501 
506  public function getConfigRepository() {
507  return $this->getService( 'ConfigRepository' );
508  }
509 
514  public function getConfiguredReadOnlyMode() {
515  return $this->getService( 'ConfiguredReadOnlyMode' );
516  }
517 
522  public function getContentLanguage() {
523  return $this->getService( 'ContentLanguage' );
524  }
525 
530  public function getContentModelStore() {
531  return $this->getService( 'NameTableStoreFactory' )->getContentModels();
532  }
533 
538  public function getCryptHKDF() {
539  return $this->getService( 'CryptHKDF' );
540  }
541 
546  public function getDateFormatterFactory() {
547  return $this->getService( 'DateFormatterFactory' );
548  }
549 
554  public function getDBLoadBalancer() {
555  return $this->getService( 'DBLoadBalancer' );
556  }
557 
562  public function getDBLoadBalancerFactory() {
563  return $this->getService( 'DBLoadBalancerFactory' );
564  }
565 
570  public function getEventRelayerGroup() {
571  return $this->getService( 'EventRelayerGroup' );
572  }
573 
578  public function getExternalStoreFactory() {
579  return $this->getService( 'ExternalStoreFactory' );
580  }
581 
586  public function getGenderCache() {
587  return $this->getService( 'GenderCache' );
588  }
589 
594  public function getHttpRequestFactory() {
595  return $this->getService( 'HttpRequestFactory' );
596  }
597 
602  public function getInterwikiLookup() {
603  return $this->getService( 'InterwikiLookup' );
604  }
605 
610  public function getLinkCache() {
611  return $this->getService( 'LinkCache' );
612  }
613 
621  public function getLinkRenderer() {
622  return $this->getService( 'LinkRenderer' );
623  }
624 
629  public function getLinkRendererFactory() {
630  return $this->getService( 'LinkRendererFactory' );
631  }
632 
637  public function getLocalServerObjectCache() {
638  return $this->getService( 'LocalServerObjectCache' );
639  }
640 
645  public function getMagicWordFactory() {
646  return $this->getService( 'MagicWordFactory' );
647  }
648 
656  public function getMainConfig() {
657  return $this->getService( 'MainConfig' );
658  }
659 
664  public function getMainObjectStash() {
665  return $this->getService( 'MainObjectStash' );
666  }
667 
672  public function getMainWANObjectCache() {
673  return $this->getService( 'MainWANObjectCache' );
674  }
675 
680  public function getMediaHandlerFactory() {
681  return $this->getService( 'MediaHandlerFactory' );
682  }
683 
688  public function getMimeAnalyzer() {
689  return $this->getService( 'MimeAnalyzer' );
690  }
691 
696  public function getNamespaceInfo() : NamespaceInfo {
697  return $this->getService( 'NamespaceInfo' );
698  }
699 
704  public function getNameTableStoreFactory() {
705  return $this->getService( 'NameTableStoreFactory' );
706  }
707 
712  public function getOldRevisionImporter() {
713  return $this->getService( 'OldRevisionImporter' );
714  }
715 
720  public function getPageEditStash() {
721  return $this->getService( 'PageEditStash' );
722  }
723 
728  public function getParser() {
729  return $this->getService( 'Parser' );
730  }
731 
736  public function getParserCache() {
737  return $this->getService( 'ParserCache' );
738  }
739 
744  public function getParserFactory() {
745  return $this->getService( 'ParserFactory' );
746  }
747 
752  public function getPasswordFactory() {
753  return $this->getService( 'PasswordFactory' );
754  }
755 
760  public function getPerDbNameStatsdDataFactory() {
761  return $this->getService( 'PerDbNameStatsdDataFactory' );
762  }
763 
768  public function getPermissionManager() {
769  return $this->getService( 'PermissionManager' );
770  }
771 
776  public function getPreferencesFactory() {
777  return $this->getService( 'PreferencesFactory' );
778  }
779 
784  public function getProxyLookup() {
785  return $this->getService( 'ProxyLookup' );
786  }
787 
792  public function getReadOnlyMode() {
793  return $this->getService( 'ReadOnlyMode' );
794  }
795 
800  public function getRepoGroup() : RepoGroup {
801  return $this->getService( 'RepoGroup' );
802  }
803 
808  public function getResourceLoader() {
809  return $this->getService( 'ResourceLoader' );
810  }
811 
816  public function getRevisionFactory() {
817  return $this->getService( 'RevisionFactory' );
818  }
819 
824  public function getRevisionLookup() {
825  return $this->getService( 'RevisionLookup' );
826  }
827 
832  public function getRevisionRenderer() {
833  return $this->getService( 'RevisionRenderer' );
834  }
835 
840  public function getRevisionStore() {
841  return $this->getService( 'RevisionStore' );
842  }
843 
848  public function getRevisionStoreFactory() {
849  return $this->getService( 'RevisionStoreFactory' );
850  }
851 
856  public function newSearchEngine() {
857  // New engine object every time, since they keep state
858  return $this->getService( 'SearchEngineFactory' )->create();
859  }
860 
865  public function getSearchEngineConfig() {
866  return $this->getService( 'SearchEngineConfig' );
867  }
868 
873  public function getSearchEngineFactory() {
874  return $this->getService( 'SearchEngineFactory' );
875  }
876 
881  public function getShellCommandFactory() {
882  return $this->getService( 'ShellCommandFactory' );
883  }
884 
889  public function getSiteLookup() {
890  return $this->getService( 'SiteLookup' );
891  }
892 
897  public function getSiteStore() {
898  return $this->getService( 'SiteStore' );
899  }
900 
905  public function getSkinFactory() {
906  return $this->getService( 'SkinFactory' );
907  }
908 
913  public function getSlotRoleRegistry() {
914  return $this->getService( 'SlotRoleRegistry' );
915  }
916 
921  public function getSlotRoleStore() {
922  return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
923  }
924 
930  return $this->getService( 'SpecialPageFactory' );
931  }
932 
937  public function getStatsdDataFactory() {
938  return $this->getService( 'StatsdDataFactory' );
939  }
940 
945  public function getTitleFormatter() {
946  return $this->getService( 'TitleFormatter' );
947  }
948 
953  public function getTitleParser() {
954  return $this->getService( 'TitleParser' );
955  }
956 
961  public function getUploadRevisionImporter() {
962  return $this->getService( 'UploadRevisionImporter' );
963  }
964 
969  public function getVirtualRESTServiceClient() {
970  return $this->getService( 'VirtualRESTServiceClient' );
971  }
972 
977  public function getWatchedItemQueryService() {
978  return $this->getService( 'WatchedItemQueryService' );
979  }
980 
985  public function getWatchedItemStore() {
986  return $this->getService( 'WatchedItemStore' );
987  }
988 
994  return $this->getService( 'OldRevisionImporter' );
995  }
996 
1002  return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
1003  }
1004 
1009  public function getWikiRevisionUploadImporter() {
1010  return $this->getService( 'UploadRevisionImporter' );
1011  }
1012 
1013 }
In both all secondary updates will be triggered handle like object that caches derived data representing a and can trigger updates of cached copies of that e g in the links the ParserCache
Definition: pageupdater.txt:78
getLinkRenderer()
LinkRenderer instance that can be used if no custom options are needed.
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2159
salvage(self $other)
PhpDocSignatureInspection
A helper class for throttling authentication attempts.
static getInstance()
Returns the global default instance of the top level service locator.
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Interface for configuration instances.
Definition: Config.php:28
getMainConfig()
Returns the Config object that provides configuration for MediaWiki core.
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title e g db for database replication lag or jobqueue for job queue size converted to pseudo seconds It is possible to add more fields and they will be returned to the user in the API response after the basic globals have been set but before ordinary actions take place or wrap services the preferred way to define a new service is the $wgServiceWiringFiles array $services
Definition: hooks.txt:2217
Wrapper for backward compatibility for old callers that used static methods.
static resetChildProcessServices()
Resets any services that may have become stale after a child process returns from after pcntl_fork()...
static resetGlobalInstance(Config $bootstrapConfig=null, $quick='')
Creates a new instance of MediaWikiServices and sets it as the global default instance.
static disableStorageBackend()
Disables all storage layer services.
static failIfResetNotAllowed( $method)
Convenience method that throws an exception unless it is called during a phase in which resetting of ...
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
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
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
resetServiceForTesting( $name, $destroy=true)
Resets the given service for testing purposes.
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:271
getBootstrapConfig()
Returns the Config object containing the bootstrap configuration.
static clear()
Clear all the cached instances.
MediaWikiServices is the service locator for the application scope of MediaWiki.
static newInstance(Config $bootstrapConfig, $loadWiring='')
Creates a new MediaWikiServices instance and initializes it according to the given $bootstrapConfig...
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
static forceGlobalInstance(MediaWikiServices $services)
Replaces the global MediaWikiServices instance.