MediaWiki  1.28.1
MediaWikiServices.php
Go to the documentation of this file.
1 <?php
2 namespace MediaWiki;
3 
4 use Config;
11 use Hooks;
38 
75 class MediaWikiServices extends ServiceContainer {
76 
80  private static $instance = null;
81 
96  public static function getInstance() {
97  if ( self::$instance === null ) {
98  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
99  // but some information from the global scope has to be injected here,
100  // even if it's just a file name or database credentials to load
101  // configuration from.
102  $bootstrapConfig = new GlobalVarConfig();
103  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
104  }
105 
106  return self::$instance;
107  }
108 
122  public static function forceGlobalInstance( MediaWikiServices $services ) {
123  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
124  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
125  }
126 
127  $old = self::getInstance();
128  self::$instance = $services;
129 
130  return $old;
131  }
132 
172  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
173  if ( self::$instance === null ) {
174  // no global instance yet, nothing to reset
175  return;
176  }
177 
178  self::failIfResetNotAllowed( __METHOD__ );
179 
180  if ( $bootstrapConfig === null ) {
181  $bootstrapConfig = self::$instance->getBootstrapConfig();
182  }
183 
184  $oldInstance = self::$instance;
185 
186  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
187  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
188 
189  if ( $quick === 'quick' ) {
190  self::$instance->salvage( $oldInstance );
191  } else {
192  $oldInstance->destroy();
193  }
194 
195  }
196 
204  private function salvage( self $other ) {
205  foreach ( $this->getServiceNames() as $name ) {
206  // The service could be new in the new instance and not registered in the
207  // other instance (e.g. an extension that was loaded after the instantiation of
208  // the other instance. Skip this service in this case. See T143974
209  try {
210  $oldService = $other->peekService( $name );
211  } catch ( NoSuchServiceException $e ) {
212  continue;
213  }
214 
215  if ( $oldService instanceof SalvageableService ) {
217  $newService = $this->getService( $name );
218  $newService->salvage( $oldService );
219  }
220  }
221 
222  $other->destroy();
223  }
224 
240  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
241  $instance = new self( $bootstrapConfig );
242 
243  // Load the default wiring from the specified files.
244  if ( $loadWiring === 'load' ) {
245  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
246  $instance->loadWiringFiles( $wiringFiles );
247  }
248 
249  // Provide a traditional hook point to allow extensions to configure services.
250  Hooks::run( 'MediaWikiServices', [ $instance ] );
251 
252  return $instance;
253  }
254 
270  public static function disableStorageBackend() {
271  // TODO: also disable some Caches, JobQueues, etc
272  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
273  $services = self::getInstance();
274 
275  foreach ( $destroy as $name ) {
276  $services->disableService( $name );
277  }
278 
280  }
281 
294  public static function resetChildProcessServices() {
295  // NOTE: for now, just reset everything. Since we don't know the interdependencies
296  // between services, we can't do this more selectively at this time.
297  self::resetGlobalInstance();
298 
299  // Child, reseed because there is no bug in PHP:
300  // http://bugs.php.net/bug.php?id=42465
301  mt_srand( getmypid() );
302  }
303 
325  public function resetServiceForTesting( $name, $destroy = true ) {
326  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
327  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
328  }
329 
330  $this->resetService( $name, $destroy );
331  }
332 
360  public static function failIfResetNotAllowed( $method ) {
361  if ( !defined( 'MW_PHPUNIT_TEST' )
362  && !defined( 'MW_PARSER_TEST' )
363  && !defined( 'MEDIAWIKI_INSTALL' )
364  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
365  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
366  ) {
367  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
368  }
369  }
370 
376  public function __construct( Config $config ) {
377  parent::__construct();
378 
379  // Register the given Config object as the bootstrap config service.
380  $this->defineService( 'BootstrapConfig', function() use ( $config ) {
381  return $config;
382  } );
383  }
384 
385  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
386 
400  public function getBootstrapConfig() {
401  return $this->getService( 'BootstrapConfig' );
402  }
403 
408  public function getConfigFactory() {
409  return $this->getService( 'ConfigFactory' );
410  }
411 
419  public function getMainConfig() {
420  return $this->getService( 'MainConfig' );
421  }
422 
427  public function getSiteLookup() {
428  return $this->getService( 'SiteLookup' );
429  }
430 
435  public function getSiteStore() {
436  return $this->getService( 'SiteStore' );
437  }
438 
443  public function getInterwikiLookup() {
444  return $this->getService( 'InterwikiLookup' );
445  }
446 
451  public function getStatsdDataFactory() {
452  return $this->getService( 'StatsdDataFactory' );
453  }
454 
459  public function getEventRelayerGroup() {
460  return $this->getService( 'EventRelayerGroup' );
461  }
462 
467  public function newSearchEngine() {
468  // New engine object every time, since they keep state
469  return $this->getService( 'SearchEngineFactory' )->create();
470  }
471 
476  public function getSearchEngineFactory() {
477  return $this->getService( 'SearchEngineFactory' );
478  }
479 
484  public function getSearchEngineConfig() {
485  return $this->getService( 'SearchEngineConfig' );
486  }
487 
492  public function getSkinFactory() {
493  return $this->getService( 'SkinFactory' );
494  }
495 
500  public function getDBLoadBalancerFactory() {
501  return $this->getService( 'DBLoadBalancerFactory' );
502  }
503 
508  public function getDBLoadBalancer() {
509  return $this->getService( 'DBLoadBalancer' );
510  }
511 
516  public function getWatchedItemStore() {
517  return $this->getService( 'WatchedItemStore' );
518  }
519 
524  public function getWatchedItemQueryService() {
525  return $this->getService( 'WatchedItemQueryService' );
526  }
527 
532  public function getCryptRand() {
533  return $this->getService( 'CryptRand' );
534  }
535 
540  public function getCryptHKDF() {
541  return $this->getService( 'CryptHKDF' );
542  }
543 
548  public function getMediaHandlerFactory() {
549  return $this->getService( 'MediaHandlerFactory' );
550  }
551 
556  public function getMimeAnalyzer() {
557  return $this->getService( 'MimeAnalyzer' );
558  }
559 
564  public function getProxyLookup() {
565  return $this->getService( 'ProxyLookup' );
566  }
567 
572  public function getGenderCache() {
573  return $this->getService( 'GenderCache' );
574  }
575 
580  public function getLinkCache() {
581  return $this->getService( 'LinkCache' );
582  }
583 
588  public function getLinkRendererFactory() {
589  return $this->getService( 'LinkRendererFactory' );
590  }
591 
599  public function getLinkRenderer() {
600  return $this->getService( 'LinkRenderer' );
601  }
602 
607  public function getTitleFormatter() {
608  return $this->getService( 'TitleFormatter' );
609  }
610 
615  public function getTitleParser() {
616  return $this->getService( 'TitleParser' );
617  }
618 
623  public function getMainObjectStash() {
624  return $this->getService( 'MainObjectStash' );
625  }
626 
631  public function getMainWANObjectCache() {
632  return $this->getService( 'MainWANObjectCache' );
633  }
634 
639  public function getLocalServerObjectCache() {
640  return $this->getService( 'LocalServerObjectCache' );
641  }
642 
647  public function getVirtualRESTServiceClient() {
648  return $this->getService( 'VirtualRESTServiceClient' );
649  }
650 
652  // NOTE: When adding a service getter here, don't forget to add a test
653  // case for it in MediaWikiServicesTest::provideGetters() and in
654  // MediaWikiServicesTest::provideGetService()!
656 
657 }
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:2102
salvage(self $other)
Salvages the state of any salvageable service instances in $other.
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.".
resetServiceForTesting($name, $destroy=true)
Resets the given service for testing purposes.
getMainConfig()
Returns the Config object that provides configuration for MediaWiki core.
static resetChildProcessServices()
Resets any services that may have become stale after a child process returns from after pcntl_fork()...
static disableStorageBackend()
Disables all storage layer services.
static run($event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
static resetGlobalInstance(Config $bootstrapConfig=null, $quick= '')
Creates a new instance of MediaWikiServices and sets it as the global default instance.
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title 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:2159
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
static failIfResetNotAllowed($method)
Convenience method that throws an exception unless it is called during a phase in which resetting of ...
static newInstance(Config $bootstrapConfig, $loadWiring= '')
Creates a new MediaWikiServices instance and initializes it according to the given $bootstrapConfig...
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 forceGlobalInstance(MediaWikiServices $services)
Replaces the global MediaWikiServices instance.
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:300