ServiceWiring.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. <?php
  2. /**
  3. * Default wiring for MediaWiki services.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. *
  22. * This file is loaded by MediaWiki\MediaWikiServices::getInstance() during the
  23. * bootstrapping of the dependency injection framework.
  24. *
  25. * This file returns an array that associates service name with instantiator functions
  26. * that create the default instances for the services used by MediaWiki core.
  27. * For every service that MediaWiki core requires, an instantiator must be defined in
  28. * this file.
  29. *
  30. * @note As of version 1.27, MediaWiki is only beginning to use dependency injection.
  31. * The services defined here do not yet fully represent all services used by core,
  32. * much of the code still relies on global state for this accessing services.
  33. *
  34. * @since 1.27
  35. *
  36. * @see docs/injection.txt for an overview of using dependency injection in the
  37. * MediaWiki code base.
  38. */
  39. use MediaWiki\Auth\AuthManager;
  40. use MediaWiki\Interwiki\ClassicInterwikiLookup;
  41. use MediaWiki\Linker\LinkRendererFactory;
  42. use MediaWiki\Logger\LoggerFactory;
  43. use MediaWiki\MediaWikiServices;
  44. use MediaWiki\Preferences\DefaultPreferencesFactory;
  45. use MediaWiki\Shell\CommandFactory;
  46. use MediaWiki\Storage\BlobStoreFactory;
  47. use MediaWiki\Storage\NameTableStore;
  48. use MediaWiki\Storage\RevisionStore;
  49. use MediaWiki\Storage\SqlBlobStore;
  50. use Wikimedia\ObjectFactory;
  51. return [
  52. 'DBLoadBalancerFactory' => function ( MediaWikiServices $services ) {
  53. $mainConfig = $services->getMainConfig();
  54. $lbConf = MWLBFactory::applyDefaultConfig(
  55. $mainConfig->get( 'LBFactoryConf' ),
  56. $mainConfig,
  57. $services->getConfiguredReadOnlyMode()
  58. );
  59. $class = MWLBFactory::getLBFactoryClass( $lbConf );
  60. $instance = new $class( $lbConf );
  61. MWLBFactory::setSchemaAliases( $instance, $mainConfig );
  62. return $instance;
  63. },
  64. 'DBLoadBalancer' => function ( MediaWikiServices $services ) {
  65. // just return the default LB from the DBLoadBalancerFactory service
  66. return $services->getDBLoadBalancerFactory()->getMainLB();
  67. },
  68. 'SiteStore' => function ( MediaWikiServices $services ) {
  69. $rawSiteStore = new DBSiteStore( $services->getDBLoadBalancer() );
  70. // TODO: replace wfGetCache with a CacheFactory service.
  71. // TODO: replace wfIsHHVM with a capabilities service.
  72. $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING );
  73. return new CachingSiteStore( $rawSiteStore, $cache );
  74. },
  75. 'SiteLookup' => function ( MediaWikiServices $services ) {
  76. $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' );
  77. if ( $cacheFile !== false ) {
  78. return new FileBasedSiteLookup( $cacheFile );
  79. } else {
  80. // Use the default SiteStore as the SiteLookup implementation for now
  81. return $services->getSiteStore();
  82. }
  83. },
  84. 'ConfigFactory' => function ( MediaWikiServices $services ) {
  85. // Use the bootstrap config to initialize the ConfigFactory.
  86. $registry = $services->getBootstrapConfig()->get( 'ConfigRegistry' );
  87. $factory = new ConfigFactory();
  88. foreach ( $registry as $name => $callback ) {
  89. $factory->register( $name, $callback );
  90. }
  91. return $factory;
  92. },
  93. 'MainConfig' => function ( MediaWikiServices $services ) {
  94. // Use the 'main' config from the ConfigFactory service.
  95. return $services->getConfigFactory()->makeConfig( 'main' );
  96. },
  97. 'InterwikiLookup' => function ( MediaWikiServices $services ) {
  98. global $wgContLang; // TODO: manage $wgContLang as a service
  99. $config = $services->getMainConfig();
  100. return new ClassicInterwikiLookup(
  101. $wgContLang,
  102. $services->getMainWANObjectCache(),
  103. $config->get( 'InterwikiExpiry' ),
  104. $config->get( 'InterwikiCache' ),
  105. $config->get( 'InterwikiScopes' ),
  106. $config->get( 'InterwikiFallbackSite' )
  107. );
  108. },
  109. 'StatsdDataFactory' => function ( MediaWikiServices $services ) {
  110. return new BufferingStatsdDataFactory(
  111. rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' )
  112. );
  113. },
  114. 'EventRelayerGroup' => function ( MediaWikiServices $services ) {
  115. return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) );
  116. },
  117. 'SearchEngineFactory' => function ( MediaWikiServices $services ) {
  118. return new SearchEngineFactory( $services->getSearchEngineConfig() );
  119. },
  120. 'SearchEngineConfig' => function ( MediaWikiServices $services ) {
  121. global $wgContLang;
  122. return new SearchEngineConfig( $services->getMainConfig(), $wgContLang );
  123. },
  124. 'SkinFactory' => function ( MediaWikiServices $services ) {
  125. $factory = new SkinFactory();
  126. $names = $services->getMainConfig()->get( 'ValidSkinNames' );
  127. foreach ( $names as $name => $skin ) {
  128. $factory->register( $name, $skin, function () use ( $name, $skin ) {
  129. $class = "Skin$skin";
  130. return new $class( $name );
  131. } );
  132. }
  133. // Register a hidden "fallback" skin
  134. $factory->register( 'fallback', 'Fallback', function () {
  135. return new SkinFallback;
  136. } );
  137. // Register a hidden skin for api output
  138. $factory->register( 'apioutput', 'ApiOutput', function () {
  139. return new SkinApi;
  140. } );
  141. return $factory;
  142. },
  143. 'WatchedItemStore' => function ( MediaWikiServices $services ) {
  144. $store = new WatchedItemStore(
  145. $services->getDBLoadBalancer(),
  146. new HashBagOStuff( [ 'maxKeys' => 100 ] ),
  147. $services->getReadOnlyMode(),
  148. $services->getMainConfig()->get( 'UpdateRowsPerQuery' )
  149. );
  150. $store->setStatsdDataFactory( $services->getStatsdDataFactory() );
  151. if ( $services->getMainConfig()->get( 'ReadOnlyWatchedItemStore' ) ) {
  152. $store = new NoWriteWatchedItemStore( $store );
  153. }
  154. return $store;
  155. },
  156. 'WatchedItemQueryService' => function ( MediaWikiServices $services ) {
  157. return new WatchedItemQueryService(
  158. $services->getDBLoadBalancer(),
  159. $services->getCommentStore(),
  160. $services->getActorMigration()
  161. );
  162. },
  163. 'CryptRand' => function ( MediaWikiServices $services ) {
  164. $secretKey = $services->getMainConfig()->get( 'SecretKey' );
  165. return new CryptRand(
  166. [
  167. // To try vary the system information of the state a bit more
  168. // by including the system's hostname into the state
  169. 'wfHostname',
  170. // It's mostly worthless but throw the wiki's id into the data
  171. // for a little more variance
  172. 'wfWikiID',
  173. // If we have a secret key set then throw it into the state as well
  174. function () use ( $secretKey ) {
  175. return $secretKey ?: '';
  176. }
  177. ],
  178. // The config file is likely the most often edited file we know should
  179. // be around so include its stat info into the state.
  180. // The constant with its location will almost always be defined, as
  181. // WebStart.php defines MW_CONFIG_FILE to $IP/LocalSettings.php unless
  182. // being configured with MW_CONFIG_CALLBACK (e.g. the installer).
  183. defined( 'MW_CONFIG_FILE' ) ? [ MW_CONFIG_FILE ] : [],
  184. LoggerFactory::getInstance( 'CryptRand' )
  185. );
  186. },
  187. 'CryptHKDF' => function ( MediaWikiServices $services ) {
  188. $config = $services->getMainConfig();
  189. $secret = $config->get( 'HKDFSecret' ) ?: $config->get( 'SecretKey' );
  190. if ( !$secret ) {
  191. throw new RuntimeException( "Cannot use MWCryptHKDF without a secret." );
  192. }
  193. // In HKDF, the context can be known to the attacker, but this will
  194. // keep simultaneous runs from producing the same output.
  195. $context = [ microtime(), getmypid(), gethostname() ];
  196. // Setup salt cache. Use APC, or fallback to the main cache if it isn't setup
  197. $cache = $services->getLocalServerObjectCache();
  198. if ( $cache instanceof EmptyBagOStuff ) {
  199. $cache = ObjectCache::getLocalClusterInstance();
  200. }
  201. return new CryptHKDF( $secret, $config->get( 'HKDFAlgorithm' ),
  202. $cache, $context, $services->getCryptRand()
  203. );
  204. },
  205. 'MediaHandlerFactory' => function ( MediaWikiServices $services ) {
  206. return new MediaHandlerFactory(
  207. $services->getMainConfig()->get( 'MediaHandlers' )
  208. );
  209. },
  210. 'MimeAnalyzer' => function ( MediaWikiServices $services ) {
  211. $logger = LoggerFactory::getInstance( 'Mime' );
  212. $mainConfig = $services->getMainConfig();
  213. $params = [
  214. 'typeFile' => $mainConfig->get( 'MimeTypeFile' ),
  215. 'infoFile' => $mainConfig->get( 'MimeInfoFile' ),
  216. 'xmlTypes' => $mainConfig->get( 'XMLMimeTypes' ),
  217. 'guessCallback' =>
  218. function ( $mimeAnalyzer, &$head, &$tail, $file, &$mime ) use ( $logger ) {
  219. // Also test DjVu
  220. $deja = new DjVuImage( $file );
  221. if ( $deja->isValid() ) {
  222. $logger->info( __METHOD__ . ": detected $file as image/vnd.djvu\n" );
  223. $mime = 'image/vnd.djvu';
  224. return;
  225. }
  226. // Some strings by reference for performance - assuming well-behaved hooks
  227. Hooks::run(
  228. 'MimeMagicGuessFromContent',
  229. [ $mimeAnalyzer, &$head, &$tail, $file, &$mime ]
  230. );
  231. },
  232. 'extCallback' => function ( $mimeAnalyzer, $ext, &$mime ) {
  233. // Media handling extensions can improve the MIME detected
  234. Hooks::run( 'MimeMagicImproveFromExtension', [ $mimeAnalyzer, $ext, &$mime ] );
  235. },
  236. 'initCallback' => function ( $mimeAnalyzer ) {
  237. // Allow media handling extensions adding MIME-types and MIME-info
  238. Hooks::run( 'MimeMagicInit', [ $mimeAnalyzer ] );
  239. },
  240. 'logger' => $logger
  241. ];
  242. if ( $params['infoFile'] === 'includes/mime.info' ) {
  243. $params['infoFile'] = __DIR__ . "/libs/mime/mime.info";
  244. }
  245. if ( $params['typeFile'] === 'includes/mime.types' ) {
  246. $params['typeFile'] = __DIR__ . "/libs/mime/mime.types";
  247. }
  248. $detectorCmd = $mainConfig->get( 'MimeDetectorCommand' );
  249. if ( $detectorCmd ) {
  250. $factory = $services->getShellCommandFactory();
  251. $params['detectCallback'] = function ( $file ) use ( $detectorCmd, $factory ) {
  252. $result = $factory->create()
  253. // $wgMimeDetectorCommand can contain commands with parameters
  254. ->unsafeParams( $detectorCmd )
  255. ->params( $file )
  256. ->execute();
  257. return $result->getStdout();
  258. };
  259. }
  260. // XXX: MimeMagic::singleton currently requires this service to return an instance of MimeMagic
  261. return new MimeMagic( $params );
  262. },
  263. 'ProxyLookup' => function ( MediaWikiServices $services ) {
  264. $mainConfig = $services->getMainConfig();
  265. return new ProxyLookup(
  266. $mainConfig->get( 'SquidServers' ),
  267. $mainConfig->get( 'SquidServersNoPurge' )
  268. );
  269. },
  270. 'Parser' => function ( MediaWikiServices $services ) {
  271. $conf = $services->getMainConfig()->get( 'ParserConf' );
  272. return ObjectFactory::constructClassInstance( $conf['class'], [ $conf ] );
  273. },
  274. 'ParserCache' => function ( MediaWikiServices $services ) {
  275. $config = $services->getMainConfig();
  276. $cache = ObjectCache::getInstance( $config->get( 'ParserCacheType' ) );
  277. wfDebugLog( 'caches', 'parser: ' . get_class( $cache ) );
  278. return new ParserCache(
  279. $cache,
  280. $config->get( 'CacheEpoch' )
  281. );
  282. },
  283. 'LinkCache' => function ( MediaWikiServices $services ) {
  284. return new LinkCache(
  285. $services->getTitleFormatter(),
  286. $services->getMainWANObjectCache()
  287. );
  288. },
  289. 'LinkRendererFactory' => function ( MediaWikiServices $services ) {
  290. return new LinkRendererFactory(
  291. $services->getTitleFormatter(),
  292. $services->getLinkCache()
  293. );
  294. },
  295. 'LinkRenderer' => function ( MediaWikiServices $services ) {
  296. global $wgUser;
  297. if ( defined( 'MW_NO_SESSION' ) ) {
  298. return $services->getLinkRendererFactory()->create();
  299. } else {
  300. return $services->getLinkRendererFactory()->createForUser( $wgUser );
  301. }
  302. },
  303. 'GenderCache' => function ( MediaWikiServices $services ) {
  304. return new GenderCache();
  305. },
  306. '_MediaWikiTitleCodec' => function ( MediaWikiServices $services ) {
  307. global $wgContLang;
  308. return new MediaWikiTitleCodec(
  309. $wgContLang,
  310. $services->getGenderCache(),
  311. $services->getMainConfig()->get( 'LocalInterwikis' )
  312. );
  313. },
  314. 'TitleFormatter' => function ( MediaWikiServices $services ) {
  315. return $services->getService( '_MediaWikiTitleCodec' );
  316. },
  317. 'TitleParser' => function ( MediaWikiServices $services ) {
  318. return $services->getService( '_MediaWikiTitleCodec' );
  319. },
  320. 'MainObjectStash' => function ( MediaWikiServices $services ) {
  321. $mainConfig = $services->getMainConfig();
  322. $id = $mainConfig->get( 'MainStash' );
  323. if ( !isset( $mainConfig->get( 'ObjectCaches' )[$id] ) ) {
  324. throw new UnexpectedValueException(
  325. "Cache type \"$id\" is not present in \$wgObjectCaches." );
  326. }
  327. return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] );
  328. },
  329. 'MainWANObjectCache' => function ( MediaWikiServices $services ) {
  330. $mainConfig = $services->getMainConfig();
  331. $id = $mainConfig->get( 'MainWANCache' );
  332. if ( !isset( $mainConfig->get( 'WANObjectCaches' )[$id] ) ) {
  333. throw new UnexpectedValueException(
  334. "WAN cache type \"$id\" is not present in \$wgWANObjectCaches." );
  335. }
  336. $params = $mainConfig->get( 'WANObjectCaches' )[$id];
  337. $objectCacheId = $params['cacheId'];
  338. if ( !isset( $mainConfig->get( 'ObjectCaches' )[$objectCacheId] ) ) {
  339. throw new UnexpectedValueException(
  340. "Cache type \"$objectCacheId\" is not present in \$wgObjectCaches." );
  341. }
  342. $params['store'] = $mainConfig->get( 'ObjectCaches' )[$objectCacheId];
  343. return \ObjectCache::newWANCacheFromParams( $params );
  344. },
  345. 'LocalServerObjectCache' => function ( MediaWikiServices $services ) {
  346. $mainConfig = $services->getMainConfig();
  347. if ( function_exists( 'apc_fetch' ) ) {
  348. $id = 'apc';
  349. } elseif ( function_exists( 'apcu_fetch' ) ) {
  350. $id = 'apcu';
  351. } elseif ( function_exists( 'wincache_ucache_get' ) ) {
  352. $id = 'wincache';
  353. } else {
  354. $id = CACHE_NONE;
  355. }
  356. if ( !isset( $mainConfig->get( 'ObjectCaches' )[$id] ) ) {
  357. throw new UnexpectedValueException(
  358. "Cache type \"$id\" is not present in \$wgObjectCaches." );
  359. }
  360. return \ObjectCache::newFromParams( $mainConfig->get( 'ObjectCaches' )[$id] );
  361. },
  362. 'VirtualRESTServiceClient' => function ( MediaWikiServices $services ) {
  363. $config = $services->getMainConfig()->get( 'VirtualRestConfig' );
  364. $vrsClient = new VirtualRESTServiceClient( new MultiHttpClient( [] ) );
  365. foreach ( $config['paths'] as $prefix => $serviceConfig ) {
  366. $class = $serviceConfig['class'];
  367. // Merge in the global defaults
  368. $constructArg = isset( $serviceConfig['options'] )
  369. ? $serviceConfig['options']
  370. : [];
  371. $constructArg += $config['global'];
  372. // Make the VRS service available at the mount point
  373. $vrsClient->mount( $prefix, [ 'class' => $class, 'config' => $constructArg ] );
  374. }
  375. return $vrsClient;
  376. },
  377. 'ConfiguredReadOnlyMode' => function ( MediaWikiServices $services ) {
  378. return new ConfiguredReadOnlyMode( $services->getMainConfig() );
  379. },
  380. 'ReadOnlyMode' => function ( MediaWikiServices $services ) {
  381. return new ReadOnlyMode(
  382. $services->getConfiguredReadOnlyMode(),
  383. $services->getDBLoadBalancer()
  384. );
  385. },
  386. 'UploadRevisionImporter' => function ( MediaWikiServices $services ) {
  387. return new ImportableUploadRevisionImporter(
  388. $services->getMainConfig()->get( 'EnableUploads' ),
  389. LoggerFactory::getInstance( 'UploadRevisionImporter' )
  390. );
  391. },
  392. 'OldRevisionImporter' => function ( MediaWikiServices $services ) {
  393. return new ImportableOldRevisionImporter(
  394. true,
  395. LoggerFactory::getInstance( 'OldRevisionImporter' ),
  396. $services->getDBLoadBalancer()
  397. );
  398. },
  399. 'WikiRevisionOldRevisionImporterNoUpdates' => function ( MediaWikiServices $services ) {
  400. return new ImportableOldRevisionImporter(
  401. false,
  402. LoggerFactory::getInstance( 'OldRevisionImporter' ),
  403. $services->getDBLoadBalancer()
  404. );
  405. },
  406. 'ShellCommandFactory' => function ( MediaWikiServices $services ) {
  407. $config = $services->getMainConfig();
  408. $limits = [
  409. 'time' => $config->get( 'MaxShellTime' ),
  410. 'walltime' => $config->get( 'MaxShellWallClockTime' ),
  411. 'memory' => $config->get( 'MaxShellMemory' ),
  412. 'filesize' => $config->get( 'MaxShellFileSize' ),
  413. ];
  414. $cgroup = $config->get( 'ShellCgroup' );
  415. $restrictionMethod = $config->get( 'ShellRestrictionMethod' );
  416. $factory = new CommandFactory( $limits, $cgroup, $restrictionMethod );
  417. $factory->setLogger( LoggerFactory::getInstance( 'exec' ) );
  418. $factory->logStderr();
  419. return $factory;
  420. },
  421. 'ExternalStoreFactory' => function ( MediaWikiServices $services ) {
  422. $config = $services->getMainConfig();
  423. return new ExternalStoreFactory(
  424. $config->get( 'ExternalStores' )
  425. );
  426. },
  427. 'RevisionStore' => function ( MediaWikiServices $services ) {
  428. /** @var SqlBlobStore $blobStore */
  429. $blobStore = $services->getService( '_SqlBlobStore' );
  430. $store = new RevisionStore(
  431. $services->getDBLoadBalancer(),
  432. $blobStore,
  433. $services->getMainWANObjectCache(),
  434. $services->getCommentStore(),
  435. $services->getActorMigration()
  436. );
  437. $store->setLogger( LoggerFactory::getInstance( 'RevisionStore' ) );
  438. $config = $services->getMainConfig();
  439. $store->setContentHandlerUseDB( $config->get( 'ContentHandlerUseDB' ) );
  440. return $store;
  441. },
  442. 'RevisionLookup' => function ( MediaWikiServices $services ) {
  443. return $services->getRevisionStore();
  444. },
  445. 'RevisionFactory' => function ( MediaWikiServices $services ) {
  446. return $services->getRevisionStore();
  447. },
  448. 'BlobStoreFactory' => function ( MediaWikiServices $services ) {
  449. global $wgContLang;
  450. return new BlobStoreFactory(
  451. $services->getDBLoadBalancer(),
  452. $services->getMainWANObjectCache(),
  453. $services->getMainConfig(),
  454. $wgContLang
  455. );
  456. },
  457. 'BlobStore' => function ( MediaWikiServices $services ) {
  458. return $services->getService( '_SqlBlobStore' );
  459. },
  460. '_SqlBlobStore' => function ( MediaWikiServices $services ) {
  461. return $services->getBlobStoreFactory()->newSqlBlobStore();
  462. },
  463. 'ContentModelStore' => function ( MediaWikiServices $services ) {
  464. return new NameTableStore(
  465. $services->getDBLoadBalancer(),
  466. $services->getMainWANObjectCache(),
  467. LoggerFactory::getInstance( 'NameTableSqlStore' ),
  468. 'content_models',
  469. 'model_id',
  470. 'model_name'
  471. /**
  472. * No strtolower normalization is added to the service as there are examples of
  473. * extensions that do not stick to this assumption.
  474. * - extensions/examples/DataPages define( 'CONTENT_MODEL_XML_DATA','XML_DATA' );
  475. * - extensions/Scribunto define( 'CONTENT_MODEL_SCRIBUNTO', 'Scribunto' );
  476. */
  477. );
  478. },
  479. 'SlotRoleStore' => function ( MediaWikiServices $services ) {
  480. return new NameTableStore(
  481. $services->getDBLoadBalancer(),
  482. $services->getMainWANObjectCache(),
  483. LoggerFactory::getInstance( 'NameTableSqlStore' ),
  484. 'slot_roles',
  485. 'role_id',
  486. 'role_name',
  487. 'strtolower'
  488. );
  489. },
  490. 'PreferencesFactory' => function ( MediaWikiServices $services ) {
  491. global $wgContLang;
  492. $authManager = AuthManager::singleton();
  493. $linkRenderer = $services->getLinkRendererFactory()->create();
  494. $config = $services->getMainConfig();
  495. $factory = new DefaultPreferencesFactory( $config, $wgContLang, $authManager, $linkRenderer );
  496. $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) );
  497. return $factory;
  498. },
  499. 'HttpRequestFactory' => function ( MediaWikiServices $services ) {
  500. return new \MediaWiki\Http\HttpRequestFactory();
  501. },
  502. 'CommentStore' => function ( MediaWikiServices $services ) {
  503. global $wgContLang;
  504. return new CommentStore(
  505. $wgContLang,
  506. $services->getMainConfig()->get( 'CommentTableSchemaMigrationStage' )
  507. );
  508. },
  509. 'ActorMigration' => function ( MediaWikiServices $services ) {
  510. return new ActorMigration(
  511. $services->getMainConfig()->get( 'ActorTableSchemaMigrationStage' )
  512. );
  513. },
  514. ///////////////////////////////////////////////////////////////////////////
  515. // NOTE: When adding a service here, don't forget to add a getter function
  516. // in the MediaWikiServices class. The convenience getter should just call
  517. // $this->getService( 'FooBarService' ).
  518. ///////////////////////////////////////////////////////////////////////////
  519. ];