MediaWiki  master
MediaWikiServices.php
Go to the documentation of this file.
1 <?php
2 namespace MediaWiki;
3 
6 use Config;
13 use Hooks;
42 use Parser;
64 
101 class MediaWikiServices extends ServiceContainer {
102 
106  private static $instance = null;
107 
122  public static function getInstance() {
123  if ( self::$instance === null ) {
124  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
125  // but some information from the global scope has to be injected here,
126  // even if it's just a file name or database credentials to load
127  // configuration from.
128  $bootstrapConfig = new GlobalVarConfig();
129  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
130  }
131 
132  return self::$instance;
133  }
134 
148  public static function forceGlobalInstance( MediaWikiServices $services ) {
149  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
150  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
151  }
152 
153  $old = self::getInstance();
154  self::$instance = $services;
155 
156  return $old;
157  }
158 
198  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
199  if ( self::$instance === null ) {
200  // no global instance yet, nothing to reset
201  return;
202  }
203 
204  self::failIfResetNotAllowed( __METHOD__ );
205 
206  if ( $bootstrapConfig === null ) {
207  $bootstrapConfig = self::$instance->getBootstrapConfig();
208  }
209 
210  $oldInstance = self::$instance;
211 
212  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
213  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
214 
215  if ( $quick === 'quick' ) {
216  self::$instance->salvage( $oldInstance );
217  } else {
218  $oldInstance->destroy();
219  }
220  }
221 
229  private function salvage( self $other ) {
230  foreach ( $this->getServiceNames() as $name ) {
231  // The service could be new in the new instance and not registered in the
232  // other instance (e.g. an extension that was loaded after the instantiation of
233  // the other instance. Skip this service in this case. See T143974
234  try {
235  $oldService = $other->peekService( $name );
236  } catch ( NoSuchServiceException $e ) {
237  continue;
238  }
239 
240  if ( $oldService instanceof SalvageableService ) {
242  $newService = $this->getService( $name );
243  $newService->salvage( $oldService );
244  }
245  }
246 
247  $other->destroy();
248  }
249 
265  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
266  $instance = new self( $bootstrapConfig );
267 
268  // Load the default wiring from the specified files.
269  if ( $loadWiring === 'load' ) {
270  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
271  $instance->loadWiringFiles( $wiringFiles );
272  }
273 
274  // Provide a traditional hook point to allow extensions to configure services.
275  Hooks::run( 'MediaWikiServices', [ $instance ] );
276 
277  return $instance;
278  }
279 
295  public static function disableStorageBackend() {
296  // TODO: also disable some Caches, JobQueues, etc
297  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
298  $services = self::getInstance();
299 
300  foreach ( $destroy as $name ) {
301  $services->disableService( $name );
302  }
303 
305  }
306 
319  public static function resetChildProcessServices() {
320  // NOTE: for now, just reset everything. Since we don't know the interdependencies
321  // between services, we can't do this more selectively at this time.
322  self::resetGlobalInstance();
323 
324  // Child, reseed because there is no bug in PHP:
325  // https://bugs.php.net/bug.php?id=42465
326  mt_srand( getmypid() );
327  }
328 
350  public function resetServiceForTesting( $name, $destroy = true ) {
351  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
352  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
353  }
354 
355  $this->resetService( $name, $destroy );
356  }
357 
385  public static function failIfResetNotAllowed( $method ) {
386  if ( !defined( 'MW_PHPUNIT_TEST' )
387  && !defined( 'MW_PARSER_TEST' )
388  && !defined( 'MEDIAWIKI_INSTALL' )
389  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
390  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
391  ) {
392  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
393  }
394  }
395 
401  public function __construct( Config $config ) {
402  parent::__construct();
403 
404  // Register the given Config object as the bootstrap config service.
405  $this->defineService( 'BootstrapConfig', function () use ( $config ) {
406  return $config;
407  } );
408  }
409 
410  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
411 
416  public function getActorMigration() {
417  return $this->getService( 'ActorMigration' );
418  }
419 
424  public function getBlobStore() {
425  return $this->getService( '_SqlBlobStore' );
426  }
427 
432  public function getBlobStoreFactory() {
433  return $this->getService( 'BlobStoreFactory' );
434  }
435 
449  public function getBootstrapConfig() {
450  return $this->getService( 'BootstrapConfig' );
451  }
452 
457  public function getChangeTagDefStore() {
458  return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
459  }
460 
465  public function getCommentStore() {
466  return $this->getService( 'CommentStore' );
467  }
468 
473  public function getConfigFactory() {
474  return $this->getService( 'ConfigFactory' );
475  }
476 
481  public function getConfigRepository() {
482  return $this->getService( 'ConfigRepository' );
483  }
484 
489  public function getConfiguredReadOnlyMode() {
490  return $this->getService( 'ConfiguredReadOnlyMode' );
491  }
492 
497  public function getContentLanguage() {
498  return $this->getService( 'ContentLanguage' );
499  }
500 
505  public function getContentModelStore() {
506  return $this->getService( 'NameTableStoreFactory' )->getContentModels();
507  }
508 
513  public function getCryptHKDF() {
514  return $this->getService( 'CryptHKDF' );
515  }
516 
522  public function getCryptRand() {
523  wfDeprecated( __METHOD__, '1.32' );
524  return $this->getService( 'CryptRand' );
525  }
526 
531  public function getDBLoadBalancer() {
532  return $this->getService( 'DBLoadBalancer' );
533  }
534 
539  public function getDBLoadBalancerFactory() {
540  return $this->getService( 'DBLoadBalancerFactory' );
541  }
542 
547  public function getEventRelayerGroup() {
548  return $this->getService( 'EventRelayerGroup' );
549  }
550 
555  public function getExternalStoreFactory() {
556  return $this->getService( 'ExternalStoreFactory' );
557  }
558 
563  public function getGenderCache() {
564  return $this->getService( 'GenderCache' );
565  }
566 
571  public function getHttpRequestFactory() {
572  return $this->getService( 'HttpRequestFactory' );
573  }
574 
579  public function getInterwikiLookup() {
580  return $this->getService( 'InterwikiLookup' );
581  }
582 
587  public function getLinkCache() {
588  return $this->getService( 'LinkCache' );
589  }
590 
598  public function getLinkRenderer() {
599  return $this->getService( 'LinkRenderer' );
600  }
601 
606  public function getLinkRendererFactory() {
607  return $this->getService( 'LinkRendererFactory' );
608  }
609 
614  public function getLocalServerObjectCache() {
615  return $this->getService( 'LocalServerObjectCache' );
616  }
617 
622  public function getMagicWordFactory() {
623  return $this->getService( 'MagicWordFactory' );
624  }
625 
633  public function getMainConfig() {
634  return $this->getService( 'MainConfig' );
635  }
636 
641  public function getMainObjectStash() {
642  return $this->getService( 'MainObjectStash' );
643  }
644 
649  public function getMainWANObjectCache() {
650  return $this->getService( 'MainWANObjectCache' );
651  }
652 
657  public function getMediaHandlerFactory() {
658  return $this->getService( 'MediaHandlerFactory' );
659  }
660 
665  public function getMimeAnalyzer() {
666  return $this->getService( 'MimeAnalyzer' );
667  }
668 
673  public function getNameTableStoreFactory() {
674  return $this->getService( 'NameTableStoreFactory' );
675  }
676 
680  public function getOldRevisionImporter() {
681  return $this->getService( 'OldRevisionImporter' );
682  }
683 
688  public function getParser() {
689  return $this->getService( 'Parser' );
690  }
691 
696  public function getParserCache() {
697  return $this->getService( 'ParserCache' );
698  }
699 
704  public function getParserFactory() {
705  return $this->getService( 'ParserFactory' );
706  }
707 
712  public function getPasswordFactory() {
713  return $this->getService( 'PasswordFactory' );
714  }
715 
720  public function getPerDbNameStatsdDataFactory() {
721  return $this->getService( 'PerDbNameStatsdDataFactory' );
722  }
723 
728  public function getPreferencesFactory() {
729  return $this->getService( 'PreferencesFactory' );
730  }
731 
736  public function getProxyLookup() {
737  return $this->getService( 'ProxyLookup' );
738  }
739 
744  public function getReadOnlyMode() {
745  return $this->getService( 'ReadOnlyMode' );
746  }
747 
752  public function getResourceLoader() {
753  return $this->getService( 'ResourceLoader' );
754  }
755 
760  public function getRevisionFactory() {
761  return $this->getService( 'RevisionFactory' );
762  }
763 
768  public function getRevisionLookup() {
769  return $this->getService( 'RevisionLookup' );
770  }
771 
776  public function getRevisionRenderer() {
777  return $this->getService( 'RevisionRenderer' );
778  }
779 
784  public function getRevisionStore() {
785  return $this->getService( 'RevisionStore' );
786  }
787 
792  public function getRevisionStoreFactory() {
793  return $this->getService( 'RevisionStoreFactory' );
794  }
795 
800  public function newSearchEngine() {
801  // New engine object every time, since they keep state
802  return $this->getService( 'SearchEngineFactory' )->create();
803  }
804 
809  public function getSearchEngineConfig() {
810  return $this->getService( 'SearchEngineConfig' );
811  }
812 
817  public function getSearchEngineFactory() {
818  return $this->getService( 'SearchEngineFactory' );
819  }
820 
825  public function getShellCommandFactory() {
826  return $this->getService( 'ShellCommandFactory' );
827  }
828 
833  public function getSiteLookup() {
834  return $this->getService( 'SiteLookup' );
835  }
836 
841  public function getSiteStore() {
842  return $this->getService( 'SiteStore' );
843  }
844 
849  public function getSkinFactory() {
850  return $this->getService( 'SkinFactory' );
851  }
852 
857  public function getSlotRoleRegistry() {
858  return $this->getService( 'SlotRoleRegistry' );
859  }
860 
865  public function getSlotRoleStore() {
866  return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
867  }
868 
874  return $this->getService( 'SpecialPageFactory' );
875  }
876 
881  public function getStatsdDataFactory() {
882  return $this->getService( 'StatsdDataFactory' );
883  }
884 
889  public function getTitleFormatter() {
890  return $this->getService( 'TitleFormatter' );
891  }
892 
897  public function getTitleParser() {
898  return $this->getService( 'TitleParser' );
899  }
900 
905  public function getUploadRevisionImporter() {
906  return $this->getService( 'UploadRevisionImporter' );
907  }
908 
913  public function getVirtualRESTServiceClient() {
914  return $this->getService( 'VirtualRESTServiceClient' );
915  }
916 
921  public function getWatchedItemQueryService() {
922  return $this->getService( 'WatchedItemQueryService' );
923  }
924 
929  public function getWatchedItemStore() {
930  return $this->getService( 'WatchedItemStore' );
931  }
932 
938  return $this->getService( 'OldRevisionImporter' );
939  }
940 
946  return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
947  }
948 
953  public function getWikiRevisionUploadImporter() {
954  return $this->getService( 'UploadRevisionImporter' );
955  }
956 
957 }
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:2172
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.".
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:2220
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
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
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.