From: Aryeh Gregor Date: Fri, 3 Aug 2018 08:05:44 +0000 (+0300) Subject: Alphabetize service lists X-Git-Tag: 1.34.0-rc.0~4504^2 X-Git-Url: http://git.cyclocoop.org/%7B%24admin_url%7Dmes_infos.php?a=commitdiff_plain;h=3c45e203a8bf74199bbf566eead9e71e2aa57c70;p=lhc%2Fweb%2Fwiklou.git Alphabetize service lists Adding everything at the end makes the list arbitrarily ordered, and also invites lots of merge conflicts as new things are added. Change-Id: I58bcca4fa79140f5d5f2f6ef447e67035cc37aae --- diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php index fd9b472f96..080a7f94b0 100644 --- a/includes/MediaWikiServices.php +++ b/includes/MediaWikiServices.php @@ -403,128 +403,117 @@ class MediaWikiServices extends ServiceContainer { // CONVENIENCE GETTERS //////////////////////////////////////////////////// /** - * Returns the Config object containing the bootstrap configuration. - * Bootstrap configuration would typically include database credentials - * and other information that may be needed before the ConfigFactory - * service can be instantiated. - * - * @note This should only be used during bootstrapping, in particular - * when creating the MainConfig service. Application logic should - * use getMainConfig() to get a Config instances. - * - * @since 1.27 - * @return Config + * @since 1.31 + * @return ActorMigration */ - public function getBootstrapConfig() { - return $this->getService( 'BootstrapConfig' ); + public function getActorMigration() { + return $this->getService( 'ActorMigration' ); } /** - * @since 1.27 - * @return ConfigFactory + * @since 1.31 + * @return BlobStore */ - public function getConfigFactory() { - return $this->getService( 'ConfigFactory' ); + public function getBlobStore() { + return $this->getService( '_SqlBlobStore' ); } /** - * Returns the Config object that provides configuration for MediaWiki core. - * This may or may not be the same object that is returned by getBootstrapConfig(). - * - * @since 1.27 - * @return Config + * @since 1.31 + * @return BlobStoreFactory */ - public function getMainConfig() { - return $this->getService( 'MainConfig' ); + public function getBlobStoreFactory() { + return $this->getService( 'BlobStoreFactory' ); } /** + * Returns the Config object containing the bootstrap configuration. + * Bootstrap configuration would typically include database credentials + * and other information that may be needed before the ConfigFactory + * service can be instantiated. + * + * @note This should only be used during bootstrapping, in particular + * when creating the MainConfig service. Application logic should + * use getMainConfig() to get a Config instances. + * * @since 1.27 - * @return SiteLookup + * @return Config */ - public function getSiteLookup() { - return $this->getService( 'SiteLookup' ); + public function getBootstrapConfig() { + return $this->getService( 'BootstrapConfig' ); } /** - * @since 1.27 - * @return SiteStore + * @since 1.32 + * @return NameTableStore */ - public function getSiteStore() { - return $this->getService( 'SiteStore' ); + public function getChangeTagDefStore() { + return $this->getService( 'ChangeTagDefStore' ); } /** - * @since 1.28 - * @return InterwikiLookup + * @since 1.31 + * @return CommentStore */ - public function getInterwikiLookup() { - return $this->getService( 'InterwikiLookup' ); + public function getCommentStore() { + return $this->getService( 'CommentStore' ); } /** * @since 1.27 - * @return IBufferingStatsdDataFactory + * @return ConfigFactory */ - public function getStatsdDataFactory() { - return $this->getService( 'StatsdDataFactory' ); + public function getConfigFactory() { + return $this->getService( 'ConfigFactory' ); } /** * @since 1.32 - * @return IBufferingStatsdDataFactory - */ - public function getPerDbNameStatsdDataFactory() { - return $this->getService( 'PerDbNameStatsdDataFactory' ); - } - - /** - * @since 1.27 - * @return EventRelayerGroup + * @return ConfigRepository */ - public function getEventRelayerGroup() { - return $this->getService( 'EventRelayerGroup' ); + public function getConfigRepository() { + return $this->getService( 'ConfigRepository' ); } /** - * @since 1.27 - * @return SearchEngine + * @since 1.29 + * @return \ConfiguredReadOnlyMode */ - public function newSearchEngine() { - // New engine object every time, since they keep state - return $this->getService( 'SearchEngineFactory' )->create(); + public function getConfiguredReadOnlyMode() { + return $this->getService( 'ConfiguredReadOnlyMode' ); } /** - * @since 1.27 - * @return SearchEngineFactory + * @since 1.32 + * @return \Language */ - public function getSearchEngineFactory() { - return $this->getService( 'SearchEngineFactory' ); + public function getContentLanguage() { + return $this->getService( 'ContentLanguage' ); } /** - * @since 1.27 - * @return SearchEngineConfig + * @since 1.31 + * @return NameTableStore */ - public function getSearchEngineConfig() { - return $this->getService( 'SearchEngineConfig' ); + public function getContentModelStore() { + return $this->getService( 'ContentModelStore' ); } /** - * @since 1.27 - * @return SkinFactory + * @since 1.28 + * @return CryptHKDF */ - public function getSkinFactory() { - return $this->getService( 'SkinFactory' ); + public function getCryptHKDF() { + return $this->getService( 'CryptHKDF' ); } /** * @since 1.28 - * @return LBFactory + * @deprecated since 1.32, use random_bytes()/random_int() + * @return CryptRand */ - public function getDBLoadBalancerFactory() { - return $this->getService( 'DBLoadBalancerFactory' ); + public function getCryptRand() { + return $this->getService( 'CryptRand' ); } /** @@ -537,91 +526,69 @@ class MediaWikiServices extends ServiceContainer { /** * @since 1.28 - * @return WatchedItemStoreInterface - */ - public function getWatchedItemStore() { - return $this->getService( 'WatchedItemStore' ); - } - - /** - * @since 1.28 - * @return WatchedItemQueryService + * @return LBFactory */ - public function getWatchedItemQueryService() { - return $this->getService( 'WatchedItemQueryService' ); + public function getDBLoadBalancerFactory() { + return $this->getService( 'DBLoadBalancerFactory' ); } /** - * @since 1.28 - * @deprecated since 1.32, use random_bytes()/random_int() - * @return CryptRand + * @since 1.27 + * @return EventRelayerGroup */ - public function getCryptRand() { - return $this->getService( 'CryptRand' ); + public function getEventRelayerGroup() { + return $this->getService( 'EventRelayerGroup' ); } /** - * @since 1.28 - * @return CryptHKDF + * @since 1.31 + * @return \ExternalStoreFactory */ - public function getCryptHKDF() { - return $this->getService( 'CryptHKDF' ); + public function getExternalStoreFactory() { + return $this->getService( 'ExternalStoreFactory' ); } /** * @since 1.28 - * @return MediaHandlerFactory + * @return GenderCache */ - public function getMediaHandlerFactory() { - return $this->getService( 'MediaHandlerFactory' ); + public function getGenderCache() { + return $this->getService( 'GenderCache' ); } /** - * @since 1.28 - * @return MimeAnalyzer + * @since 1.31 + * @return HttpRequestFactory */ - public function getMimeAnalyzer() { - return $this->getService( 'MimeAnalyzer' ); + public function getHttpRequestFactory() { + return $this->getService( 'HttpRequestFactory' ); } /** * @since 1.28 - * @return ProxyLookup - */ - public function getProxyLookup() { - return $this->getService( 'ProxyLookup' ); - } - - /** - * @since 1.29 - * @return Parser - */ - public function getParser() { - return $this->getService( 'Parser' ); - } - - /** - * @since 1.30 - * @return ParserCache + * @return InterwikiLookup */ - public function getParserCache() { - return $this->getService( 'ParserCache' ); + public function getInterwikiLookup() { + return $this->getService( 'InterwikiLookup' ); } /** * @since 1.28 - * @return GenderCache + * @return LinkCache */ - public function getGenderCache() { - return $this->getService( 'GenderCache' ); + public function getLinkCache() { + return $this->getService( 'LinkCache' ); } /** + * LinkRenderer instance that can be used + * if no custom options are needed + * * @since 1.28 - * @return LinkCache + * @return LinkRenderer */ - public function getLinkCache() { - return $this->getService( 'LinkCache' ); + public function getLinkRenderer() { + return $this->getService( 'LinkRenderer' ); } /** @@ -633,30 +600,30 @@ class MediaWikiServices extends ServiceContainer { } /** - * LinkRenderer instance that can be used - * if no custom options are needed - * * @since 1.28 - * @return LinkRenderer + * @return \BagOStuff */ - public function getLinkRenderer() { - return $this->getService( 'LinkRenderer' ); + public function getLocalServerObjectCache() { + return $this->getService( 'LocalServerObjectCache' ); } /** - * @since 1.28 - * @return TitleFormatter + * @since 1.32 + * @return MagicWordFactory */ - public function getTitleFormatter() { - return $this->getService( 'TitleFormatter' ); + public function getMagicWordFactory() { + return $this->getService( 'MagicWordFactory' ); } /** - * @since 1.28 - * @return TitleParser + * Returns the Config object that provides configuration for MediaWiki core. + * This may or may not be the same object that is returned by getBootstrapConfig(). + * + * @since 1.27 + * @return Config */ - public function getTitleParser() { - return $this->getService( 'TitleParser' ); + public function getMainConfig() { + return $this->getService( 'MainConfig' ); } /** @@ -677,90 +644,98 @@ class MediaWikiServices extends ServiceContainer { /** * @since 1.28 - * @return \BagOStuff + * @return MediaHandlerFactory */ - public function getLocalServerObjectCache() { - return $this->getService( 'LocalServerObjectCache' ); + public function getMediaHandlerFactory() { + return $this->getService( 'MediaHandlerFactory' ); } /** * @since 1.28 - * @return VirtualRESTServiceClient + * @return MimeAnalyzer */ - public function getVirtualRESTServiceClient() { - return $this->getService( 'VirtualRESTServiceClient' ); + public function getMimeAnalyzer() { + return $this->getService( 'MimeAnalyzer' ); } /** - * @since 1.29 - * @return \ConfiguredReadOnlyMode + * @since 1.32 + * @return OldRevisionImporter */ - public function getConfiguredReadOnlyMode() { - return $this->getService( 'ConfiguredReadOnlyMode' ); + public function getOldRevisionImporter() { + return $this->getService( 'OldRevisionImporter' ); } /** * @since 1.29 - * @return \ReadOnlyMode + * @return Parser */ - public function getReadOnlyMode() { - return $this->getService( 'ReadOnlyMode' ); + public function getParser() { + return $this->getService( 'Parser' ); } /** - * @since 1.31 - * @return \UploadRevisionImporter + * @since 1.30 + * @return ParserCache */ - public function getWikiRevisionUploadImporter() { - return $this->getService( 'UploadRevisionImporter' ); + public function getParserCache() { + return $this->getService( 'ParserCache' ); } /** - * @since 1.31 - * @return \OldRevisionImporter + * @since 1.32 + * @return PasswordFactory */ - public function getWikiRevisionOldRevisionImporter() { - return $this->getService( 'OldRevisionImporter' ); + public function getPasswordFactory() { + return $this->getService( 'PasswordFactory' ); + } + + /** + * @since 1.32 + * @return IBufferingStatsdDataFactory + */ + public function getPerDbNameStatsdDataFactory() { + return $this->getService( 'PerDbNameStatsdDataFactory' ); } /** * @since 1.31 - * @return \OldRevisionImporter + * @return PreferencesFactory */ - public function getWikiRevisionOldRevisionImporterNoUpdates() { - return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' ); + public function getPreferencesFactory() { + return $this->getService( 'PreferencesFactory' ); } /** - * @since 1.30 - * @return CommandFactory + * @since 1.28 + * @return ProxyLookup */ - public function getShellCommandFactory() { - return $this->getService( 'ShellCommandFactory' ); + public function getProxyLookup() { + return $this->getService( 'ProxyLookup' ); } /** - * @since 1.31 - * @return \ExternalStoreFactory + * @since 1.29 + * @return \ReadOnlyMode */ - public function getExternalStoreFactory() { - return $this->getService( 'ExternalStoreFactory' ); + public function getReadOnlyMode() { + return $this->getService( 'ReadOnlyMode' ); } /** * @since 1.31 - * @return BlobStoreFactory + * @return RevisionFactory */ - public function getBlobStoreFactory() { - return $this->getService( 'BlobStoreFactory' ); + public function getRevisionFactory() { + return $this->getService( 'RevisionFactory' ); } /** * @since 1.31 - * @return BlobStore + * @return RevisionLookup */ - public function getBlobStore() { - return $this->getService( '_SqlBlobStore' ); + public function getRevisionLookup() { + return $this->getService( 'RevisionLookup' ); } /** @@ -780,75 +755,92 @@ class MediaWikiServices extends ServiceContainer { } /** - * @since 1.31 - * @return RevisionLookup + * @since 1.27 + * @return SearchEngine */ - public function getRevisionLookup() { - return $this->getService( 'RevisionLookup' ); + public function newSearchEngine() { + // New engine object every time, since they keep state + return $this->getService( 'SearchEngineFactory' )->create(); } /** - * @since 1.31 - * @return RevisionFactory + * @since 1.27 + * @return SearchEngineConfig */ - public function getRevisionFactory() { - return $this->getService( 'RevisionFactory' ); + public function getSearchEngineConfig() { + return $this->getService( 'SearchEngineConfig' ); } /** - * @since 1.31 - * @return NameTableStore + * @since 1.27 + * @return SearchEngineFactory */ - public function getContentModelStore() { - return $this->getService( 'ContentModelStore' ); + public function getSearchEngineFactory() { + return $this->getService( 'SearchEngineFactory' ); } /** - * @since 1.31 - * @return NameTableStore + * @since 1.30 + * @return CommandFactory */ - public function getSlotRoleStore() { - return $this->getService( 'SlotRoleStore' ); + public function getShellCommandFactory() { + return $this->getService( 'ShellCommandFactory' ); } /** - * @since 1.32 - * @return NameTableStore + * @since 1.27 + * @return SiteLookup */ - public function getChangeTagDefStore() { - return $this->getService( 'ChangeTagDefStore' ); + public function getSiteLookup() { + return $this->getService( 'SiteLookup' ); } /** - * @since 1.31 - * @return PreferencesFactory + * @since 1.27 + * @return SiteStore */ - public function getPreferencesFactory() { - return $this->getService( 'PreferencesFactory' ); + public function getSiteStore() { + return $this->getService( 'SiteStore' ); } /** - * @since 1.31 - * @return HttpRequestFactory + * @since 1.27 + * @return SkinFactory */ - public function getHttpRequestFactory() { - return $this->getService( 'HttpRequestFactory' ); + public function getSkinFactory() { + return $this->getService( 'SkinFactory' ); } /** * @since 1.31 - * @return CommentStore + * @return NameTableStore */ - public function getCommentStore() { - return $this->getService( 'CommentStore' ); + public function getSlotRoleStore() { + return $this->getService( 'SlotRoleStore' ); } /** - * @since 1.31 - * @return ActorMigration + * @since 1.27 + * @return IBufferingStatsdDataFactory */ - public function getActorMigration() { - return $this->getService( 'ActorMigration' ); + public function getStatsdDataFactory() { + return $this->getService( 'StatsdDataFactory' ); + } + + /** + * @since 1.28 + * @return TitleFormatter + */ + public function getTitleFormatter() { + return $this->getService( 'TitleFormatter' ); + } + + /** + * @since 1.28 + * @return TitleParser + */ + public function getTitleParser() { + return $this->getService( 'TitleParser' ); } /** @@ -860,43 +852,51 @@ class MediaWikiServices extends ServiceContainer { } /** - * @since 1.32 - * @return OldRevisionImporter + * @since 1.28 + * @return VirtualRESTServiceClient */ - public function getOldRevisionImporter() { - return $this->getService( 'OldRevisionImporter' ); + public function getVirtualRESTServiceClient() { + return $this->getService( 'VirtualRESTServiceClient' ); } /** - * @since 1.32 - * @return ConfigRepository + * @since 1.28 + * @return WatchedItemQueryService */ - public function getConfigRepository() { - return $this->getService( 'ConfigRepository' ); + public function getWatchedItemQueryService() { + return $this->getService( 'WatchedItemQueryService' ); } /** - * @since 1.32 - * @return MagicWordFactory + * @since 1.28 + * @return WatchedItemStoreInterface */ - public function getMagicWordFactory() { - return $this->getService( 'MagicWordFactory' ); + public function getWatchedItemStore() { + return $this->getService( 'WatchedItemStore' ); } /** - * @since 1.32 - * @return \Language + * @since 1.31 + * @return \OldRevisionImporter */ - public function getContentLanguage() { - return $this->getService( 'ContentLanguage' ); + public function getWikiRevisionOldRevisionImporter() { + return $this->getService( 'OldRevisionImporter' ); } /** - * @since 1.32 - * @return PasswordFactory + * @since 1.31 + * @return \OldRevisionImporter */ - public function getPasswordFactory() { - return $this->getService( 'PasswordFactory' ); + public function getWikiRevisionOldRevisionImporterNoUpdates() { + return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' ); + } + + /** + * @since 1.31 + * @return \UploadRevisionImporter + */ + public function getWikiRevisionUploadImporter() { + return $this->getService( 'UploadRevisionImporter' ); } /////////////////////////////////////////////////////////////////////////// diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 671544e549..6202f8313a 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -51,46 +51,48 @@ use MediaWiki\Storage\RevisionStoreFactory; use Wikimedia\ObjectFactory; return [ - 'DBLoadBalancerFactory' => function ( MediaWikiServices $services ) { - $mainConfig = $services->getMainConfig(); - - $lbConf = MWLBFactory::applyDefaultConfig( - $mainConfig->get( 'LBFactoryConf' ), - $mainConfig, - $services->getConfiguredReadOnlyMode() + 'ActorMigration' => function ( MediaWikiServices $services ) { + return new ActorMigration( + $services->getMainConfig()->get( 'ActorTableSchemaMigrationStage' ) ); - $class = MWLBFactory::getLBFactoryClass( $lbConf ); - - $instance = new $class( $lbConf ); - MWLBFactory::setSchemaAliases( $instance, $mainConfig ); - - return $instance; }, - 'DBLoadBalancer' => function ( MediaWikiServices $services ) { - // just return the default LB from the DBLoadBalancerFactory service - return $services->getDBLoadBalancerFactory()->getMainLB(); + 'BlobStore' => function ( MediaWikiServices $services ) { + return $services->getService( '_SqlBlobStore' ); }, - 'SiteStore' => function ( MediaWikiServices $services ) { - $rawSiteStore = new DBSiteStore( $services->getDBLoadBalancer() ); - - // TODO: replace wfGetCache with a CacheFactory service. - // TODO: replace wfIsHHVM with a capabilities service. - $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING ); - - return new CachingSiteStore( $rawSiteStore, $cache ); + 'BlobStoreFactory' => function ( MediaWikiServices $services ) { + return new BlobStoreFactory( + $services->getDBLoadBalancer(), + $services->getMainWANObjectCache(), + $services->getMainConfig(), + $services->getContentLanguage() + ); }, - 'SiteLookup' => function ( MediaWikiServices $services ) { - $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' ); + 'ChangeTagDefStore' => function ( MediaWikiServices $services ) { + return new NameTableStore( + $services->getDBLoadBalancer(), + $services->getMainWANObjectCache(), + LoggerFactory::getInstance( 'NameTableSqlStore' ), + 'change_tag_def', + 'ctd_id', + 'ctd_name', + null, + false, + function ( $insertFields ) { + $insertFields['ctd_user_defined'] = 0; + $insertFields['ctd_count'] = 0; + return $insertFields; + } + ); + }, - if ( $cacheFile !== false ) { - return new FileBasedSiteLookup( $cacheFile ); - } else { - // Use the default SiteStore as the SiteLookup implementation for now - return $services->getSiteStore(); - } + 'CommentStore' => function ( MediaWikiServices $services ) { + return new CommentStore( + $services->getContentLanguage(), + $services->getMainConfig()->get( 'CommentTableSchemaMigrationStage' ) + ); }, 'ConfigFactory' => function ( MediaWikiServices $services ) { @@ -108,120 +110,177 @@ return [ return new ConfigRepository( $services->getConfigFactory() ); }, - 'MainConfig' => function ( MediaWikiServices $services ) { - // Use the 'main' config from the ConfigFactory service. - return $services->getConfigFactory()->makeConfig( 'main' ); + 'ConfiguredReadOnlyMode' => function ( MediaWikiServices $services ) { + return new ConfiguredReadOnlyMode( $services->getMainConfig() ); }, - 'InterwikiLookup' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); - return new ClassicInterwikiLookup( - $services->getContentLanguage(), - $services->getMainWANObjectCache(), - $config->get( 'InterwikiExpiry' ), - $config->get( 'InterwikiCache' ), - $config->get( 'InterwikiScopes' ), - $config->get( 'InterwikiFallbackSite' ) - ); + 'ContentLanguage' => function ( MediaWikiServices $services ) { + return Language::factory( $services->getMainConfig()->get( 'LanguageCode' ) ); }, - 'StatsdDataFactory' => function ( MediaWikiServices $services ) { - return new BufferingStatsdDataFactory( - rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) + 'ContentModelStore' => function ( MediaWikiServices $services ) { + return new NameTableStore( + $services->getDBLoadBalancer(), + $services->getMainWANObjectCache(), + LoggerFactory::getInstance( 'NameTableSqlStore' ), + 'content_models', + 'model_id', + 'model_name' + /** + * No strtolower normalization is added to the service as there are examples of + * extensions that do not stick to this assumption. + * - extensions/examples/DataPages define( 'CONTENT_MODEL_XML_DATA','XML_DATA' ); + * - extensions/Scribunto define( 'CONTENT_MODEL_SCRIBUNTO', 'Scribunto' ); + */ ); }, - 'PerDbNameStatsdDataFactory' => function ( MediaWikiServices $services ) { + 'CryptHKDF' => function ( MediaWikiServices $services ) { $config = $services->getMainConfig(); - $wiki = $config->get( 'DBname' ); - return new BufferingStatsdDataFactory( - rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) . '.' . $wiki + + $secret = $config->get( 'HKDFSecret' ) ?: $config->get( 'SecretKey' ); + if ( !$secret ) { + throw new RuntimeException( "Cannot use MWCryptHKDF without a secret." ); + } + + // In HKDF, the context can be known to the attacker, but this will + // keep simultaneous runs from producing the same output. + $context = [ microtime(), getmypid(), gethostname() ]; + + // Setup salt cache. Use APC, or fallback to the main cache if it isn't setup + $cache = $services->getLocalServerObjectCache(); + if ( $cache instanceof EmptyBagOStuff ) { + $cache = ObjectCache::getLocalClusterInstance(); + } + + return new CryptHKDF( $secret, $config->get( 'HKDFAlgorithm' ), $cache, $context ); + }, + + 'CryptRand' => function () { + return new CryptRand(); + }, + + 'DBLoadBalancer' => function ( MediaWikiServices $services ) { + // just return the default LB from the DBLoadBalancerFactory service + return $services->getDBLoadBalancerFactory()->getMainLB(); + }, + + 'DBLoadBalancerFactory' => function ( MediaWikiServices $services ) { + $mainConfig = $services->getMainConfig(); + + $lbConf = MWLBFactory::applyDefaultConfig( + $mainConfig->get( 'LBFactoryConf' ), + $mainConfig, + $services->getConfiguredReadOnlyMode() ); + $class = MWLBFactory::getLBFactoryClass( $lbConf ); + + $instance = new $class( $lbConf ); + MWLBFactory::setSchemaAliases( $instance, $mainConfig ); + + return $instance; }, 'EventRelayerGroup' => function ( MediaWikiServices $services ) { return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) ); }, - 'SearchEngineFactory' => function ( MediaWikiServices $services ) { - return new SearchEngineFactory( $services->getSearchEngineConfig() ); - }, + 'ExternalStoreFactory' => function ( MediaWikiServices $services ) { + $config = $services->getMainConfig(); - 'SearchEngineConfig' => function ( MediaWikiServices $services ) { - return new SearchEngineConfig( $services->getMainConfig(), - $services->getContentLanguage() ); + return new ExternalStoreFactory( + $config->get( 'ExternalStores' ) + ); }, - 'SkinFactory' => function ( MediaWikiServices $services ) { - $factory = new SkinFactory(); - - $names = $services->getMainConfig()->get( 'ValidSkinNames' ); + 'GenderCache' => function ( MediaWikiServices $services ) { + return new GenderCache(); + }, - foreach ( $names as $name => $skin ) { - $factory->register( $name, $skin, function () use ( $name, $skin ) { - $class = "Skin$skin"; - return new $class( $name ); - } ); - } - // Register a hidden "fallback" skin - $factory->register( 'fallback', 'Fallback', function () { - return new SkinFallback; - } ); - // Register a hidden skin for api output - $factory->register( 'apioutput', 'ApiOutput', function () { - return new SkinApi; - } ); + 'HttpRequestFactory' => function ( MediaWikiServices $services ) { + return new \MediaWiki\Http\HttpRequestFactory(); + }, - return $factory; + 'InterwikiLookup' => function ( MediaWikiServices $services ) { + $config = $services->getMainConfig(); + return new ClassicInterwikiLookup( + $services->getContentLanguage(), + $services->getMainWANObjectCache(), + $config->get( 'InterwikiExpiry' ), + $config->get( 'InterwikiCache' ), + $config->get( 'InterwikiScopes' ), + $config->get( 'InterwikiFallbackSite' ) + ); }, - 'WatchedItemStore' => function ( MediaWikiServices $services ) { - $store = new WatchedItemStore( - $services->getDBLoadBalancer(), - new HashBagOStuff( [ 'maxKeys' => 100 ] ), - $services->getReadOnlyMode(), - $services->getMainConfig()->get( 'UpdateRowsPerQuery' ) + 'LinkCache' => function ( MediaWikiServices $services ) { + return new LinkCache( + $services->getTitleFormatter(), + $services->getMainWANObjectCache() ); - $store->setStatsdDataFactory( $services->getStatsdDataFactory() ); + }, - if ( $services->getMainConfig()->get( 'ReadOnlyWatchedItemStore' ) ) { - $store = new NoWriteWatchedItemStore( $store ); - } + 'LinkRenderer' => function ( MediaWikiServices $services ) { + global $wgUser; - return $store; + if ( defined( 'MW_NO_SESSION' ) ) { + return $services->getLinkRendererFactory()->create(); + } else { + return $services->getLinkRendererFactory()->createForUser( $wgUser ); + } }, - 'WatchedItemQueryService' => function ( MediaWikiServices $services ) { - return new WatchedItemQueryService( - $services->getDBLoadBalancer(), - $services->getCommentStore(), - $services->getActorMigration() + 'LinkRendererFactory' => function ( MediaWikiServices $services ) { + return new LinkRendererFactory( + $services->getTitleFormatter(), + $services->getLinkCache() ); }, - 'CryptRand' => function () { - return new CryptRand(); + 'LocalServerObjectCache' => function ( MediaWikiServices $services ) { + $cacheId = \ObjectCache::detectLocalServerCache(); + return \ObjectCache::newFromId( $cacheId ); }, - 'CryptHKDF' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); + 'MagicWordFactory' => function ( MediaWikiServices $services ) { + return new MagicWordFactory( $services->getContentLanguage() ); + }, - $secret = $config->get( 'HKDFSecret' ) ?: $config->get( 'SecretKey' ); - if ( !$secret ) { - throw new RuntimeException( "Cannot use MWCryptHKDF without a secret." ); + 'MainConfig' => function ( MediaWikiServices $services ) { + // Use the 'main' config from the ConfigFactory service. + return $services->getConfigFactory()->makeConfig( 'main' ); + }, + + 'MainObjectStash' => function ( MediaWikiServices $services ) { + $mainConfig = $services->getMainConfig(); + + $id = $mainConfig->get( 'MainStash' ); + if ( !isset( $mainConfig->get( 'ObjectCaches' )[$id] ) ) { + throw new UnexpectedValueException( + "Cache type \"$id\" is not present in \$wgObjectCaches." ); } - // In HKDF, the context can be known to the attacker, but this will - // keep simultaneous runs from producing the same output. - $context = [ microtime(), getmypid(), gethostname() ]; + return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] ); + }, - // Setup salt cache. Use APC, or fallback to the main cache if it isn't setup - $cache = $services->getLocalServerObjectCache(); - if ( $cache instanceof EmptyBagOStuff ) { - $cache = ObjectCache::getLocalClusterInstance(); + 'MainWANObjectCache' => function ( MediaWikiServices $services ) { + $mainConfig = $services->getMainConfig(); + + $id = $mainConfig->get( 'MainWANCache' ); + if ( !isset( $mainConfig->get( 'WANObjectCaches' )[$id] ) ) { + throw new UnexpectedValueException( + "WAN cache type \"$id\" is not present in \$wgWANObjectCaches." ); } - return new CryptHKDF( $secret, $config->get( 'HKDFAlgorithm' ), $cache, $context ); + $params = $mainConfig->get( 'WANObjectCaches' )[$id]; + $objectCacheId = $params['cacheId']; + if ( !isset( $mainConfig->get( 'ObjectCaches' )[$objectCacheId] ) ) { + throw new UnexpectedValueException( + "Cache type \"$objectCacheId\" is not present in \$wgObjectCaches." ); + } + $params['store'] = $mainConfig->get( 'ObjectCaches' )[$objectCacheId]; + + return \ObjectCache::newWANCacheFromParams( $params ); }, 'MediaHandlerFactory' => function ( MediaWikiServices $services ) { @@ -289,11 +348,11 @@ return [ return new MimeMagic( $params ); }, - 'ProxyLookup' => function ( MediaWikiServices $services ) { - $mainConfig = $services->getMainConfig(); - return new ProxyLookup( - $mainConfig->get( 'SquidServers' ), - $mainConfig->get( 'SquidServersNoPurge' ) + 'OldRevisionImporter' => function ( MediaWikiServices $services ) { + return new ImportableOldRevisionImporter( + true, + LoggerFactory::getInstance( 'OldRevisionImporter' ), + $services->getDBLoadBalancer() ); }, @@ -314,164 +373,56 @@ return [ ); }, - 'LinkCache' => function ( MediaWikiServices $services ) { - return new LinkCache( - $services->getTitleFormatter(), - $services->getMainWANObjectCache() - ); - }, - - 'LinkRendererFactory' => function ( MediaWikiServices $services ) { - return new LinkRendererFactory( - $services->getTitleFormatter(), - $services->getLinkCache() - ); - }, - - 'LinkRenderer' => function ( MediaWikiServices $services ) { - global $wgUser; - - if ( defined( 'MW_NO_SESSION' ) ) { - return $services->getLinkRendererFactory()->create(); - } else { - return $services->getLinkRendererFactory()->createForUser( $wgUser ); - } - }, - - 'GenderCache' => function ( MediaWikiServices $services ) { - return new GenderCache(); - }, - - '_MediaWikiTitleCodec' => function ( MediaWikiServices $services ) { - return new MediaWikiTitleCodec( - $services->getContentLanguage(), - $services->getGenderCache(), - $services->getMainConfig()->get( 'LocalInterwikis' ) - ); - }, - - 'TitleFormatter' => function ( MediaWikiServices $services ) { - return $services->getService( '_MediaWikiTitleCodec' ); - }, - - 'TitleParser' => function ( MediaWikiServices $services ) { - return $services->getService( '_MediaWikiTitleCodec' ); - }, - - 'MainObjectStash' => function ( MediaWikiServices $services ) { - $mainConfig = $services->getMainConfig(); - - $id = $mainConfig->get( 'MainStash' ); - if ( !isset( $mainConfig->get( 'ObjectCaches' )[$id] ) ) { - throw new UnexpectedValueException( - "Cache type \"$id\" is not present in \$wgObjectCaches." ); - } - - return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] ); - }, - - 'MainWANObjectCache' => function ( MediaWikiServices $services ) { - $mainConfig = $services->getMainConfig(); - - $id = $mainConfig->get( 'MainWANCache' ); - if ( !isset( $mainConfig->get( 'WANObjectCaches' )[$id] ) ) { - throw new UnexpectedValueException( - "WAN cache type \"$id\" is not present in \$wgWANObjectCaches." ); - } - - $params = $mainConfig->get( 'WANObjectCaches' )[$id]; - $objectCacheId = $params['cacheId']; - if ( !isset( $mainConfig->get( 'ObjectCaches' )[$objectCacheId] ) ) { - throw new UnexpectedValueException( - "Cache type \"$objectCacheId\" is not present in \$wgObjectCaches." ); - } - $params['store'] = $mainConfig->get( 'ObjectCaches' )[$objectCacheId]; - - return \ObjectCache::newWANCacheFromParams( $params ); - }, - - 'LocalServerObjectCache' => function ( MediaWikiServices $services ) { - $cacheId = \ObjectCache::detectLocalServerCache(); - return \ObjectCache::newFromId( $cacheId ); - }, - - 'VirtualRESTServiceClient' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig()->get( 'VirtualRestConfig' ); - - $vrsClient = new VirtualRESTServiceClient( new MultiHttpClient( [] ) ); - foreach ( $config['paths'] as $prefix => $serviceConfig ) { - $class = $serviceConfig['class']; - // Merge in the global defaults - $constructArg = $serviceConfig['options'] ?? []; - $constructArg += $config['global']; - // Make the VRS service available at the mount point - $vrsClient->mount( $prefix, [ 'class' => $class, 'config' => $constructArg ] ); - } - - return $vrsClient; - }, - - 'ConfiguredReadOnlyMode' => function ( MediaWikiServices $services ) { - return new ConfiguredReadOnlyMode( $services->getMainConfig() ); - }, - - 'ReadOnlyMode' => function ( MediaWikiServices $services ) { - return new ReadOnlyMode( - $services->getConfiguredReadOnlyMode(), - $services->getDBLoadBalancer() - ); - }, - - 'UploadRevisionImporter' => function ( MediaWikiServices $services ) { - return new ImportableUploadRevisionImporter( - $services->getMainConfig()->get( 'EnableUploads' ), - LoggerFactory::getInstance( 'UploadRevisionImporter' ) - ); - }, - - 'OldRevisionImporter' => function ( MediaWikiServices $services ) { - return new ImportableOldRevisionImporter( - true, - LoggerFactory::getInstance( 'OldRevisionImporter' ), - $services->getDBLoadBalancer() + 'PasswordFactory' => function ( MediaWikiServices $services ) { + $config = $services->getMainConfig(); + return new PasswordFactory( + $config->get( 'PasswordConfig' ), + $config->get( 'PasswordDefault' ) ); }, - 'WikiRevisionOldRevisionImporterNoUpdates' => function ( MediaWikiServices $services ) { - return new ImportableOldRevisionImporter( - false, - LoggerFactory::getInstance( 'OldRevisionImporter' ), - $services->getDBLoadBalancer() + 'PerDbNameStatsdDataFactory' => function ( MediaWikiServices $services ) { + $config = $services->getMainConfig(); + $wiki = $config->get( 'DBname' ); + return new BufferingStatsdDataFactory( + rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) . '.' . $wiki ); }, - 'ShellCommandFactory' => function ( MediaWikiServices $services ) { + 'PreferencesFactory' => function ( MediaWikiServices $services ) { + $authManager = AuthManager::singleton(); + $linkRenderer = $services->getLinkRendererFactory()->create(); $config = $services->getMainConfig(); - - $limits = [ - 'time' => $config->get( 'MaxShellTime' ), - 'walltime' => $config->get( 'MaxShellWallClockTime' ), - 'memory' => $config->get( 'MaxShellMemory' ), - 'filesize' => $config->get( 'MaxShellFileSize' ), - ]; - $cgroup = $config->get( 'ShellCgroup' ); - $restrictionMethod = $config->get( 'ShellRestrictionMethod' ); - - $factory = new CommandFactory( $limits, $cgroup, $restrictionMethod ); - $factory->setLogger( LoggerFactory::getInstance( 'exec' ) ); - $factory->logStderr(); + $factory = new DefaultPreferencesFactory( $config, $services->getContentLanguage(), + $authManager, $linkRenderer ); + $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) ); return $factory; }, - 'ExternalStoreFactory' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); + 'ProxyLookup' => function ( MediaWikiServices $services ) { + $mainConfig = $services->getMainConfig(); + return new ProxyLookup( + $mainConfig->get( 'SquidServers' ), + $mainConfig->get( 'SquidServersNoPurge' ) + ); + }, - return new ExternalStoreFactory( - $config->get( 'ExternalStores' ) + 'ReadOnlyMode' => function ( MediaWikiServices $services ) { + return new ReadOnlyMode( + $services->getConfiguredReadOnlyMode(), + $services->getDBLoadBalancer() ); }, + 'RevisionFactory' => function ( MediaWikiServices $services ) { + return $services->getRevisionStore(); + }, + + 'RevisionLookup' => function ( MediaWikiServices $services ) { + return $services->getRevisionStore(); + }, + 'RevisionStore' => function ( MediaWikiServices $services ) { return $services->getRevisionStoreFactory()->getRevisionStore(); }, @@ -492,46 +443,76 @@ return [ return $store; }, - 'RevisionLookup' => function ( MediaWikiServices $services ) { - return $services->getRevisionStore(); + 'SearchEngineConfig' => function ( MediaWikiServices $services ) { + return new SearchEngineConfig( $services->getMainConfig(), + $services->getContentLanguage() ); }, - 'RevisionFactory' => function ( MediaWikiServices $services ) { - return $services->getRevisionStore(); + 'SearchEngineFactory' => function ( MediaWikiServices $services ) { + return new SearchEngineFactory( $services->getSearchEngineConfig() ); }, - 'BlobStoreFactory' => function ( MediaWikiServices $services ) { - return new BlobStoreFactory( - $services->getDBLoadBalancer(), - $services->getMainWANObjectCache(), - $services->getMainConfig(), - $services->getContentLanguage() - ); + 'ShellCommandFactory' => function ( MediaWikiServices $services ) { + $config = $services->getMainConfig(); + + $limits = [ + 'time' => $config->get( 'MaxShellTime' ), + 'walltime' => $config->get( 'MaxShellWallClockTime' ), + 'memory' => $config->get( 'MaxShellMemory' ), + 'filesize' => $config->get( 'MaxShellFileSize' ), + ]; + $cgroup = $config->get( 'ShellCgroup' ); + $restrictionMethod = $config->get( 'ShellRestrictionMethod' ); + + $factory = new CommandFactory( $limits, $cgroup, $restrictionMethod ); + $factory->setLogger( LoggerFactory::getInstance( 'exec' ) ); + $factory->logStderr(); + + return $factory; }, - 'BlobStore' => function ( MediaWikiServices $services ) { - return $services->getService( '_SqlBlobStore' ); + 'SiteLookup' => function ( MediaWikiServices $services ) { + $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' ); + + if ( $cacheFile !== false ) { + return new FileBasedSiteLookup( $cacheFile ); + } else { + // Use the default SiteStore as the SiteLookup implementation for now + return $services->getSiteStore(); + } }, - '_SqlBlobStore' => function ( MediaWikiServices $services ) { - return $services->getBlobStoreFactory()->newSqlBlobStore(); + 'SiteStore' => function ( MediaWikiServices $services ) { + $rawSiteStore = new DBSiteStore( $services->getDBLoadBalancer() ); + + // TODO: replace wfGetCache with a CacheFactory service. + // TODO: replace wfIsHHVM with a capabilities service. + $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING ); + + return new CachingSiteStore( $rawSiteStore, $cache ); }, - 'ContentModelStore' => function ( MediaWikiServices $services ) { - return new NameTableStore( - $services->getDBLoadBalancer(), - $services->getMainWANObjectCache(), - LoggerFactory::getInstance( 'NameTableSqlStore' ), - 'content_models', - 'model_id', - 'model_name' - /** - * No strtolower normalization is added to the service as there are examples of - * extensions that do not stick to this assumption. - * - extensions/examples/DataPages define( 'CONTENT_MODEL_XML_DATA','XML_DATA' ); - * - extensions/Scribunto define( 'CONTENT_MODEL_SCRIBUNTO', 'Scribunto' ); - */ - ); + 'SkinFactory' => function ( MediaWikiServices $services ) { + $factory = new SkinFactory(); + + $names = $services->getMainConfig()->get( 'ValidSkinNames' ); + + foreach ( $names as $name => $skin ) { + $factory->register( $name, $skin, function () use ( $name, $skin ) { + $class = "Skin$skin"; + return new $class( $name ); + } ); + } + // Register a hidden "fallback" skin + $factory->register( 'fallback', 'Fallback', function () { + return new SkinFallback; + } ); + // Register a hidden skin for api output + $factory->register( 'apioutput', 'ApiOutput', function () { + return new SkinApi; + } ); + + return $factory; }, 'SlotRoleStore' => function ( MediaWikiServices $services ) { @@ -546,68 +527,87 @@ return [ ); }, - 'ChangeTagDefStore' => function ( MediaWikiServices $services ) { - return new NameTableStore( - $services->getDBLoadBalancer(), - $services->getMainWANObjectCache(), - LoggerFactory::getInstance( 'NameTableSqlStore' ), - 'change_tag_def', - 'ctd_id', - 'ctd_name', - null, - false, - function ( $insertFields ) { - $insertFields['ctd_user_defined'] = 0; - $insertFields['ctd_count'] = 0; - return $insertFields; - } + 'StatsdDataFactory' => function ( MediaWikiServices $services ) { + return new BufferingStatsdDataFactory( + rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) ); }, - 'PreferencesFactory' => function ( MediaWikiServices $services ) { - $authManager = AuthManager::singleton(); - $linkRenderer = $services->getLinkRendererFactory()->create(); - $config = $services->getMainConfig(); - $factory = new DefaultPreferencesFactory( $config, $services->getContentLanguage(), - $authManager, $linkRenderer ); - $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) ); - - return $factory; + 'TitleFormatter' => function ( MediaWikiServices $services ) { + return $services->getService( '_MediaWikiTitleCodec' ); }, - 'HttpRequestFactory' => function ( MediaWikiServices $services ) { - return new \MediaWiki\Http\HttpRequestFactory(); + 'TitleParser' => function ( MediaWikiServices $services ) { + return $services->getService( '_MediaWikiTitleCodec' ); }, - 'CommentStore' => function ( MediaWikiServices $services ) { - return new CommentStore( - $services->getContentLanguage(), - $services->getMainConfig()->get( 'CommentTableSchemaMigrationStage' ) + 'UploadRevisionImporter' => function ( MediaWikiServices $services ) { + return new ImportableUploadRevisionImporter( + $services->getMainConfig()->get( 'EnableUploads' ), + LoggerFactory::getInstance( 'UploadRevisionImporter' ) ); }, - 'ActorMigration' => function ( MediaWikiServices $services ) { - return new ActorMigration( - $services->getMainConfig()->get( 'ActorTableSchemaMigrationStage' ) + 'VirtualRESTServiceClient' => function ( MediaWikiServices $services ) { + $config = $services->getMainConfig()->get( 'VirtualRestConfig' ); + + $vrsClient = new VirtualRESTServiceClient( new MultiHttpClient( [] ) ); + foreach ( $config['paths'] as $prefix => $serviceConfig ) { + $class = $serviceConfig['class']; + // Merge in the global defaults + $constructArg = $serviceConfig['options'] ?? []; + $constructArg += $config['global']; + // Make the VRS service available at the mount point + $vrsClient->mount( $prefix, [ 'class' => $class, 'config' => $constructArg ] ); + } + + return $vrsClient; + }, + + 'WatchedItemQueryService' => function ( MediaWikiServices $services ) { + return new WatchedItemQueryService( + $services->getDBLoadBalancer(), + $services->getCommentStore(), + $services->getActorMigration() ); }, - 'MagicWordFactory' => function ( MediaWikiServices $services ) { - return new MagicWordFactory( $services->getContentLanguage() ); + 'WatchedItemStore' => function ( MediaWikiServices $services ) { + $store = new WatchedItemStore( + $services->getDBLoadBalancer(), + new HashBagOStuff( [ 'maxKeys' => 100 ] ), + $services->getReadOnlyMode(), + $services->getMainConfig()->get( 'UpdateRowsPerQuery' ) + ); + $store->setStatsdDataFactory( $services->getStatsdDataFactory() ); + + if ( $services->getMainConfig()->get( 'ReadOnlyWatchedItemStore' ) ) { + $store = new NoWriteWatchedItemStore( $store ); + } + + return $store; }, - 'ContentLanguage' => function ( MediaWikiServices $services ) { - return Language::factory( $services->getMainConfig()->get( 'LanguageCode' ) ); + 'WikiRevisionOldRevisionImporterNoUpdates' => function ( MediaWikiServices $services ) { + return new ImportableOldRevisionImporter( + false, + LoggerFactory::getInstance( 'OldRevisionImporter' ), + $services->getDBLoadBalancer() + ); }, - 'PasswordFactory' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); - return new PasswordFactory( - $config->get( 'PasswordConfig' ), - $config->get( 'PasswordDefault' ) + '_MediaWikiTitleCodec' => function ( MediaWikiServices $services ) { + return new MediaWikiTitleCodec( + $services->getContentLanguage(), + $services->getGenderCache(), + $services->getMainConfig()->get( 'LocalInterwikis' ) ); }, + '_SqlBlobStore' => function ( MediaWikiServices $services ) { + return $services->getBlobStoreFactory()->newSqlBlobStore(); + }, + /////////////////////////////////////////////////////////////////////////// // NOTE: When adding a service here, don't forget to add a getter function // in the MediaWikiServices class. The convenience getter should just call diff --git a/tests/phpunit/includes/MediaWikiServicesTest.php b/tests/phpunit/includes/MediaWikiServicesTest.php index 413c1a24f4..eee4490e60 100644 --- a/tests/phpunit/includes/MediaWikiServicesTest.php +++ b/tests/phpunit/includes/MediaWikiServicesTest.php @@ -309,67 +309,71 @@ class MediaWikiServicesTest extends MediaWikiTestCase { public function provideGetService() { // NOTE: This should list all service getters defined in ServiceWiring.php. return [ + '_MediaWikiTitleCodec' => [ '_MediaWikiTitleCodec', MediaWikiTitleCodec::class ], + '_SqlBlobStore' => [ '_SqlBlobStore', SqlBlobStore::class ], + 'ActorMigration' => [ 'ActorMigration', ActorMigration::class ], + 'BlobStore' => [ 'BlobStore', BlobStore::class ], + 'BlobStoreFactory' => [ 'BlobStoreFactory', BlobStoreFactory::class ], 'BootstrapConfig' => [ 'BootstrapConfig', Config::class ], + 'ChangeTagDefStore' => [ 'ChangeTagDefStore', NameTableStore::class ], + 'CommentStore' => [ 'CommentStore', CommentStore::class ], 'ConfigFactory' => [ 'ConfigFactory', ConfigFactory::class ], - 'MainConfig' => [ 'MainConfig', Config::class ], - 'SiteStore' => [ 'SiteStore', SiteStore::class ], - 'SiteLookup' => [ 'SiteLookup', SiteLookup::class ], - 'StatsdDataFactory' => [ 'StatsdDataFactory', IBufferingStatsdDataFactory::class ], - 'PerDbNameStatsdDataFactory' => - [ 'PerDbNameStatsdDataFactory', IBufferingStatsdDataFactory::class ], - 'InterwikiLookup' => [ 'InterwikiLookup', InterwikiLookup::class ], - 'EventRelayerGroup' => [ 'EventRelayerGroup', EventRelayerGroup::class ], - 'SearchEngineFactory' => [ 'SearchEngineFactory', SearchEngineFactory::class ], - 'SearchEngineConfig' => [ 'SearchEngineConfig', SearchEngineConfig::class ], - 'SkinFactory' => [ 'SkinFactory', SkinFactory::class ], - 'DBLoadBalancerFactory' => [ 'DBLoadBalancerFactory', Wikimedia\Rdbms\LBFactory::class ], - 'DBLoadBalancer' => [ 'DBLoadBalancer', Wikimedia\Rdbms\LoadBalancer::class ], - 'WatchedItemStore' => [ 'WatchedItemStore', WatchedItemStore::class ], - 'WatchedItemQueryService' => [ 'WatchedItemQueryService', WatchedItemQueryService::class ], - 'CryptRand' => [ 'CryptRand', CryptRand::class ], + 'ConfigRepository' => [ 'ConfigRepository', \MediaWiki\Config\ConfigRepository::class ], + 'ConfiguredReadOnlyMode' => [ 'ConfiguredReadOnlyMode', ConfiguredReadOnlyMode::class ], + 'ContentLanguage' => [ 'ContentLanguage', Language::class ], + 'ContentModelStore' => [ 'ContentModelStore', NameTableStore::class ], 'CryptHKDF' => [ 'CryptHKDF', CryptHKDF::class ], - 'MediaHandlerFactory' => [ 'MediaHandlerFactory', MediaHandlerFactory::class ], - 'Parser' => [ 'Parser', Parser::class ], - 'ParserCache' => [ 'ParserCache', ParserCache::class ], + 'CryptRand' => [ 'CryptRand', CryptRand::class ], + 'DBLoadBalancer' => [ 'DBLoadBalancer', Wikimedia\Rdbms\LoadBalancer::class ], + 'DBLoadBalancerFactory' => + [ 'DBLoadBalancerFactory', Wikimedia\Rdbms\LBFactory::class ], + 'EventRelayerGroup' => [ 'EventRelayerGroup', EventRelayerGroup::class ], + 'ExternalStoreFactory' => [ 'ExternalStoreFactory', ExternalStoreFactory::class ], 'GenderCache' => [ 'GenderCache', GenderCache::class ], + 'HttpRequestFactory' => [ 'HttpRequestFactory', HttpRequestFactory::class ], + 'InterwikiLookup' => [ 'InterwikiLookup', InterwikiLookup::class ], 'LinkCache' => [ 'LinkCache', LinkCache::class ], 'LinkRenderer' => [ 'LinkRenderer', LinkRenderer::class ], 'LinkRendererFactory' => [ 'LinkRendererFactory', LinkRendererFactory::class ], - '_MediaWikiTitleCodec' => [ '_MediaWikiTitleCodec', MediaWikiTitleCodec::class ], - 'MimeAnalyzer' => [ 'MimeAnalyzer', MimeAnalyzer::class ], - 'TitleFormatter' => [ 'TitleFormatter', TitleFormatter::class ], - 'TitleParser' => [ 'TitleParser', TitleParser::class ], - 'ProxyLookup' => [ 'ProxyLookup', ProxyLookup::class ], + 'LocalServerObjectCache' => [ 'LocalServerObjectCache', BagOStuff::class ], + 'MagicWordFactory' => [ 'MagicWordFactory', MagicWordFactory::class ], + 'MainConfig' => [ 'MainConfig', Config::class ], 'MainObjectStash' => [ 'MainObjectStash', BagOStuff::class ], 'MainWANObjectCache' => [ 'MainWANObjectCache', WANObjectCache::class ], - 'LocalServerObjectCache' => [ 'LocalServerObjectCache', BagOStuff::class ], - 'VirtualRESTServiceClient' => [ 'VirtualRESTServiceClient', VirtualRESTServiceClient::class ], - 'ShellCommandFactory' => [ 'ShellCommandFactory', CommandFactory::class ], - 'BlobStoreFactory' => [ 'BlobStoreFactory', BlobStoreFactory::class ], - 'BlobStore' => [ 'BlobStore', BlobStore::class ], - '_SqlBlobStore' => [ '_SqlBlobStore', SqlBlobStore::class ], + 'MediaHandlerFactory' => [ 'MediaHandlerFactory', MediaHandlerFactory::class ], + 'MimeAnalyzer' => [ 'MimeAnalyzer', MimeAnalyzer::class ], + 'OldRevisionImporter' => [ 'OldRevisionImporter', OldRevisionImporter::class ], + 'Parser' => [ 'Parser', Parser::class ], + 'ParserCache' => [ 'ParserCache', ParserCache::class ], + 'PasswordFactory' => [ 'PasswordFactory', PasswordFactory::class ], + 'PerDbNameStatsdDataFactory' => + [ 'PerDbNameStatsdDataFactory', IBufferingStatsdDataFactory::class ], + 'PreferencesFactory' => [ 'PreferencesFactory', PreferencesFactory::class ], + 'ProxyLookup' => [ 'ProxyLookup', ProxyLookup::class ], + 'ReadOnlyMode' => [ 'ReadOnlyMode', ReadOnlyMode::class ], + 'RevisionFactory' => [ 'RevisionFactory', RevisionFactory::class ], + 'RevisionLookup' => [ 'RevisionLookup', RevisionLookup::class ], 'RevisionStore' => [ 'RevisionStore', RevisionStore::class ], 'RevisionStoreFactory' => [ 'RevisionStoreFactory', RevisionStoreFactory::class ], - 'RevisionLookup' => [ 'RevisionLookup', RevisionLookup::class ], - 'RevisionFactory' => [ 'RevisionFactory', RevisionFactory::class ], - 'ContentModelStore' => [ 'ContentModelStore', NameTableStore::class ], + 'SearchEngineConfig' => [ 'SearchEngineConfig', SearchEngineConfig::class ], + 'SearchEngineFactory' => [ 'SearchEngineFactory', SearchEngineFactory::class ], + 'ShellCommandFactory' => [ 'ShellCommandFactory', CommandFactory::class ], + 'SiteLookup' => [ 'SiteLookup', SiteLookup::class ], + 'SiteStore' => [ 'SiteStore', SiteStore::class ], + 'SkinFactory' => [ 'SkinFactory', SkinFactory::class ], 'SlotRoleStore' => [ 'SlotRoleStore', NameTableStore::class ], - 'HttpRequestFactory' => [ 'HttpRequestFactory', HttpRequestFactory::class ], - 'CommentStore' => [ 'CommentStore', CommentStore::class ], - 'ChangeTagDefStore' => [ 'ChangeTagDefStore', NameTableStore::class ], - 'ConfiguredReadOnlyMode' => [ 'ConfiguredReadOnlyMode', ConfiguredReadOnlyMode::class ], - 'ReadOnlyMode' => [ 'ReadOnlyMode', ReadOnlyMode::class ], + 'StatsdDataFactory' => [ 'StatsdDataFactory', IBufferingStatsdDataFactory::class ], + 'TitleFormatter' => [ 'TitleFormatter', TitleFormatter::class ], + 'TitleParser' => [ 'TitleParser', TitleParser::class ], 'UploadRevisionImporter' => [ 'UploadRevisionImporter', UploadRevisionImporter::class ], - 'OldRevisionImporter' => [ 'OldRevisionImporter', OldRevisionImporter::class ], + 'VirtualRESTServiceClient' => + [ 'VirtualRESTServiceClient', VirtualRESTServiceClient::class ], + 'WatchedItemQueryService' => + [ 'WatchedItemQueryService', WatchedItemQueryService::class ], + 'WatchedItemStore' => [ 'WatchedItemStore', WatchedItemStore::class ], 'WikiRevisionOldRevisionImporterNoUpdates' => - [ 'WikiRevisionOldRevisionImporterNoUpdates', ImportableOldRevisionImporter::class ], - 'ExternalStoreFactory' => [ 'ExternalStoreFactory', ExternalStoreFactory::class ], - 'PreferencesFactory' => [ 'PreferencesFactory', PreferencesFactory::class ], - 'ActorMigration' => [ 'ActorMigration', ActorMigration::class ], - 'ConfigRepository' => [ 'ConfigRepository', \MediaWiki\Config\ConfigRepository::class ], - 'MagicWordFactory' => [ 'MagicWordFactory', MagicWordFactory::class ], - 'ContentLanguage' => [ 'ContentLanguage', Language::class ], - 'PasswordFactory' => [ 'PasswordFactory', PasswordFactory::class ], + [ 'WikiRevisionOldRevisionImporterNoUpdates', + ImportableOldRevisionImporter::class ], ]; } @@ -409,4 +413,24 @@ class MediaWikiServicesTest extends MediaWikiTestCase { ); } + public function testGettersAreSorted() { + $methods = ( new ReflectionClass( MediaWikiServices::class ) ) + ->getMethods( ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC ); + + $names = array_map( function ( $method ) { + return $method->getName(); + }, $methods ); + $serviceNames = array_map( function ( $name ) { + return "get$name"; + }, array_keys( $this->provideGetService() ) ); + $names = array_values( array_filter( $names, function ( $name ) use ( $serviceNames ) { + return in_array( $name, $serviceNames ); + } ) ); + + $sortedNames = $names; + sort( $sortedNames ); + + $this->assertSame( $sortedNames, $names, + 'Please keep service getters sorted alphabetically' ); + } } diff --git a/tests/phpunit/includes/ServiceWiringTest.php b/tests/phpunit/includes/ServiceWiringTest.php new file mode 100644 index 0000000000..74e8e1b3ea --- /dev/null +++ b/tests/phpunit/includes/ServiceWiringTest.php @@ -0,0 +1,16 @@ +assertSame( $sortedServices, $services, + 'Please keep services sorted alphabetically' ); + } +}