MediaWiki  master
MediaWikiServices.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki;
4 
6 use CommentStore;
7 use Config;
8 use ConfigFactory;
9 use CryptHKDF;
12 use GenderCache;
13 use GlobalVarConfig;
14 use Hooks;
24 use PasswordReset;
27 use TitleFactory;
47 use LinkCache;
52 use MWException;
53 use MessageCache;
54 use MimeAnalyzer;
55 use NamespaceInfo;
56 use ObjectCache;
57 use Parser;
58 use ParserCache;
59 use ParserFactory;
60 use PasswordFactory;
61 use ProxyLookup;
62 use RepoGroup;
63 use ResourceLoader;
64 use SearchEngine;
67 use SiteLookup;
68 use SiteStore;
71 use SkinFactory;
72 use TitleFormatter;
73 use TitleParser;
83 
120 class MediaWikiServices extends ServiceContainer {
121 
125  private static $instance = null;
126 
141  public static function getInstance() {
142  if ( self::$instance === null ) {
143  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
144  // but some information from the global scope has to be injected here,
145  // even if it's just a file name or database credentials to load
146  // configuration from.
147  $bootstrapConfig = new GlobalVarConfig();
148  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
149  }
150 
151  return self::$instance;
152  }
153 
167  public static function forceGlobalInstance( MediaWikiServices $services ) {
168  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
169  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
170  }
171 
172  $old = self::getInstance();
173  self::$instance = $services;
174 
175  return $old;
176  }
177 
217  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
218  if ( self::$instance === null ) {
219  // no global instance yet, nothing to reset
220  return;
221  }
222 
223  self::failIfResetNotAllowed( __METHOD__ );
224 
225  if ( $bootstrapConfig === null ) {
226  $bootstrapConfig = self::$instance->getBootstrapConfig();
227  }
228 
229  $oldInstance = self::$instance;
230 
231  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
232  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
233 
234  if ( $quick === 'quick' ) {
235  self::$instance->salvage( $oldInstance );
236  } else {
237  $oldInstance->destroy();
238  }
239  }
240 
250  private function salvage( self $other ) {
251  foreach ( $this->getServiceNames() as $name ) {
252  // The service could be new in the new instance and not registered in the
253  // other instance (e.g. an extension that was loaded after the instantiation of
254  // the other instance. Skip this service in this case. See T143974
255  try {
256  $oldService = $other->peekService( $name );
257  } catch ( NoSuchServiceException $e ) {
258  continue;
259  }
260 
261  if ( $oldService instanceof SalvageableService ) {
263  $newService = $this->getService( $name );
264  $newService->salvage( $oldService );
265  }
266  }
267 
268  $other->destroy();
269  }
270 
286  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
287  $instance = new self( $bootstrapConfig );
288 
289  // Load the default wiring from the specified files.
290  if ( $loadWiring === 'load' ) {
291  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
292  $instance->loadWiringFiles( $wiringFiles );
293  }
294 
295  // Provide a traditional hook point to allow extensions to configure services.
296  Hooks::run( 'MediaWikiServices', [ $instance ] );
297 
298  return $instance;
299  }
300 
316  public static function disableStorageBackend() {
317  // TODO: also disable some Caches, JobQueues, etc
318  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
319  $services = self::getInstance();
320 
321  foreach ( $destroy as $name ) {
322  $services->disableService( $name );
323  }
324 
326  }
327 
340  public static function resetChildProcessServices() {
341  // NOTE: for now, just reset everything. Since we don't know the interdependencies
342  // between services, we can't do this more selectively at this time.
343  self::resetGlobalInstance();
344 
345  // Child, reseed because there is no bug in PHP:
346  // https://bugs.php.net/bug.php?id=42465
347  mt_srand( getmypid() );
348  }
349 
371  public function resetServiceForTesting( $name, $destroy = true ) {
372  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
373  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
374  }
375 
376  $this->resetService( $name, $destroy );
377  }
378 
406  public static function failIfResetNotAllowed( $method ) {
407  if ( !defined( 'MW_PHPUNIT_TEST' )
408  && !defined( 'MW_PARSER_TEST' )
409  && !defined( 'MEDIAWIKI_INSTALL' )
410  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
411  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
412  ) {
413  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
414  }
415  }
416 
422  public function __construct( Config $config ) {
423  parent::__construct();
424 
425  // Register the given Config object as the bootstrap config service.
426  $this->defineService( 'BootstrapConfig', function () use ( $config ) {
427  return $config;
428  } );
429  }
430 
431  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
432 
437  public function getActorMigration() {
438  return $this->getService( 'ActorMigration' );
439  }
440 
445  public function getBadFileLookup() : BadFileLookup {
446  return $this->getService( 'BadFileLookup' );
447  }
448 
453  public function getBlobStore() {
454  return $this->getService( '_SqlBlobStore' );
455  }
456 
461  public function getBlobStoreFactory() {
462  return $this->getService( 'BlobStoreFactory' );
463  }
464 
469  public function getBlockErrorFormatter() : BlockErrorFormatter {
470  return $this->getService( 'BlockErrorFormatter' );
471  }
472 
477  public function getBlockManager() : BlockManager {
478  return $this->getService( 'BlockManager' );
479  }
480 
485  public function getBlockRestrictionStore() : BlockRestrictionStore {
486  return $this->getService( 'BlockRestrictionStore' );
487  }
488 
502  public function getBootstrapConfig() {
503  return $this->getService( 'BootstrapConfig' );
504  }
505 
510  public function getChangeTagDefStore() {
511  return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
512  }
513 
518  public function getCommentStore() {
519  return $this->getService( 'CommentStore' );
520  }
521 
526  public function getConfigFactory() {
527  return $this->getService( 'ConfigFactory' );
528  }
529 
534  public function getConfigRepository() {
535  return $this->getService( 'ConfigRepository' );
536  }
537 
542  public function getConfiguredReadOnlyMode() {
543  return $this->getService( 'ConfiguredReadOnlyMode' );
544  }
545 
550  public function getContentLanguage() {
551  return $this->getService( 'ContentLanguage' );
552  }
553 
558  public function getContentModelStore() {
559  return $this->getService( 'NameTableStoreFactory' )->getContentModels();
560  }
561 
566  public function getCryptHKDF() {
567  return $this->getService( 'CryptHKDF' );
568  }
569 
574  public function getDateFormatterFactory() {
575  return $this->getService( 'DateFormatterFactory' );
576  }
577 
582  public function getDBLoadBalancer() {
583  return $this->getService( 'DBLoadBalancer' );
584  }
585 
590  public function getDBLoadBalancerFactory() {
591  return $this->getService( 'DBLoadBalancerFactory' );
592  }
593 
598  public function getEventRelayerGroup() {
599  return $this->getService( 'EventRelayerGroup' );
600  }
601 
606  public function getExternalStoreAccess() {
607  return $this->getService( 'ExternalStoreAccess' );
608  }
609 
614  public function getExternalStoreFactory() {
615  return $this->getService( 'ExternalStoreFactory' );
616  }
617 
622  public function getGenderCache() {
623  return $this->getService( 'GenderCache' );
624  }
625 
630  public function getHttpRequestFactory() {
631  return $this->getService( 'HttpRequestFactory' );
632  }
633 
638  public function getInterwikiLookup() {
639  return $this->getService( 'InterwikiLookup' );
640  }
641 
646  public function getLanguageFallback() : LanguageFallback {
647  return $this->getService( 'LanguageFallback' );
648  }
649 
654  public function getLanguageNameUtils() {
655  return $this->getService( 'LanguageNameUtils' );
656  }
657 
662  public function getLinkCache() {
663  return $this->getService( 'LinkCache' );
664  }
665 
673  public function getLinkRenderer() {
674  return $this->getService( 'LinkRenderer' );
675  }
676 
681  public function getLinkRendererFactory() {
682  return $this->getService( 'LinkRendererFactory' );
683  }
684 
690  return $this->getService( 'LocalisationCache' );
691  }
692 
697  public function getLocalServerObjectCache() {
698  return $this->getService( 'LocalServerObjectCache' );
699  }
700 
705  public function getLockManagerGroupFactory() : LockManagerGroupFactory {
706  return $this->getService( 'LockManagerGroupFactory' );
707  }
708 
713  public function getMagicWordFactory() {
714  return $this->getService( 'MagicWordFactory' );
715  }
716 
724  public function getMainConfig() {
725  return $this->getService( 'MainConfig' );
726  }
727 
732  public function getMainObjectStash() {
733  return $this->getService( 'MainObjectStash' );
734  }
735 
740  public function getMainWANObjectCache() {
741  return $this->getService( 'MainWANObjectCache' );
742  }
743 
748  public function getMediaHandlerFactory() {
749  return $this->getService( 'MediaHandlerFactory' );
750  }
751 
756  public function getMessageCache() : MessageCache {
757  return $this->getService( 'MessageCache' );
758  }
759 
764  public function getMessageFormatterFactory() {
765  return $this->getService( 'MessageFormatterFactory' );
766  }
767 
772  public function getMimeAnalyzer() {
773  return $this->getService( 'MimeAnalyzer' );
774  }
775 
780  public function getMovePageFactory() : MovePageFactory {
781  return $this->getService( 'MovePageFactory' );
782  }
783 
788  public function getNamespaceInfo() : NamespaceInfo {
789  return $this->getService( 'NamespaceInfo' );
790  }
791 
796  public function getNameTableStoreFactory() {
797  return $this->getService( 'NameTableStoreFactory' );
798  }
799 
807  public function getObjectFactory() {
808  return $this->getService( 'ObjectFactory' );
809  }
810 
815  public function getOldRevisionImporter() {
816  return $this->getService( 'OldRevisionImporter' );
817  }
818 
823  public function getPageEditStash() {
824  return $this->getService( 'PageEditStash' );
825  }
826 
831  public function getParser() {
832  return $this->getService( 'Parser' );
833  }
834 
839  public function getParserCache() {
840  return $this->getService( 'ParserCache' );
841  }
842 
847  public function getParserFactory() {
848  return $this->getService( 'ParserFactory' );
849  }
850 
855  public function getPasswordFactory() {
856  return $this->getService( 'PasswordFactory' );
857  }
858 
863  public function getPasswordReset() : PasswordReset {
864  return $this->getService( 'PasswordReset' );
865  }
866 
871  public function getPerDbNameStatsdDataFactory() {
872  return $this->getService( 'PerDbNameStatsdDataFactory' );
873  }
874 
879  public function getPermissionManager() {
880  return $this->getService( 'PermissionManager' );
881  }
882 
887  public function getPreferencesFactory() {
888  return $this->getService( 'PreferencesFactory' );
889  }
890 
895  public function getProxyLookup() {
896  return $this->getService( 'ProxyLookup' );
897  }
898 
903  public function getReadOnlyMode() {
904  return $this->getService( 'ReadOnlyMode' );
905  }
906 
911  public function getRepoGroup() : RepoGroup {
912  return $this->getService( 'RepoGroup' );
913  }
914 
919  public function getResourceLoader() {
920  return $this->getService( 'ResourceLoader' );
921  }
922 
927  public function getRevisionFactory() {
928  return $this->getService( 'RevisionFactory' );
929  }
930 
935  public function getRevisionLookup() {
936  return $this->getService( 'RevisionLookup' );
937  }
938 
943  public function getRevisionRenderer() {
944  return $this->getService( 'RevisionRenderer' );
945  }
946 
951  public function getRevisionStore() {
952  return $this->getService( 'RevisionStore' );
953  }
954 
959  public function getRevisionStoreFactory() {
960  return $this->getService( 'RevisionStoreFactory' );
961  }
962 
967  public function newSearchEngine() {
968  // New engine object every time, since they keep state
969  return $this->getService( 'SearchEngineFactory' )->create();
970  }
971 
976  public function getSearchEngineConfig() {
977  return $this->getService( 'SearchEngineConfig' );
978  }
979 
984  public function getSearchEngineFactory() {
985  return $this->getService( 'SearchEngineFactory' );
986  }
987 
992  public function getShellCommandFactory() {
993  return $this->getService( 'ShellCommandFactory' );
994  }
995 
1000  public function getSiteLookup() {
1001  return $this->getService( 'SiteLookup' );
1002  }
1003 
1008  public function getSiteStore() {
1009  return $this->getService( 'SiteStore' );
1010  }
1011 
1016  public function getSkinFactory() {
1017  return $this->getService( 'SkinFactory' );
1018  }
1019 
1024  public function getSlotRoleRegistry() {
1025  return $this->getService( 'SlotRoleRegistry' );
1026  }
1027 
1032  public function getSlotRoleStore() {
1033  return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
1034  }
1035 
1041  return $this->getService( 'SpecialPageFactory' );
1042  }
1043 
1048  public function getStatsdDataFactory() {
1049  return $this->getService( 'StatsdDataFactory' );
1050  }
1051 
1056  public function getTempFSFileFactory() : TempFSFileFactory {
1057  return $this->getService( 'TempFSFileFactory' );
1058  }
1059 
1064  public function getTitleFactory() : TitleFactory {
1065  return $this->getService( 'TitleFactory' );
1066  }
1067 
1072  public function getTitleFormatter() {
1073  return $this->getService( 'TitleFormatter' );
1074  }
1075 
1080  public function getTitleParser() {
1081  return $this->getService( 'TitleParser' );
1082  }
1083 
1088  public function getUploadRevisionImporter() {
1089  return $this->getService( 'UploadRevisionImporter' );
1090  }
1091 
1096  public function getVirtualRESTServiceClient() {
1097  return $this->getService( 'VirtualRESTServiceClient' );
1098  }
1099 
1104  public function getWatchedItemQueryService() {
1105  return $this->getService( 'WatchedItemQueryService' );
1106  }
1107 
1112  public function getWatchedItemStore() {
1113  return $this->getService( 'WatchedItemStore' );
1114  }
1115 
1121  return $this->getService( 'OldRevisionImporter' );
1122  }
1123 
1129  return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
1130  }
1131 
1136  public function getWikiRevisionUploadImporter() {
1137  return $this->getService( 'UploadRevisionImporter' );
1138  }
1139 
1140 }
getLinkRenderer()
LinkRenderer instance that can be used if no custom options are needed.
getObjectFactory()
ObjectFactory is intended for instantiating "handlers" from declarative definitions, such as Action API modules, special pages, or REST API handlers.
salvage(self $other)
PhpDocSignatureInspection
static getInstance()
Returns the global default instance of the top level service locator.
A helper class for throttling authentication attempts.
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.
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 ...
resetServiceForTesting( $name, $destroy=true)
Resets the given service for testing purposes.
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.