MediaWiki  master
MediaWikiServices.php
Go to the documentation of this file.
1 <?php
2 namespace MediaWiki;
3 
6 use Config;
13 use Hooks;
44 use Parser;
66 
103 class MediaWikiServices extends ServiceContainer {
104 
108  private static $instance = null;
109 
124  public static function getInstance() {
125  if ( self::$instance === null ) {
126  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
127  // but some information from the global scope has to be injected here,
128  // even if it's just a file name or database credentials to load
129  // configuration from.
130  $bootstrapConfig = new GlobalVarConfig();
131  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
132  }
133 
134  return self::$instance;
135  }
136 
150  public static function forceGlobalInstance( MediaWikiServices $services ) {
151  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
152  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
153  }
154 
155  $old = self::getInstance();
156  self::$instance = $services;
157 
158  return $old;
159  }
160 
200  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
201  if ( self::$instance === null ) {
202  // no global instance yet, nothing to reset
203  return;
204  }
205 
206  self::failIfResetNotAllowed( __METHOD__ );
207 
208  if ( $bootstrapConfig === null ) {
209  $bootstrapConfig = self::$instance->getBootstrapConfig();
210  }
211 
212  $oldInstance = self::$instance;
213 
214  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
215  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
216 
217  if ( $quick === 'quick' ) {
218  self::$instance->salvage( $oldInstance );
219  } else {
220  $oldInstance->destroy();
221  }
222  }
223 
231  private function salvage( self $other ) {
232  foreach ( $this->getServiceNames() as $name ) {
233  // The service could be new in the new instance and not registered in the
234  // other instance (e.g. an extension that was loaded after the instantiation of
235  // the other instance. Skip this service in this case. See T143974
236  try {
237  $oldService = $other->peekService( $name );
238  } catch ( NoSuchServiceException $e ) {
239  continue;
240  }
241 
242  if ( $oldService instanceof SalvageableService ) {
244  $newService = $this->getService( $name );
245  $newService->salvage( $oldService );
246  }
247  }
248 
249  $other->destroy();
250  }
251 
267  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
268  $instance = new self( $bootstrapConfig );
269 
270  // Load the default wiring from the specified files.
271  if ( $loadWiring === 'load' ) {
272  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
273  $instance->loadWiringFiles( $wiringFiles );
274  }
275 
276  // Provide a traditional hook point to allow extensions to configure services.
277  Hooks::run( 'MediaWikiServices', [ $instance ] );
278 
279  return $instance;
280  }
281 
297  public static function disableStorageBackend() {
298  // TODO: also disable some Caches, JobQueues, etc
299  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
300  $services = self::getInstance();
301 
302  foreach ( $destroy as $name ) {
303  $services->disableService( $name );
304  }
305 
307  }
308 
321  public static function resetChildProcessServices() {
322  // NOTE: for now, just reset everything. Since we don't know the interdependencies
323  // between services, we can't do this more selectively at this time.
324  self::resetGlobalInstance();
325 
326  // Child, reseed because there is no bug in PHP:
327  // https://bugs.php.net/bug.php?id=42465
328  mt_srand( getmypid() );
329  }
330 
352  public function resetServiceForTesting( $name, $destroy = true ) {
353  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
354  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
355  }
356 
357  $this->resetService( $name, $destroy );
358  }
359 
387  public static function failIfResetNotAllowed( $method ) {
388  if ( !defined( 'MW_PHPUNIT_TEST' )
389  && !defined( 'MW_PARSER_TEST' )
390  && !defined( 'MEDIAWIKI_INSTALL' )
391  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
392  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
393  ) {
394  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
395  }
396  }
397 
403  public function __construct( Config $config ) {
404  parent::__construct();
405 
406  // Register the given Config object as the bootstrap config service.
407  $this->defineService( 'BootstrapConfig', function () use ( $config ) {
408  return $config;
409  } );
410  }
411 
412  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
413 
418  public function getActorMigration() {
419  return $this->getService( 'ActorMigration' );
420  }
421 
426  public function getBlobStore() {
427  return $this->getService( '_SqlBlobStore' );
428  }
429 
434  public function getBlobStoreFactory() {
435  return $this->getService( 'BlobStoreFactory' );
436  }
437 
451  public function getBootstrapConfig() {
452  return $this->getService( 'BootstrapConfig' );
453  }
454 
459  public function getChangeTagDefStore() {
460  return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
461  }
462 
467  public function getCommentStore() {
468  return $this->getService( 'CommentStore' );
469  }
470 
475  public function getConfigFactory() {
476  return $this->getService( 'ConfigFactory' );
477  }
478 
483  public function getConfigRepository() {
484  return $this->getService( 'ConfigRepository' );
485  }
486 
491  public function getConfiguredReadOnlyMode() {
492  return $this->getService( 'ConfiguredReadOnlyMode' );
493  }
494 
499  public function getContentLanguage() {
500  return $this->getService( 'ContentLanguage' );
501  }
502 
507  public function getContentModelStore() {
508  return $this->getService( 'NameTableStoreFactory' )->getContentModels();
509  }
510 
515  public function getCryptHKDF() {
516  return $this->getService( 'CryptHKDF' );
517  }
518 
523  public function getDateFormatterFactory() {
524  return $this->getService( 'DateFormatterFactory' );
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 getNamespaceInfo() : NamespaceInfo {
674  return $this->getService( 'NamespaceInfo' );
675  }
676 
681  public function getNameTableStoreFactory() {
682  return $this->getService( 'NameTableStoreFactory' );
683  }
684 
689  public function getOldRevisionImporter() {
690  return $this->getService( 'OldRevisionImporter' );
691  }
692 
697  public function getParser() {
698  return $this->getService( 'Parser' );
699  }
700 
705  public function getParserCache() {
706  return $this->getService( 'ParserCache' );
707  }
708 
713  public function getParserFactory() {
714  return $this->getService( 'ParserFactory' );
715  }
716 
721  public function getPasswordFactory() {
722  return $this->getService( 'PasswordFactory' );
723  }
724 
729  public function getPerDbNameStatsdDataFactory() {
730  return $this->getService( 'PerDbNameStatsdDataFactory' );
731  }
732 
737  public function getPermissionManager() {
738  return $this->getService( 'PermissionManager' );
739  }
740 
745  public function getPreferencesFactory() {
746  return $this->getService( 'PreferencesFactory' );
747  }
748 
753  public function getProxyLookup() {
754  return $this->getService( 'ProxyLookup' );
755  }
756 
761  public function getReadOnlyMode() {
762  return $this->getService( 'ReadOnlyMode' );
763  }
764 
769  public function getResourceLoader() {
770  return $this->getService( 'ResourceLoader' );
771  }
772 
777  public function getRevisionFactory() {
778  return $this->getService( 'RevisionFactory' );
779  }
780 
785  public function getRevisionLookup() {
786  return $this->getService( 'RevisionLookup' );
787  }
788 
793  public function getRevisionRenderer() {
794  return $this->getService( 'RevisionRenderer' );
795  }
796 
801  public function getRevisionStore() {
802  return $this->getService( 'RevisionStore' );
803  }
804 
809  public function getRevisionStoreFactory() {
810  return $this->getService( 'RevisionStoreFactory' );
811  }
812 
817  public function newSearchEngine() {
818  // New engine object every time, since they keep state
819  return $this->getService( 'SearchEngineFactory' )->create();
820  }
821 
826  public function getSearchEngineConfig() {
827  return $this->getService( 'SearchEngineConfig' );
828  }
829 
834  public function getSearchEngineFactory() {
835  return $this->getService( 'SearchEngineFactory' );
836  }
837 
842  public function getShellCommandFactory() {
843  return $this->getService( 'ShellCommandFactory' );
844  }
845 
850  public function getSiteLookup() {
851  return $this->getService( 'SiteLookup' );
852  }
853 
858  public function getSiteStore() {
859  return $this->getService( 'SiteStore' );
860  }
861 
866  public function getSkinFactory() {
867  return $this->getService( 'SkinFactory' );
868  }
869 
874  public function getSlotRoleRegistry() {
875  return $this->getService( 'SlotRoleRegistry' );
876  }
877 
882  public function getSlotRoleStore() {
883  return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
884  }
885 
891  return $this->getService( 'SpecialPageFactory' );
892  }
893 
898  public function getStatsdDataFactory() {
899  return $this->getService( 'StatsdDataFactory' );
900  }
901 
906  public function getTitleFormatter() {
907  return $this->getService( 'TitleFormatter' );
908  }
909 
914  public function getTitleParser() {
915  return $this->getService( 'TitleParser' );
916  }
917 
922  public function getUploadRevisionImporter() {
923  return $this->getService( 'UploadRevisionImporter' );
924  }
925 
930  public function getVirtualRESTServiceClient() {
931  return $this->getService( 'VirtualRESTServiceClient' );
932  }
933 
938  public function getWatchedItemQueryService() {
939  return $this->getService( 'WatchedItemQueryService' );
940  }
941 
946  public function getWatchedItemStore() {
947  return $this->getService( 'WatchedItemStore' );
948  }
949 
955  return $this->getService( 'OldRevisionImporter' );
956  }
957 
963  return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
964  }
965 
970  public function getWikiRevisionUploadImporter() {
971  return $this->getService( 'UploadRevisionImporter' );
972  }
973 
974 }
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)
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: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.