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;
67 
104 class MediaWikiServices extends ServiceContainer {
105 
109  private static $instance = null;
110 
125  public static function getInstance() {
126  if ( self::$instance === null ) {
127  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
128  // but some information from the global scope has to be injected here,
129  // even if it's just a file name or database credentials to load
130  // configuration from.
131  $bootstrapConfig = new GlobalVarConfig();
132  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
133  }
134 
135  return self::$instance;
136  }
137 
151  public static function forceGlobalInstance( MediaWikiServices $services ) {
152  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
153  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
154  }
155 
156  $old = self::getInstance();
157  self::$instance = $services;
158 
159  return $old;
160  }
161 
201  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
202  if ( self::$instance === null ) {
203  // no global instance yet, nothing to reset
204  return;
205  }
206 
207  self::failIfResetNotAllowed( __METHOD__ );
208 
209  if ( $bootstrapConfig === null ) {
210  $bootstrapConfig = self::$instance->getBootstrapConfig();
211  }
212 
213  $oldInstance = self::$instance;
214 
215  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
216  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
217 
218  if ( $quick === 'quick' ) {
219  self::$instance->salvage( $oldInstance );
220  } else {
221  $oldInstance->destroy();
222  }
223  }
224 
232  private function salvage( self $other ) {
233  foreach ( $this->getServiceNames() as $name ) {
234  // The service could be new in the new instance and not registered in the
235  // other instance (e.g. an extension that was loaded after the instantiation of
236  // the other instance. Skip this service in this case. See T143974
237  try {
238  $oldService = $other->peekService( $name );
239  } catch ( NoSuchServiceException $e ) {
240  continue;
241  }
242 
243  if ( $oldService instanceof SalvageableService ) {
245  $newService = $this->getService( $name );
246  $newService->salvage( $oldService );
247  }
248  }
249 
250  $other->destroy();
251  }
252 
268  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
269  $instance = new self( $bootstrapConfig );
270 
271  // Load the default wiring from the specified files.
272  if ( $loadWiring === 'load' ) {
273  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
274  $instance->loadWiringFiles( $wiringFiles );
275  }
276 
277  // Provide a traditional hook point to allow extensions to configure services.
278  Hooks::run( 'MediaWikiServices', [ $instance ] );
279 
280  return $instance;
281  }
282 
298  public static function disableStorageBackend() {
299  // TODO: also disable some Caches, JobQueues, etc
300  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
301  $services = self::getInstance();
302 
303  foreach ( $destroy as $name ) {
304  $services->disableService( $name );
305  }
306 
308  }
309 
322  public static function resetChildProcessServices() {
323  // NOTE: for now, just reset everything. Since we don't know the interdependencies
324  // between services, we can't do this more selectively at this time.
325  self::resetGlobalInstance();
326 
327  // Child, reseed because there is no bug in PHP:
328  // https://bugs.php.net/bug.php?id=42465
329  mt_srand( getmypid() );
330  }
331 
353  public function resetServiceForTesting( $name, $destroy = true ) {
354  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
355  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
356  }
357 
358  $this->resetService( $name, $destroy );
359  }
360 
388  public static function failIfResetNotAllowed( $method ) {
389  if ( !defined( 'MW_PHPUNIT_TEST' )
390  && !defined( 'MW_PARSER_TEST' )
391  && !defined( 'MEDIAWIKI_INSTALL' )
392  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
393  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
394  ) {
395  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
396  }
397  }
398 
404  public function __construct( Config $config ) {
405  parent::__construct();
406 
407  // Register the given Config object as the bootstrap config service.
408  $this->defineService( 'BootstrapConfig', function () use ( $config ) {
409  return $config;
410  } );
411  }
412 
413  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
414 
419  public function getActorMigration() {
420  return $this->getService( 'ActorMigration' );
421  }
422 
427  public function getBlobStore() {
428  return $this->getService( '_SqlBlobStore' );
429  }
430 
435  public function getBlobStoreFactory() {
436  return $this->getService( 'BlobStoreFactory' );
437  }
438 
452  public function getBootstrapConfig() {
453  return $this->getService( 'BootstrapConfig' );
454  }
455 
460  public function getChangeTagDefStore() {
461  return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
462  }
463 
468  public function getCommentStore() {
469  return $this->getService( 'CommentStore' );
470  }
471 
476  public function getConfigFactory() {
477  return $this->getService( 'ConfigFactory' );
478  }
479 
484  public function getConfigRepository() {
485  return $this->getService( 'ConfigRepository' );
486  }
487 
492  public function getConfiguredReadOnlyMode() {
493  return $this->getService( 'ConfiguredReadOnlyMode' );
494  }
495 
500  public function getContentLanguage() {
501  return $this->getService( 'ContentLanguage' );
502  }
503 
508  public function getContentModelStore() {
509  return $this->getService( 'NameTableStoreFactory' )->getContentModels();
510  }
511 
516  public function getCryptHKDF() {
517  return $this->getService( 'CryptHKDF' );
518  }
519 
524  public function getDateFormatterFactory() {
525  return $this->getService( 'DateFormatterFactory' );
526  }
527 
532  public function getDBLoadBalancer() {
533  return $this->getService( 'DBLoadBalancer' );
534  }
535 
540  public function getDBLoadBalancerFactory() {
541  return $this->getService( 'DBLoadBalancerFactory' );
542  }
543 
548  public function getEventRelayerGroup() {
549  return $this->getService( 'EventRelayerGroup' );
550  }
551 
556  public function getExternalStoreFactory() {
557  return $this->getService( 'ExternalStoreFactory' );
558  }
559 
564  public function getGenderCache() {
565  return $this->getService( 'GenderCache' );
566  }
567 
572  public function getHttpRequestFactory() {
573  return $this->getService( 'HttpRequestFactory' );
574  }
575 
580  public function getInterwikiLookup() {
581  return $this->getService( 'InterwikiLookup' );
582  }
583 
588  public function getLinkCache() {
589  return $this->getService( 'LinkCache' );
590  }
591 
599  public function getLinkRenderer() {
600  return $this->getService( 'LinkRenderer' );
601  }
602 
607  public function getLinkRendererFactory() {
608  return $this->getService( 'LinkRendererFactory' );
609  }
610 
615  public function getLocalServerObjectCache() {
616  return $this->getService( 'LocalServerObjectCache' );
617  }
618 
623  public function getMagicWordFactory() {
624  return $this->getService( 'MagicWordFactory' );
625  }
626 
634  public function getMainConfig() {
635  return $this->getService( 'MainConfig' );
636  }
637 
642  public function getMainObjectStash() {
643  return $this->getService( 'MainObjectStash' );
644  }
645 
650  public function getMainWANObjectCache() {
651  return $this->getService( 'MainWANObjectCache' );
652  }
653 
658  public function getMediaHandlerFactory() {
659  return $this->getService( 'MediaHandlerFactory' );
660  }
661 
666  public function getMimeAnalyzer() {
667  return $this->getService( 'MimeAnalyzer' );
668  }
669 
674  public function getNamespaceInfo() : NamespaceInfo {
675  return $this->getService( 'NamespaceInfo' );
676  }
677 
682  public function getNameTableStoreFactory() {
683  return $this->getService( 'NameTableStoreFactory' );
684  }
685 
690  public function getOldRevisionImporter() {
691  return $this->getService( 'OldRevisionImporter' );
692  }
693 
698  public function getPageEditStash() {
699  return $this->getService( 'PageEditStash' );
700  }
701 
706  public function getParser() {
707  return $this->getService( 'Parser' );
708  }
709 
714  public function getParserCache() {
715  return $this->getService( 'ParserCache' );
716  }
717 
722  public function getParserFactory() {
723  return $this->getService( 'ParserFactory' );
724  }
725 
730  public function getPasswordFactory() {
731  return $this->getService( 'PasswordFactory' );
732  }
733 
738  public function getPerDbNameStatsdDataFactory() {
739  return $this->getService( 'PerDbNameStatsdDataFactory' );
740  }
741 
746  public function getPermissionManager() {
747  return $this->getService( 'PermissionManager' );
748  }
749 
754  public function getPreferencesFactory() {
755  return $this->getService( 'PreferencesFactory' );
756  }
757 
762  public function getProxyLookup() {
763  return $this->getService( 'ProxyLookup' );
764  }
765 
770  public function getReadOnlyMode() {
771  return $this->getService( 'ReadOnlyMode' );
772  }
773 
778  public function getResourceLoader() {
779  return $this->getService( 'ResourceLoader' );
780  }
781 
786  public function getRevisionFactory() {
787  return $this->getService( 'RevisionFactory' );
788  }
789 
794  public function getRevisionLookup() {
795  return $this->getService( 'RevisionLookup' );
796  }
797 
802  public function getRevisionRenderer() {
803  return $this->getService( 'RevisionRenderer' );
804  }
805 
810  public function getRevisionStore() {
811  return $this->getService( 'RevisionStore' );
812  }
813 
818  public function getRevisionStoreFactory() {
819  return $this->getService( 'RevisionStoreFactory' );
820  }
821 
826  public function newSearchEngine() {
827  // New engine object every time, since they keep state
828  return $this->getService( 'SearchEngineFactory' )->create();
829  }
830 
835  public function getSearchEngineConfig() {
836  return $this->getService( 'SearchEngineConfig' );
837  }
838 
843  public function getSearchEngineFactory() {
844  return $this->getService( 'SearchEngineFactory' );
845  }
846 
851  public function getShellCommandFactory() {
852  return $this->getService( 'ShellCommandFactory' );
853  }
854 
859  public function getSiteLookup() {
860  return $this->getService( 'SiteLookup' );
861  }
862 
867  public function getSiteStore() {
868  return $this->getService( 'SiteStore' );
869  }
870 
875  public function getSkinFactory() {
876  return $this->getService( 'SkinFactory' );
877  }
878 
883  public function getSlotRoleRegistry() {
884  return $this->getService( 'SlotRoleRegistry' );
885  }
886 
891  public function getSlotRoleStore() {
892  return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
893  }
894 
900  return $this->getService( 'SpecialPageFactory' );
901  }
902 
907  public function getStatsdDataFactory() {
908  return $this->getService( 'StatsdDataFactory' );
909  }
910 
915  public function getTitleFormatter() {
916  return $this->getService( 'TitleFormatter' );
917  }
918 
923  public function getTitleParser() {
924  return $this->getService( 'TitleParser' );
925  }
926 
931  public function getUploadRevisionImporter() {
932  return $this->getService( 'UploadRevisionImporter' );
933  }
934 
939  public function getVirtualRESTServiceClient() {
940  return $this->getService( 'VirtualRESTServiceClient' );
941  }
942 
947  public function getWatchedItemQueryService() {
948  return $this->getService( 'WatchedItemQueryService' );
949  }
950 
955  public function getWatchedItemStore() {
956  return $this->getService( 'WatchedItemStore' );
957  }
958 
964  return $this->getService( 'OldRevisionImporter' );
965  }
966 
972  return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
973  }
974 
979  public function getWikiRevisionUploadImporter() {
980  return $this->getService( 'UploadRevisionImporter' );
981  }
982 
983 }
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.