MediaWiki  master
MediaWikiServices.php
Go to the documentation of this file.
1 <?php
2 namespace MediaWiki;
3 
6 use Config;
13 use Hooks;
45 use Parser;
63 
100 class MediaWikiServices extends ServiceContainer {
101 
105  private static $instance = null;
106 
121  public static function getInstance() {
122  if ( self::$instance === null ) {
123  // NOTE: constructing GlobalVarConfig here is not particularly pretty,
124  // but some information from the global scope has to be injected here,
125  // even if it's just a file name or database credentials to load
126  // configuration from.
127  $bootstrapConfig = new GlobalVarConfig();
128  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
129  }
130 
131  return self::$instance;
132  }
133 
147  public static function forceGlobalInstance( MediaWikiServices $services ) {
148  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
149  throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
150  }
151 
152  $old = self::getInstance();
153  self::$instance = $services;
154 
155  return $old;
156  }
157 
197  public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
198  if ( self::$instance === null ) {
199  // no global instance yet, nothing to reset
200  return;
201  }
202 
203  self::failIfResetNotAllowed( __METHOD__ );
204 
205  if ( $bootstrapConfig === null ) {
206  $bootstrapConfig = self::$instance->getBootstrapConfig();
207  }
208 
209  $oldInstance = self::$instance;
210 
211  self::$instance = self::newInstance( $bootstrapConfig, 'load' );
212  self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
213 
214  if ( $quick === 'quick' ) {
215  self::$instance->salvage( $oldInstance );
216  } else {
217  $oldInstance->destroy();
218  }
219  }
220 
228  private function salvage( self $other ) {
229  foreach ( $this->getServiceNames() as $name ) {
230  // The service could be new in the new instance and not registered in the
231  // other instance (e.g. an extension that was loaded after the instantiation of
232  // the other instance. Skip this service in this case. See T143974
233  try {
234  $oldService = $other->peekService( $name );
235  } catch ( NoSuchServiceException $e ) {
236  continue;
237  }
238 
239  if ( $oldService instanceof SalvageableService ) {
241  $newService = $this->getService( $name );
242  $newService->salvage( $oldService );
243  }
244  }
245 
246  $other->destroy();
247  }
248 
264  private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
265  $instance = new self( $bootstrapConfig );
266 
267  // Load the default wiring from the specified files.
268  if ( $loadWiring === 'load' ) {
269  $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
270  $instance->loadWiringFiles( $wiringFiles );
271  }
272 
273  // Provide a traditional hook point to allow extensions to configure services.
274  Hooks::run( 'MediaWikiServices', [ $instance ] );
275 
276  return $instance;
277  }
278 
294  public static function disableStorageBackend() {
295  // TODO: also disable some Caches, JobQueues, etc
296  $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
297  $services = self::getInstance();
298 
299  foreach ( $destroy as $name ) {
300  $services->disableService( $name );
301  }
302 
304  }
305 
318  public static function resetChildProcessServices() {
319  // NOTE: for now, just reset everything. Since we don't know the interdependencies
320  // between services, we can't do this more selectively at this time.
321  self::resetGlobalInstance();
322 
323  // Child, reseed because there is no bug in PHP:
324  // https://bugs.php.net/bug.php?id=42465
325  mt_srand( getmypid() );
326  }
327 
349  public function resetServiceForTesting( $name, $destroy = true ) {
350  if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
351  throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
352  }
353 
354  $this->resetService( $name, $destroy );
355  }
356 
384  public static function failIfResetNotAllowed( $method ) {
385  if ( !defined( 'MW_PHPUNIT_TEST' )
386  && !defined( 'MW_PARSER_TEST' )
387  && !defined( 'MEDIAWIKI_INSTALL' )
388  && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
389  && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
390  ) {
391  throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
392  }
393  }
394 
400  public function __construct( Config $config ) {
401  parent::__construct();
402 
403  // Register the given Config object as the bootstrap config service.
404  $this->defineService( 'BootstrapConfig', function () use ( $config ) {
405  return $config;
406  } );
407  }
408 
409  // CONVENIENCE GETTERS ////////////////////////////////////////////////////
410 
415  public function getActorMigration() {
416  return $this->getService( 'ActorMigration' );
417  }
418 
423  public function getBlobStore() {
424  return $this->getService( '_SqlBlobStore' );
425  }
426 
431  public function getBlobStoreFactory() {
432  return $this->getService( 'BlobStoreFactory' );
433  }
434 
448  public function getBootstrapConfig() {
449  return $this->getService( 'BootstrapConfig' );
450  }
451 
456  public function getChangeTagDefStore() {
457  return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
458  }
459 
464  public function getCommentStore() {
465  return $this->getService( 'CommentStore' );
466  }
467 
472  public function getConfigFactory() {
473  return $this->getService( 'ConfigFactory' );
474  }
475 
480  public function getConfigRepository() {
481  return $this->getService( 'ConfigRepository' );
482  }
483 
488  public function getConfiguredReadOnlyMode() {
489  return $this->getService( 'ConfiguredReadOnlyMode' );
490  }
491 
496  public function getContentLanguage() {
497  return $this->getService( 'ContentLanguage' );
498  }
499 
504  public function getContentModelStore() {
505  return $this->getService( 'NameTableStoreFactory' )->getContentModels();
506  }
507 
512  public function getCryptHKDF() {
513  return $this->getService( 'CryptHKDF' );
514  }
515 
521  public function getCryptRand() {
522  wfDeprecated( __METHOD__, '1.32' );
523  return $this->getService( 'CryptRand' );
524  }
525 
530  public function getDBLoadBalancer() {
531  return $this->getService( 'DBLoadBalancer' );
532  }
533 
538  public function getDBLoadBalancerFactory() {
539  return $this->getService( 'DBLoadBalancerFactory' );
540  }
541 
546  public function getEventRelayerGroup() {
547  return $this->getService( 'EventRelayerGroup' );
548  }
549 
554  public function getExternalStoreFactory() {
555  return $this->getService( 'ExternalStoreFactory' );
556  }
557 
562  public function getGenderCache() {
563  return $this->getService( 'GenderCache' );
564  }
565 
570  public function getHttpRequestFactory() {
571  return $this->getService( 'HttpRequestFactory' );
572  }
573 
578  public function getInterwikiLookup() {
579  return $this->getService( 'InterwikiLookup' );
580  }
581 
586  public function getLinkCache() {
587  return $this->getService( 'LinkCache' );
588  }
589 
597  public function getLinkRenderer() {
598  return $this->getService( 'LinkRenderer' );
599  }
600 
605  public function getLinkRendererFactory() {
606  return $this->getService( 'LinkRendererFactory' );
607  }
608 
613  public function getLocalServerObjectCache() {
614  return $this->getService( 'LocalServerObjectCache' );
615  }
616 
621  public function getMagicWordFactory() {
622  return $this->getService( 'MagicWordFactory' );
623  }
624 
632  public function getMainConfig() {
633  return $this->getService( 'MainConfig' );
634  }
635 
640  public function getMainObjectStash() {
641  return $this->getService( 'MainObjectStash' );
642  }
643 
648  public function getMainWANObjectCache() {
649  return $this->getService( 'MainWANObjectCache' );
650  }
651 
656  public function getMediaHandlerFactory() {
657  return $this->getService( 'MediaHandlerFactory' );
658  }
659 
664  public function getMimeAnalyzer() {
665  return $this->getService( 'MimeAnalyzer' );
666  }
667 
672  public function getNameTableStoreFactory() {
673  return $this->getService( 'NameTableStoreFactory' );
674  }
675 
679  public function getOldRevisionImporter() {
680  return $this->getService( 'OldRevisionImporter' );
681  }
682 
687  public function getParser() {
688  return $this->getService( 'Parser' );
689  }
690 
695  public function getParserCache() {
696  return $this->getService( 'ParserCache' );
697  }
698 
703  public function getParserFactory() {
704  return $this->getService( 'ParserFactory' );
705  }
706 
711  public function getPasswordFactory() {
712  return $this->getService( 'PasswordFactory' );
713  }
714 
719  public function getPerDbNameStatsdDataFactory() {
720  return $this->getService( 'PerDbNameStatsdDataFactory' );
721  }
722 
727  public function getPreferencesFactory() {
728  return $this->getService( 'PreferencesFactory' );
729  }
730 
735  public function getProxyLookup() {
736  return $this->getService( 'ProxyLookup' );
737  }
738 
743  public function getReadOnlyMode() {
744  return $this->getService( 'ReadOnlyMode' );
745  }
746 
751  public function getRevisionFactory() {
752  return $this->getService( 'RevisionFactory' );
753  }
754 
759  public function getRevisionLookup() {
760  return $this->getService( 'RevisionLookup' );
761  }
762 
767  public function getRevisionRenderer() {
768  return $this->getService( 'RevisionRenderer' );
769  }
770 
775  public function getRevisionStore() {
776  return $this->getService( 'RevisionStore' );
777  }
778 
783  public function getRevisionStoreFactory() {
784  return $this->getService( 'RevisionStoreFactory' );
785  }
786 
791  public function newSearchEngine() {
792  // New engine object every time, since they keep state
793  return $this->getService( 'SearchEngineFactory' )->create();
794  }
795 
800  public function getSearchEngineConfig() {
801  return $this->getService( 'SearchEngineConfig' );
802  }
803 
808  public function getSearchEngineFactory() {
809  return $this->getService( 'SearchEngineFactory' );
810  }
811 
816  public function getShellCommandFactory() {
817  return $this->getService( 'ShellCommandFactory' );
818  }
819 
824  public function getSiteLookup() {
825  return $this->getService( 'SiteLookup' );
826  }
827 
832  public function getSiteStore() {
833  return $this->getService( 'SiteStore' );
834  }
835 
840  public function getSkinFactory() {
841  return $this->getService( 'SkinFactory' );
842  }
843 
848  public function getSlotRoleRegistry() {
849  return $this->getService( 'SlotRoleRegistry' );
850  }
851 
856  public function getSlotRoleStore() {
857  return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
858  }
859 
865  return $this->getService( 'SpecialPageFactory' );
866  }
867 
872  public function getStatsdDataFactory() {
873  return $this->getService( 'StatsdDataFactory' );
874  }
875 
880  public function getTitleFormatter() {
881  return $this->getService( 'TitleFormatter' );
882  }
883 
888  public function getTitleParser() {
889  return $this->getService( 'TitleParser' );
890  }
891 
896  public function getUploadRevisionImporter() {
897  return $this->getService( 'UploadRevisionImporter' );
898  }
899 
904  public function getVirtualRESTServiceClient() {
905  return $this->getService( 'VirtualRESTServiceClient' );
906  }
907 
912  public function getWatchedItemQueryService() {
913  return $this->getService( 'WatchedItemQueryService' );
914  }
915 
920  public function getWatchedItemStore() {
921  return $this->getService( 'WatchedItemStore' );
922  }
923 
929  return $this->getService( 'OldRevisionImporter' );
930  }
931 
937  return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
938  }
939 
944  public function getWikiRevisionUploadImporter() {
945  return $this->getService( 'UploadRevisionImporter' );
946  }
947 
948 }
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:2173
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:2221
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 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:276
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.