X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FServiceWiring.php;h=286dde197ded6d09d1f0648ef4d1e4fc416da703;hb=eaa34630f4d837422bfed32c492d7a4beffc6ddd;hp=92b2411c435cd335909041c0ecdfa0a04fd145d9;hpb=754d08f8ad32a197ad563aa45ea4d6dadcaf2b75;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 92b2411c43..286dde197d 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -40,61 +40,70 @@ use MediaWiki\Auth\AuthManager; use MediaWiki\Config\ConfigRepository; use MediaWiki\Interwiki\ClassicInterwikiLookup; +use MediaWiki\Interwiki\InterwikiLookup; +use MediaWiki\Linker\LinkRenderer; use MediaWiki\Linker\LinkRendererFactory; use MediaWiki\Logger\LoggerFactory; use MediaWiki\MediaWikiServices; +use MediaWiki\Preferences\PreferencesFactory; use MediaWiki\Preferences\DefaultPreferencesFactory; use MediaWiki\Shell\CommandFactory; +use MediaWiki\Special\SpecialPageFactory; +use MediaWiki\Storage\BlobStore; use MediaWiki\Storage\BlobStoreFactory; use MediaWiki\Storage\NameTableStore; +use MediaWiki\Storage\RevisionFactory; +use MediaWiki\Storage\RevisionLookup; use MediaWiki\Storage\RevisionStore; +use MediaWiki\Storage\RevisionStoreFactory; use MediaWiki\Storage\SqlBlobStore; -use Wikimedia\ObjectFactory; return [ - 'DBLoadBalancerFactory' => function ( MediaWikiServices $services ) { - $mainConfig = $services->getMainConfig(); - - $lbConf = MWLBFactory::applyDefaultConfig( - $mainConfig->get( 'LBFactoryConf' ), - $mainConfig, - $services->getConfiguredReadOnlyMode() + 'ActorMigration' => function ( MediaWikiServices $services ) : ActorMigration { + 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 ) : BlobStore { + 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 ) : BlobStoreFactory { + return new BlobStoreFactory( + $services->getDBLoadBalancer(), + $services->getMainWANObjectCache(), + $services->getMainConfig(), + $services->getContentLanguage() + ); }, - 'SiteLookup' => function ( MediaWikiServices $services ) { - $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' ); + 'ChangeTagDefStore' => function ( MediaWikiServices $services ) : NameTableStore { + 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 ) : CommentStore { + return new CommentStore( + $services->getContentLanguage(), + $services->getMainConfig()->get( 'CommentTableSchemaMigrationStage' ) + ); }, - 'ConfigFactory' => function ( MediaWikiServices $services ) { + 'ConfigFactory' => function ( MediaWikiServices $services ) : ConfigFactory { // Use the bootstrap config to initialize the ConfigFactory. $registry = $services->getBootstrapConfig()->get( 'ConfigRegistry' ); $factory = new ConfigFactory(); @@ -105,133 +114,192 @@ return [ return $factory; }, - 'ConfigRepository' => function ( MediaWikiServices $services ) { + 'ConfigRepository' => function ( MediaWikiServices $services ) : ConfigRepository { 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 ) : ConfiguredReadOnlyMode { + return new ConfiguredReadOnlyMode( $services->getMainConfig() ); }, - 'InterwikiLookup' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); - return new ClassicInterwikiLookup( - $services->getContentLanguage(), + 'ContentLanguage' => function ( MediaWikiServices $services ) : Language { + return Language::factory( $services->getMainConfig()->get( 'LanguageCode' ) ); + }, + + 'ContentModelStore' => function ( MediaWikiServices $services ) : NameTableStore { + return new NameTableStore( + $services->getDBLoadBalancer(), $services->getMainWANObjectCache(), - $config->get( 'InterwikiExpiry' ), - $config->get( 'InterwikiCache' ), - $config->get( 'InterwikiScopes' ), - $config->get( 'InterwikiFallbackSite' ) + 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' ); + */ ); }, - 'StatsdDataFactory' => function ( MediaWikiServices $services ) { - return new BufferingStatsdDataFactory( - rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) + 'CryptHKDF' => function ( MediaWikiServices $services ) : CryptHKDF { + $config = $services->getMainConfig(); + + $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 () : CryptRand { + return new CryptRand(); + }, + + 'DBLoadBalancer' => function ( MediaWikiServices $services ) : Wikimedia\Rdbms\LoadBalancer { + // just return the default LB from the DBLoadBalancerFactory service + return $services->getDBLoadBalancerFactory()->getMainLB(); + }, + + 'DBLoadBalancerFactory' => + function ( MediaWikiServices $services ) : Wikimedia\Rdbms\LBFactory { + $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 ) : EventRelayerGroup { + return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) ); }, - 'PerDbNameStatsdDataFactory' => function ( MediaWikiServices $services ) { + 'ExternalStoreFactory' => function ( MediaWikiServices $services ) : ExternalStoreFactory { $config = $services->getMainConfig(); - $wiki = $config->get( 'DBname' ); - return new BufferingStatsdDataFactory( - rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ) ) . '.' . $wiki + + return new ExternalStoreFactory( + $config->get( 'ExternalStores' ) ); }, - 'EventRelayerGroup' => function ( MediaWikiServices $services ) { - return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) ); + 'GenderCache' => function ( MediaWikiServices $services ) : GenderCache { + return new GenderCache(); }, - 'SearchEngineFactory' => function ( MediaWikiServices $services ) { - return new SearchEngineFactory( $services->getSearchEngineConfig() ); + 'HttpRequestFactory' => + function ( MediaWikiServices $services ) : \MediaWiki\Http\HttpRequestFactory { + return new \MediaWiki\Http\HttpRequestFactory(); }, - 'SearchEngineConfig' => function ( MediaWikiServices $services ) { - return new SearchEngineConfig( $services->getMainConfig(), - $services->getContentLanguage() ); + 'InterwikiLookup' => function ( MediaWikiServices $services ) : InterwikiLookup { + $config = $services->getMainConfig(); + return new ClassicInterwikiLookup( + $services->getContentLanguage(), + $services->getMainWANObjectCache(), + $config->get( 'InterwikiExpiry' ), + $config->get( 'InterwikiCache' ), + $config->get( 'InterwikiScopes' ), + $config->get( 'InterwikiFallbackSite' ) + ); }, - 'SkinFactory' => function ( MediaWikiServices $services ) { - $factory = new SkinFactory(); + 'LinkCache' => function ( MediaWikiServices $services ) : LinkCache { + return new LinkCache( + $services->getTitleFormatter(), + $services->getMainWANObjectCache() + ); + }, - $names = $services->getMainConfig()->get( 'ValidSkinNames' ); + 'LinkRenderer' => function ( MediaWikiServices $services ) : LinkRenderer { + global $wgUser; - foreach ( $names as $name => $skin ) { - $factory->register( $name, $skin, function () use ( $name, $skin ) { - $class = "Skin$skin"; - return new $class( $name ); - } ); + if ( defined( 'MW_NO_SESSION' ) ) { + return $services->getLinkRendererFactory()->create(); + } else { + return $services->getLinkRendererFactory()->createForUser( $wgUser ); } - // 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; }, - 'WatchedItemStore' => function ( MediaWikiServices $services ) { - $store = new WatchedItemStore( - $services->getDBLoadBalancer(), - new HashBagOStuff( [ 'maxKeys' => 100 ] ), - $services->getReadOnlyMode(), - $services->getMainConfig()->get( 'UpdateRowsPerQuery' ) + 'LinkRendererFactory' => function ( MediaWikiServices $services ) : LinkRendererFactory { + return new LinkRendererFactory( + $services->getTitleFormatter(), + $services->getLinkCache() ); - $store->setStatsdDataFactory( $services->getStatsdDataFactory() ); - - if ( $services->getMainConfig()->get( 'ReadOnlyWatchedItemStore' ) ) { - $store = new NoWriteWatchedItemStore( $store ); - } + }, - return $store; + 'LocalServerObjectCache' => function ( MediaWikiServices $services ) : BagOStuff { + $cacheId = \ObjectCache::detectLocalServerCache(); + return \ObjectCache::newFromId( $cacheId ); }, - 'WatchedItemQueryService' => function ( MediaWikiServices $services ) { - return new WatchedItemQueryService( - $services->getDBLoadBalancer(), - $services->getCommentStore(), - $services->getActorMigration() - ); + 'MagicWordFactory' => function ( MediaWikiServices $services ) : MagicWordFactory { + return new MagicWordFactory( $services->getContentLanguage() ); }, - 'CryptRand' => function () { - return new CryptRand(); + 'MainConfig' => function ( MediaWikiServices $services ) : Config { + // Use the 'main' config from the ConfigFactory service. + return $services->getConfigFactory()->makeConfig( 'main' ); }, - 'CryptHKDF' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); + 'MainObjectStash' => function ( MediaWikiServices $services ) : BagOStuff { + $mainConfig = $services->getMainConfig(); - $secret = $config->get( 'HKDFSecret' ) ?: $config->get( 'SecretKey' ); - if ( !$secret ) { - throw new RuntimeException( "Cannot use MWCryptHKDF without a secret." ); + $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 ) : WANObjectCache { + $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 ) { + 'MediaHandlerFactory' => function ( MediaWikiServices $services ) : MediaHandlerFactory { return new MediaHandlerFactory( $services->getMainConfig()->get( 'MediaHandlers' ) ); }, - 'MimeAnalyzer' => function ( MediaWikiServices $services ) { + 'MimeAnalyzer' => function ( MediaWikiServices $services ) : MimeAnalyzer { $logger = LoggerFactory::getInstance( 'Mime' ); $mainConfig = $services->getMainConfig(); $params = [ @@ -290,21 +358,19 @@ 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 ) : OldRevisionImporter { + return new ImportableOldRevisionImporter( + true, + LoggerFactory::getInstance( 'OldRevisionImporter' ), + $services->getDBLoadBalancer() ); }, - 'Parser' => function ( MediaWikiServices $services ) { - $conf = $services->getMainConfig()->get( 'ParserConf' ); - return ObjectFactory::constructClassInstance( $conf['class'], - [ $conf, $services->getMagicWordFactory() ] ); + 'Parser' => function ( MediaWikiServices $services ) : Parser { + return $services->getParserFactory()->create(); }, - 'ParserCache' => function ( MediaWikiServices $services ) { + 'ParserCache' => function ( MediaWikiServices $services ) : ParserCache { $config = $services->getMainConfig(); $cache = ObjectCache::getInstance( $config->get( 'ParserCacheType' ) ); wfDebugLog( 'caches', 'parser: ' . get_class( $cache ) ); @@ -315,138 +381,98 @@ return [ ); }, - 'LinkCache' => function ( MediaWikiServices $services ) { - return new LinkCache( - $services->getTitleFormatter(), - $services->getMainWANObjectCache() + 'ParserFactory' => function ( MediaWikiServices $services ) : ParserFactory { + return new ParserFactory( + $services->getMainConfig()->get( 'ParserConf' ), + $services->getMagicWordFactory(), + $services->getContentLanguage(), + wfUrlProtocols(), + $services->getSpecialPageFactory() ); }, - 'LinkRendererFactory' => function ( MediaWikiServices $services ) { - return new LinkRendererFactory( - $services->getTitleFormatter(), - $services->getLinkCache() + 'PasswordFactory' => function ( MediaWikiServices $services ) : PasswordFactory { + $config = $services->getMainConfig(); + return new PasswordFactory( + $config->get( 'PasswordConfig' ), + $config->get( 'PasswordDefault' ) ); }, - '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(); + 'PerDbNameStatsdDataFactory' => + function ( MediaWikiServices $services ) : IBufferingStatsdDataFactory { + $config = $services->getMainConfig(); + $wiki = $config->get( 'DBname' ); + return new BufferingStatsdDataFactory( + rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) . '.' . $wiki + ); }, - '_MediaWikiTitleCodec' => function ( MediaWikiServices $services ) { - return new MediaWikiTitleCodec( + 'PreferencesFactory' => function ( MediaWikiServices $services ) : PreferencesFactory { + $factory = new DefaultPreferencesFactory( + $services->getMainConfig(), $services->getContentLanguage(), - $services->getGenderCache(), - $services->getMainConfig()->get( 'LocalInterwikis' ) + AuthManager::singleton(), + $services->getLinkRendererFactory()->create() ); - }, - - 'TitleFormatter' => function ( MediaWikiServices $services ) { - return $services->getService( '_MediaWikiTitleCodec' ); - }, + $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) ); - 'TitleParser' => function ( MediaWikiServices $services ) { - return $services->getService( '_MediaWikiTitleCodec' ); + return $factory; }, - 'MainObjectStash' => function ( MediaWikiServices $services ) { + 'ProxyLookup' => function ( MediaWikiServices $services ) : ProxyLookup { $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] ); + return new ProxyLookup( + $mainConfig->get( 'SquidServers' ), + $mainConfig->get( 'SquidServersNoPurge' ) + ); }, - '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 ); + 'ReadOnlyMode' => function ( MediaWikiServices $services ) : ReadOnlyMode { + return new ReadOnlyMode( + $services->getConfiguredReadOnlyMode(), + $services->getDBLoadBalancer() + ); }, - 'LocalServerObjectCache' => function ( MediaWikiServices $services ) { - $cacheId = \ObjectCache::detectLocalServerCache(); - return \ObjectCache::newFromId( $cacheId ); + 'RevisionFactory' => function ( MediaWikiServices $services ) : RevisionFactory { + return $services->getRevisionStore(); }, - '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; + 'RevisionLookup' => function ( MediaWikiServices $services ) : RevisionLookup { + return $services->getRevisionStore(); }, - 'ConfiguredReadOnlyMode' => function ( MediaWikiServices $services ) { - return new ConfiguredReadOnlyMode( $services->getMainConfig() ); + 'RevisionStore' => function ( MediaWikiServices $services ) : RevisionStore { + return $services->getRevisionStoreFactory()->getRevisionStore(); }, - 'ReadOnlyMode' => function ( MediaWikiServices $services ) { - return new ReadOnlyMode( - $services->getConfiguredReadOnlyMode(), - $services->getDBLoadBalancer() + 'RevisionStoreFactory' => function ( MediaWikiServices $services ) : RevisionStoreFactory { + $config = $services->getMainConfig(); + $store = new RevisionStoreFactory( + $services->getDBLoadBalancerFactory(), + $services->getBlobStoreFactory(), + $services->getMainWANObjectCache(), + $services->getCommentStore(), + $services->getActorMigration(), + $config->get( 'MultiContentRevisionSchemaMigrationStage' ), + LoggerFactory::getProvider(), + $config->get( 'ContentHandlerUseDB' ) ); - }, - 'UploadRevisionImporter' => function ( MediaWikiServices $services ) { - return new ImportableUploadRevisionImporter( - $services->getMainConfig()->get( 'EnableUploads' ), - LoggerFactory::getInstance( 'UploadRevisionImporter' ) - ); + return $store; }, - 'OldRevisionImporter' => function ( MediaWikiServices $services ) { - return new ImportableOldRevisionImporter( - true, - LoggerFactory::getInstance( 'OldRevisionImporter' ), - $services->getDBLoadBalancer() - ); + 'SearchEngineConfig' => function ( MediaWikiServices $services ) : SearchEngineConfig { + return new SearchEngineConfig( $services->getMainConfig(), + $services->getContentLanguage() ); }, - 'WikiRevisionOldRevisionImporterNoUpdates' => function ( MediaWikiServices $services ) { - return new ImportableOldRevisionImporter( - false, - LoggerFactory::getInstance( 'OldRevisionImporter' ), - $services->getDBLoadBalancer() - ); + 'SearchEngineFactory' => function ( MediaWikiServices $services ) : SearchEngineFactory { + return new SearchEngineFactory( $services->getSearchEngineConfig() ); }, - 'ShellCommandFactory' => function ( MediaWikiServices $services ) { + 'ShellCommandFactory' => function ( MediaWikiServices $services ) : CommandFactory { $config = $services->getMainConfig(); $limits = [ @@ -465,143 +491,152 @@ return [ return $factory; }, - 'ExternalStoreFactory' => function ( MediaWikiServices $services ) { - $config = $services->getMainConfig(); + 'SiteLookup' => function ( MediaWikiServices $services ) : SiteLookup { + $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' ); - return new ExternalStoreFactory( - $config->get( 'ExternalStores' ) - ); + if ( $cacheFile !== false ) { + return new FileBasedSiteLookup( $cacheFile ); + } else { + // Use the default SiteStore as the SiteLookup implementation for now + return $services->getSiteStore(); + } }, - 'RevisionStore' => function ( MediaWikiServices $services ) { - /** @var SqlBlobStore $blobStore */ - $blobStore = $services->getService( '_SqlBlobStore' ); + 'SiteStore' => function ( MediaWikiServices $services ) : SiteStore { + $rawSiteStore = new DBSiteStore( $services->getDBLoadBalancer() ); - $store = new RevisionStore( - $services->getDBLoadBalancer(), - $blobStore, - $services->getMainWANObjectCache(), - $services->getCommentStore(), - $services->getContentModelStore(), - $services->getSlotRoleStore(), - $services->getMainConfig()->get( 'MultiContentRevisionSchemaMigrationStage' ), - $services->getActorMigration() - ); + // TODO: replace wfGetCache with a CacheFactory service. + // TODO: replace wfIsHHVM with a capabilities service. + $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING ); - $store->setLogger( LoggerFactory::getInstance( 'RevisionStore' ) ); + return new CachingSiteStore( $rawSiteStore, $cache ); + }, - $config = $services->getMainConfig(); - $store->setContentHandlerUseDB( $config->get( 'ContentHandlerUseDB' ) ); + 'SkinFactory' => function ( MediaWikiServices $services ) : SkinFactory { + $factory = new SkinFactory(); - return $store; - }, + $names = $services->getMainConfig()->get( 'ValidSkinNames' ); - 'RevisionLookup' => function ( MediaWikiServices $services ) { - return $services->getRevisionStore(); - }, + 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; + } ); - 'RevisionFactory' => function ( MediaWikiServices $services ) { - return $services->getRevisionStore(); + return $factory; }, - 'BlobStoreFactory' => function ( MediaWikiServices $services ) { - return new BlobStoreFactory( + 'SlotRoleStore' => function ( MediaWikiServices $services ) : NameTableStore { + return new NameTableStore( $services->getDBLoadBalancer(), $services->getMainWANObjectCache(), + LoggerFactory::getInstance( 'NameTableSqlStore' ), + 'slot_roles', + 'role_id', + 'role_name', + 'strtolower' + ); + }, + + 'SpecialPageFactory' => function ( MediaWikiServices $services ) : SpecialPageFactory { + return new SpecialPageFactory( $services->getMainConfig(), $services->getContentLanguage() ); }, - 'BlobStore' => function ( MediaWikiServices $services ) { - return $services->getService( '_SqlBlobStore' ); + 'StatsdDataFactory' => function ( MediaWikiServices $services ) : IBufferingStatsdDataFactory { + return new BufferingStatsdDataFactory( + rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) + ); }, - '_SqlBlobStore' => function ( MediaWikiServices $services ) { - return $services->getBlobStoreFactory()->newSqlBlobStore(); + 'TitleFormatter' => function ( MediaWikiServices $services ) : TitleFormatter { + return $services->getService( '_MediaWikiTitleCodec' ); }, - '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' ); - */ - ); + 'TitleParser' => function ( MediaWikiServices $services ) : TitleParser { + return $services->getService( '_MediaWikiTitleCodec' ); }, - 'SlotRoleStore' => function ( MediaWikiServices $services ) { - return new NameTableStore( - $services->getDBLoadBalancer(), - $services->getMainWANObjectCache(), - LoggerFactory::getInstance( 'NameTableSqlStore' ), - 'slot_roles', - 'role_id', - 'role_name', - 'strtolower' + 'UploadRevisionImporter' => function ( MediaWikiServices $services ) : UploadRevisionImporter { + return new ImportableUploadRevisionImporter( + $services->getMainConfig()->get( 'EnableUploads' ), + LoggerFactory::getInstance( 'UploadRevisionImporter' ) ); }, - '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; - } - ); - }, + 'VirtualRESTServiceClient' => + function ( MediaWikiServices $services ) : VirtualRESTServiceClient { + $config = $services->getMainConfig()->get( 'VirtualRestConfig' ); - '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' ) ); + $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 $factory; + return $vrsClient; }, - 'HttpRequestFactory' => function ( MediaWikiServices $services ) { - return new \MediaWiki\Http\HttpRequestFactory(); + 'WatchedItemQueryService' => + function ( MediaWikiServices $services ) : WatchedItemQueryService { + return new WatchedItemQueryService( + $services->getDBLoadBalancer(), + $services->getCommentStore(), + $services->getActorMigration() + ); }, - 'CommentStore' => function ( MediaWikiServices $services ) { - return new CommentStore( - $services->getContentLanguage(), - $services->getMainConfig()->get( 'CommentTableSchemaMigrationStage' ) + 'WatchedItemStore' => function ( MediaWikiServices $services ) : WatchedItemStore { + $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; }, - 'ActorMigration' => function ( MediaWikiServices $services ) { - return new ActorMigration( - $services->getMainConfig()->get( 'ActorTableSchemaMigrationStage' ) + 'WikiRevisionOldRevisionImporterNoUpdates' => + function ( MediaWikiServices $services ) : ImportableOldRevisionImporter { + return new ImportableOldRevisionImporter( + false, + LoggerFactory::getInstance( 'OldRevisionImporter' ), + $services->getDBLoadBalancer() ); }, - 'MagicWordFactory' => function ( MediaWikiServices $services ) { - return new MagicWordFactory( $services->getContentLanguage() ); + '_MediaWikiTitleCodec' => function ( MediaWikiServices $services ) : MediaWikiTitleCodec { + return new MediaWikiTitleCodec( + $services->getContentLanguage(), + $services->getGenderCache(), + $services->getMainConfig()->get( 'LocalInterwikis' ), + $services->getInterwikiLookup() + ); }, - 'ContentLanguage' => function ( MediaWikiServices $services ) { - return Language::factory( $services->getMainConfig()->get( 'LanguageCode' ) ); + '_SqlBlobStore' => function ( MediaWikiServices $services ) : SqlBlobStore { + return $services->getBlobStoreFactory()->newSqlBlobStore(); }, ///////////////////////////////////////////////////////////////////////////