Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 2146
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2/**
3 * Service implementations for %MediaWiki core.
4 *
5 * This file returns the array loaded by the MediaWikiServices class
6 * for use through `MediaWiki\MediaWikiServices::getInstance()`
7 *
8 * @see [Dependency Injection](@ref dependencyinjection) in docs/Injection.md
9 * for the principles of DI and how to use it MediaWiki core.
10 *
11 * Reminder:
12 *
13 * - ServiceWiring is NOT a cache for arbitrary singletons.
14 *
15 * - Services MUST NOT vary their behaviour on global state, especially not
16 *   WebRequest, RequestContext (T218555), or other details of the current
17 *   request or CLI process (e.g. "current" user or title). Doing so may
18 *   cause a chain reaction and cause serious data corruption.
19 *
20 *   Refer to [DI Principles](@ref di-principles) in docs/Injection.md for
21 *   how and why we avoid this, as well as for limited exemptions to these
22 *   principles.
23 *
24 * -------
25 *
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License along
37 * with this program; if not, write to the Free Software Foundation, Inc.,
38 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
39 * http://www.gnu.org/copyleft/gpl.html
40 *
41 * @file
42 */
43
44use GuzzleHttp\Client;
45use GuzzleHttp\Psr7\HttpFactory;
46use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
47use MediaWiki\Actions\ActionFactory;
48use MediaWiki\Auth\AuthManager;
49use MediaWiki\Auth\Throttler;
50use MediaWiki\Block\AutoblockExemptionList;
51use MediaWiki\Block\BlockActionInfo;
52use MediaWiki\Block\BlockErrorFormatter;
53use MediaWiki\Block\BlockManager;
54use MediaWiki\Block\BlockPermissionCheckerFactory;
55use MediaWiki\Block\BlockRestrictionStore;
56use MediaWiki\Block\BlockRestrictionStoreFactory;
57use MediaWiki\Block\BlockUserFactory;
58use MediaWiki\Block\BlockUtils;
59use MediaWiki\Block\BlockUtilsFactory;
60use MediaWiki\Block\DatabaseBlock;
61use MediaWiki\Block\DatabaseBlockStore;
62use MediaWiki\Block\DatabaseBlockStoreFactory;
63use MediaWiki\Block\HideUserUtils;
64use MediaWiki\Block\UnblockUserFactory;
65use MediaWiki\Block\UserBlockCommandFactory;
66use MediaWiki\Cache\BacklinkCache;
67use MediaWiki\Cache\BacklinkCacheFactory;
68use MediaWiki\Cache\GenderCache;
69use MediaWiki\Cache\HTMLCacheUpdater;
70use MediaWiki\Cache\LinkBatchFactory;
71use MediaWiki\Cache\LinkCache;
72use MediaWiki\Cache\UserCache;
73use MediaWiki\Category\TrackingCategories;
74use MediaWiki\ChangeTags\ChangeTagsStore;
75use MediaWiki\Collation\CollationFactory;
76use MediaWiki\CommentFormatter\CommentFormatter;
77use MediaWiki\CommentFormatter\CommentParserFactory;
78use MediaWiki\CommentFormatter\RowCommentFormatter;
79use MediaWiki\CommentStore\CommentStore;
80use MediaWiki\Config\Config;
81use MediaWiki\Config\ConfigException;
82use MediaWiki\Config\ConfigFactory;
83use MediaWiki\Config\ConfigRepository;
84use MediaWiki\Config\ServiceOptions;
85use MediaWiki\Content\ContentHandlerFactory;
86use MediaWiki\Content\IContentHandlerFactory;
87use MediaWiki\Content\Renderer\ContentRenderer;
88use MediaWiki\Content\Transform\ContentTransformer;
89use MediaWiki\Context\RequestContext;
90use MediaWiki\DAO\WikiAwareEntity;
91use MediaWiki\Deferred\DeferredUpdates;
92use MediaWiki\DomainEvent\DomainEventDispatcher;
93use MediaWiki\DomainEvent\DomainEventSource;
94use MediaWiki\DomainEvent\EventDispatchEngine;
95use MediaWiki\Edit\ParsoidOutputStash;
96use MediaWiki\Edit\SimpleParsoidOutputStash;
97use MediaWiki\EditPage\Constraint\EditConstraintFactory;
98use MediaWiki\EditPage\IntroMessageBuilder;
99use MediaWiki\EditPage\PreloadedContentBuilder;
100use MediaWiki\EditPage\SpamChecker;
101use MediaWiki\Export\WikiExporterFactory;
102use MediaWiki\FileBackend\FileBackendGroup;
103use MediaWiki\FileBackend\FSFile\TempFSFileFactory;
104use MediaWiki\FileBackend\LockManager\LockManagerGroupFactory;
105use MediaWiki\HookContainer\FauxGlobalHookArray;
106use MediaWiki\HookContainer\HookContainer;
107use MediaWiki\HookContainer\HookRunner;
108use MediaWiki\HookContainer\StaticHookRegistry;
109use MediaWiki\Http\HttpRequestFactory;
110use MediaWiki\Http\Telemetry;
111use MediaWiki\Installer\Pingback;
112use MediaWiki\Interwiki\ClassicInterwikiLookup;
113use MediaWiki\Interwiki\InterwikiLookup;
114use MediaWiki\JobQueue\JobFactory;
115use MediaWiki\JobQueue\JobQueueGroupFactory;
116use MediaWiki\Json\JsonCodec;
117use MediaWiki\Language\FormatterFactory;
118use MediaWiki\Language\Language;
119use MediaWiki\Language\LanguageCode;
120use MediaWiki\Language\LazyLocalizationContext;
121use MediaWiki\Languages\LanguageConverterFactory;
122use MediaWiki\Languages\LanguageEventIngress;
123use MediaWiki\Languages\LanguageFactory;
124use MediaWiki\Languages\LanguageFallback;
125use MediaWiki\Languages\LanguageNameUtils;
126use MediaWiki\Linker\LinkRenderer;
127use MediaWiki\Linker\LinkRendererFactory;
128use MediaWiki\Linker\LinksMigration;
129use MediaWiki\Linker\LinkTargetLookup;
130use MediaWiki\Linker\LinkTargetStore;
131use MediaWiki\Logger\LoggerFactory;
132use MediaWiki\Mail\Emailer;
133use MediaWiki\Mail\EmailUser;
134use MediaWiki\Mail\EmailUserFactory;
135use MediaWiki\Mail\IEmailer;
136use MediaWiki\MainConfigNames;
137use MediaWiki\MediaWikiServices;
138use MediaWiki\Message\Message;
139use MediaWiki\Message\MessageFormatterFactory;
140use MediaWiki\OutputTransform\DefaultOutputPipelineFactory;
141use MediaWiki\OutputTransform\OutputTransformPipeline;
142use MediaWiki\Page\ContentModelChangeFactory;
143use MediaWiki\Page\DeletePageFactory;
144use MediaWiki\Page\File\BadFileLookup;
145use MediaWiki\Page\MergeHistoryFactory;
146use MediaWiki\Page\MovePageFactory;
147use MediaWiki\Page\PageCommandFactory;
148use MediaWiki\Page\PageProps;
149use MediaWiki\Page\PageStore;
150use MediaWiki\Page\PageStoreFactory;
151use MediaWiki\Page\ParserOutputAccess;
152use MediaWiki\Page\RedirectLookup;
153use MediaWiki\Page\RedirectStore;
154use MediaWiki\Page\RollbackPageFactory;
155use MediaWiki\Page\UndeletePageFactory;
156use MediaWiki\Page\WikiPageFactory;
157use MediaWiki\Parser\DateFormatterFactory;
158use MediaWiki\Parser\MagicWordFactory;
159use MediaWiki\Parser\Parser;
160use MediaWiki\Parser\ParserCache;
161use MediaWiki\Parser\ParserCacheFactory;
162use MediaWiki\Parser\ParserFactory;
163use MediaWiki\Parser\ParserObserver;
164use MediaWiki\Parser\Parsoid\Config\DataAccess as MWDataAccess;
165use MediaWiki\Parser\Parsoid\Config\PageConfigFactory as MWPageConfigFactory;
166use MediaWiki\Parser\Parsoid\Config\SiteConfig as MWSiteConfig;
167use MediaWiki\Parser\Parsoid\HtmlTransformFactory;
168use MediaWiki\Parser\Parsoid\LintErrorChecker;
169use MediaWiki\Parser\Parsoid\ParsoidParserFactory;
170use MediaWiki\Password\PasswordFactory;
171use MediaWiki\Permissions\GrantsInfo;
172use MediaWiki\Permissions\GrantsLocalization;
173use MediaWiki\Permissions\GroupPermissionsLookup;
174use MediaWiki\Permissions\PermissionManager;
175use MediaWiki\Permissions\RateLimiter;
176use MediaWiki\Permissions\RestrictionStore;
177use MediaWiki\PoolCounter\PoolCounterFactory;
178use MediaWiki\Preferences\DefaultPreferencesFactory;
179use MediaWiki\Preferences\PreferencesFactory;
180use MediaWiki\Preferences\SignatureValidator;
181use MediaWiki\Preferences\SignatureValidatorFactory;
182use MediaWiki\RecentChanges\ChangeTrackingEventIngress;
183use MediaWiki\Registration\ExtensionRegistry;
184use MediaWiki\RenameUser\RenameUserFactory;
185use MediaWiki\Request\ProxyLookup;
186use MediaWiki\Request\WebRequest;
187use MediaWiki\ResourceLoader\MessageBlobStore;
188use MediaWiki\ResourceLoader\ResourceLoader;
189use MediaWiki\ResourceLoader\ResourceLoaderEventIngress;
190use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory;
191use MediaWiki\Revision\ArchivedRevisionLookup;
192use MediaWiki\Revision\MainSlotRoleHandler;
193use MediaWiki\Revision\RevisionFactory;
194use MediaWiki\Revision\RevisionLookup;
195use MediaWiki\Revision\RevisionRenderer;
196use MediaWiki\Revision\RevisionStore;
197use MediaWiki\Revision\RevisionStoreFactory;
198use MediaWiki\Revision\SlotRecord;
199use MediaWiki\Revision\SlotRoleRegistry;
200use MediaWiki\Search\SearchEventIngress;
201use MediaWiki\Search\SearchResultThumbnailProvider;
202use MediaWiki\Search\TitleMatcher;
203use MediaWiki\Session\SessionManager;
204use MediaWiki\Settings\Config\ConfigSchema;
205use MediaWiki\Settings\SettingsBuilder;
206use MediaWiki\Shell\CommandFactory;
207use MediaWiki\Shell\ShellboxClientFactory;
208use MediaWiki\Site\CachingSiteStore;
209use MediaWiki\Site\DBSiteStore;
210use MediaWiki\Site\SiteLookup;
211use MediaWiki\Site\SiteStore;
212use MediaWiki\SpecialPage\SpecialPageFactory;
213use MediaWiki\Storage\BlobStore;
214use MediaWiki\Storage\BlobStoreFactory;
215use MediaWiki\Storage\EditResultCache;
216use MediaWiki\Storage\NameTableStore;
217use MediaWiki\Storage\NameTableStoreFactory;
218use MediaWiki\Storage\PageEditStash;
219use MediaWiki\Storage\PageUpdaterFactory;
220use MediaWiki\Storage\RevertedTagUpdateManager;
221use MediaWiki\Storage\SqlBlobStore;
222use MediaWiki\Telemetry\MediaWikiPropagator;
223use MediaWiki\Tidy\RemexDriver;
224use MediaWiki\Tidy\TidyDriverBase;
225use MediaWiki\Title\MediaWikiTitleCodec;
226use MediaWiki\Title\NamespaceInfo;
227use MediaWiki\Title\TitleFactory;
228use MediaWiki\Title\TitleFormatter;
229use MediaWiki\Title\TitleParser;
230use MediaWiki\User\ActorMigration;
231use MediaWiki\User\ActorNormalization;
232use MediaWiki\User\ActorStore;
233use MediaWiki\User\ActorStoreFactory;
234use MediaWiki\User\BotPasswordStore;
235use MediaWiki\User\CentralId\CentralIdLookup;
236use MediaWiki\User\CentralId\CentralIdLookupFactory;
237use MediaWiki\User\Options\ConditionalDefaultsLookup;
238use MediaWiki\User\Options\DefaultOptionsLookup;
239use MediaWiki\User\Options\UserOptionsLookup;
240use MediaWiki\User\Options\UserOptionsManager;
241use MediaWiki\User\PasswordReset;
242use MediaWiki\User\Registration\LocalUserRegistrationProvider;
243use MediaWiki\User\Registration\UserRegistrationLookup;
244use MediaWiki\User\TalkPageNotificationManager;
245use MediaWiki\User\TempUser\RealTempUserConfig;
246use MediaWiki\User\TempUser\TempUserCreator;
247use MediaWiki\User\UserEditTracker;
248use MediaWiki\User\UserFactory;
249use MediaWiki\User\UserGroupManager;
250use MediaWiki\User\UserGroupManagerFactory;
251use MediaWiki\User\UserIdentity;
252use MediaWiki\User\UserIdentityLookup;
253use MediaWiki\User\UserIdentityUtils;
254use MediaWiki\User\UserNamePrefixSearch;
255use MediaWiki\User\UserNameUtils;
256use MediaWiki\Utils\UrlUtils;
257use MediaWiki\Watchlist\NoWriteWatchedItemStore;
258use MediaWiki\Watchlist\WatchedItemQueryService;
259use MediaWiki\Watchlist\WatchedItemStore;
260use MediaWiki\Watchlist\WatchlistManager;
261use MediaWiki\WikiMap\WikiMap;
262use Psr\Http\Client\ClientInterface;
263use Wikimedia\DependencyStore\DependencyStore;
264use Wikimedia\EventRelayer\EventRelayerGroup;
265use Wikimedia\Message\IMessageFormatterFactory;
266use Wikimedia\Mime\MimeAnalyzer;
267use Wikimedia\ObjectCache\BagOStuff;
268use Wikimedia\ObjectCache\EmptyBagOStuff;
269use Wikimedia\ObjectCache\HashBagOStuff;
270use Wikimedia\ObjectCache\WANObjectCache;
271use Wikimedia\ObjectFactory\ObjectFactory;
272use Wikimedia\Parsoid\Config\DataAccess;
273use Wikimedia\Parsoid\Parsoid;
274use Wikimedia\Rdbms\ChronologyProtector;
275use Wikimedia\Rdbms\ConfiguredReadOnlyMode;
276use Wikimedia\Rdbms\DatabaseFactory;
277use Wikimedia\Rdbms\IConnectionProvider;
278use Wikimedia\Rdbms\ReadOnlyMode;
279use Wikimedia\RequestTimeout\CriticalSectionProvider;
280use Wikimedia\RequestTimeout\RequestTimeout;
281use Wikimedia\Stats\BufferingStatsdDataFactory;
282use Wikimedia\Stats\IBufferingStatsdDataFactory;
283use Wikimedia\Stats\PrefixingStatsdDataFactoryProxy;
284use Wikimedia\Stats\StatsCache;
285use Wikimedia\Stats\StatsFactory;
286use Wikimedia\Telemetry\Clock;
287use Wikimedia\Telemetry\CompositePropagator;
288use Wikimedia\Telemetry\NoopTracer;
289use Wikimedia\Telemetry\OtlpHttpExporter;
290use Wikimedia\Telemetry\ProbabilisticSampler;
291use Wikimedia\Telemetry\Tracer;
292use Wikimedia\Telemetry\TracerInterface;
293use Wikimedia\Telemetry\TracerState;
294use Wikimedia\Telemetry\W3CTraceContextPropagator;
295use Wikimedia\UUID\GlobalIdGenerator;
296use Wikimedia\WRStats\BagOStuffStatsStore;
297use Wikimedia\WRStats\WRStatsFactory;
298
299/** @phpcs-require-sorted-array */
300return [
301    'ActionFactory' => static function ( MediaWikiServices $services ): ActionFactory {
302        return new ActionFactory(
303            $services->getMainConfig()->get( MainConfigNames::Actions ),
304            LoggerFactory::getInstance( 'ActionFactory' ),
305            $services->getObjectFactory(),
306            $services->getHookContainer(),
307            $services->getContentHandlerFactory()
308        );
309    },
310
311    'ActorMigration' => static function ( MediaWikiServices $services ): ActorMigration {
312        return new ActorMigration(
313            $services->getActorStoreFactory()
314        );
315    },
316
317    'ActorNormalization' => static function ( MediaWikiServices $services ): ActorNormalization {
318        return $services->getActorStoreFactory()->getActorNormalization();
319    },
320
321    'ActorStore' => static function ( MediaWikiServices $services ): ActorStore {
322        return $services->getActorStoreFactory()->getActorStore();
323    },
324
325    'ActorStoreFactory' => static function ( MediaWikiServices $services ): ActorStoreFactory {
326        return new ActorStoreFactory(
327            new ServiceOptions( ActorStoreFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
328            $services->getDBLoadBalancerFactory(),
329            $services->getUserNameUtils(),
330            $services->getTempUserConfig(),
331            LoggerFactory::getInstance( 'ActorStore' ),
332            $services->getHideUserUtils()
333        );
334    },
335
336    'ArchivedRevisionLookup' => static function ( MediaWikiServices $services ): ArchivedRevisionLookup {
337        return new ArchivedRevisionLookup(
338            $services->getConnectionProvider(),
339            $services->getRevisionStore()
340        );
341    },
342
343    'AuthManager' => static function ( MediaWikiServices $services ): AuthManager {
344        $authManager = new AuthManager(
345            RequestContext::getMain()->getRequest(),
346            $services->getMainConfig(),
347            $services->getObjectFactory(),
348            $services->getHookContainer(),
349            $services->getReadOnlyMode(),
350            $services->getUserNameUtils(),
351            $services->getBlockManager(),
352            $services->getWatchlistManager(),
353            $services->getDBLoadBalancer(),
354            $services->getContentLanguage(),
355            $services->getLanguageConverterFactory(),
356            $services->getBotPasswordStore(),
357            $services->getUserFactory(),
358            $services->getUserIdentityLookup(),
359            $services->getUserOptionsManager()
360        );
361        $authManager->setLogger( LoggerFactory::getInstance( 'authentication' ) );
362        return $authManager;
363    },
364
365    'AutoblockExemptionList' => static function ( MediaWikiServices $services ): AutoblockExemptionList {
366        $messageFormatterFactory = new MessageFormatterFactory( Message::FORMAT_PLAIN );
367        return new AutoblockExemptionList(
368            LoggerFactory::getInstance( 'AutoblockExemptionList' ),
369            $messageFormatterFactory->getTextFormatter(
370                $services->getContentLanguageCode()->toString()
371            )
372        );
373    },
374
375    'BacklinkCacheFactory' => static function ( MediaWikiServices $services ): BacklinkCacheFactory {
376        return new BacklinkCacheFactory(
377            new ServiceOptions(
378                BacklinkCache::CONSTRUCTOR_OPTIONS,
379                $services->getMainConfig()
380            ),
381            $services->getLinksMigration(),
382            $services->getMainWANObjectCache(),
383            $services->getHookContainer(),
384            $services->getConnectionProvider(),
385            LoggerFactory::getInstance( 'BacklinkCache' )
386        );
387    },
388
389    'BadFileLookup' => static function ( MediaWikiServices $services ): BadFileLookup {
390        return new BadFileLookup(
391            static function () {
392                return wfMessage( 'bad_image_list' )->inContentLanguage()->plain();
393            },
394            $services->getLocalServerObjectCache(),
395            $services->getRepoGroup(),
396            $services->getTitleParser(),
397            $services->getHookContainer()
398        );
399    },
400
401    'BlobStore' => static function ( MediaWikiServices $services ): BlobStore {
402        return $services->getService( '_SqlBlobStore' );
403    },
404
405    'BlobStoreFactory' => static function ( MediaWikiServices $services ): BlobStoreFactory {
406        return new BlobStoreFactory(
407            $services->getDBLoadBalancerFactory(),
408            $services->getExternalStoreAccess(),
409            $services->getMainWANObjectCache(),
410            new ServiceOptions( BlobStoreFactory::CONSTRUCTOR_OPTIONS,
411                $services->getMainConfig() )
412        );
413    },
414
415    'BlockActionInfo' => static function ( MediaWikiServices $services ): BlockActionInfo {
416        return new BlockActionInfo( $services->getHookContainer() );
417    },
418
419    'BlockErrorFormatter' => static function ( MediaWikiServices $services ): BlockErrorFormatter {
420        return $services->getFormatterFactory()->getBlockErrorFormatter(
421            new LazyLocalizationContext( static function () {
422                return RequestContext::getMain();
423            } )
424        );
425    },
426
427    'BlockManager' => static function ( MediaWikiServices $services ): BlockManager {
428        return new BlockManager(
429            new ServiceOptions(
430                BlockManager::CONSTRUCTOR_OPTIONS,
431                $services->getMainConfig()
432            ),
433            $services->getUserFactory(),
434            $services->getUserIdentityUtils(),
435            LoggerFactory::getInstance( 'BlockManager' ),
436            $services->getHookContainer(),
437            $services->getDatabaseBlockStore(),
438            $services->getProxyLookup()
439        );
440    },
441
442    'BlockPermissionCheckerFactory' => static function (
443        MediaWikiServices $services
444    ): BlockPermissionCheckerFactory {
445        return new BlockPermissionCheckerFactory(
446            new ServiceOptions(
447                BlockPermissionCheckerFactory::CONSTRUCTOR_OPTIONS,
448                $services->getMainConfig()
449            ),
450            $services->getBlockUtils()
451        );
452    },
453
454    'BlockRestrictionStore' => static function ( MediaWikiServices $services ): BlockRestrictionStore {
455        return $services->getBlockRestrictionStoreFactory()->getBlockRestrictionStore( WikiAwareEntity::LOCAL );
456    },
457
458    'BlockRestrictionStoreFactory' => static function ( MediaWikiServices $services ): BlockRestrictionStoreFactory {
459        return new BlockRestrictionStoreFactory(
460            $services->getDBLoadBalancerFactory()
461        );
462    },
463
464    'BlockUserFactory' => static function ( MediaWikiServices $services ): BlockUserFactory {
465        return $services->getService( '_UserBlockCommandFactory' );
466    },
467
468    'BlockUtils' => static function ( MediaWikiServices $services ): BlockUtils {
469        return $services->getBlockUtilsFactory()->getBlockUtils();
470    },
471
472    'BlockUtilsFactory' => static function ( MediaWikiServices $services ): BlockUtilsFactory {
473        return new BlockUtilsFactory(
474            new ServiceOptions(
475                BlockUtilsFactory::CONSTRUCTOR_OPTIONS,
476                $services->getMainConfig()
477            ),
478            $services->getActorStoreFactory(),
479            $services->getUserNameUtils(),
480            $services->getDBLoadBalancerFactory()
481        );
482    },
483
484    'BotPasswordStore' => static function ( MediaWikiServices $services ): BotPasswordStore {
485        return new BotPasswordStore(
486            new ServiceOptions(
487                BotPasswordStore::CONSTRUCTOR_OPTIONS,
488                $services->getMainConfig()
489            ),
490            $services->getCentralIdLookup(),
491            $services->getDBLoadBalancerFactory()
492        );
493    },
494
495    'CentralIdLookup' => static function ( MediaWikiServices $services ): CentralIdLookup {
496        return $services->getCentralIdLookupFactory()->getLookup();
497    },
498
499    'CentralIdLookupFactory' => static function ( MediaWikiServices $services ): CentralIdLookupFactory {
500        return new CentralIdLookupFactory(
501            new ServiceOptions( CentralIdLookupFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
502            $services->getObjectFactory(),
503            $services->getUserIdentityLookup(),
504            $services->getUserFactory()
505        );
506    },
507
508    'ChangeTagDefStore' => static function ( MediaWikiServices $services ): NameTableStore {
509        return $services->getNameTableStoreFactory()->getChangeTagDef();
510    },
511
512    'ChangeTagsStore' => static function ( MediaWikiServices $services ): ChangeTagsStore {
513        return new ChangeTagsStore(
514            $services->getConnectionProvider(),
515            $services->getChangeTagDefStore(),
516            $services->getMainWANObjectCache(),
517            $services->getHookContainer(),
518            LoggerFactory::getInstance( 'ChangeTags' ),
519            $services->getUserFactory(),
520            new ServiceOptions(
521                ChangeTagsStore::CONSTRUCTOR_OPTIONS,
522                $services->getMainConfig()
523            )
524        );
525    },
526
527    'ChronologyProtector' => static function ( MediaWikiServices $services ): ChronologyProtector {
528        $mainConfig = $services->getMainConfig();
529        $microStashIsDatabase = $services->getObjectCacheFactory()->isDatabaseId(
530            $mainConfig->get( MainConfigNames::MicroStashType )
531        );
532        $cpStash = $microStashIsDatabase
533            ? new EmptyBagOStuff()
534            : $services->getMicroStash();
535
536        $chronologyProtector = new ChronologyProtector(
537            $cpStash,
538            $mainConfig->get( MainConfigNames::ChronologyProtectorSecret ),
539            MW_ENTRY_POINT === 'cli',
540            LoggerFactory::getInstance( 'rdbms' )
541        );
542
543        // Use the global WebRequest singleton. The main reason for using this
544        // is to call WebRequest::getIP() which is non-trivial to reproduce statically
545        // because it needs $wgUsePrivateIPs, as well as ProxyLookup and HookRunner services.
546        // TODO: Create a static version of WebRequest::getIP that accepts these three
547        // as dependencies, and then call that here. The other uses of $req below can
548        // trivially use $_COOKIES, $_GET and $_SERVER instead.
549        $req = RequestContext::getMain()->getRequest();
550
551        // Set user IP/agent information for agent session consistency purposes
552        $reqStart = (int)( $_SERVER['REQUEST_TIME_FLOAT'] ?? time() );
553        $cpPosInfo = ChronologyProtector::getCPInfoFromCookieValue(
554        // The cookie has no prefix and is set by MediaWiki::preOutputCommit()
555            $req->getCookie( 'cpPosIndex', '' ),
556            // Mitigate broken client-side cookie expiration handling (T190082)
557            $reqStart - ChronologyProtector::POSITION_COOKIE_TTL
558        );
559        $chronologyProtector->setRequestInfo( [
560            'IPAddress' => $req->getIP(),
561            'UserAgent' => $req->getHeader( 'User-Agent' ),
562            'ChronologyPositionIndex' => $req->getInt( 'cpPosIndex', $cpPosInfo['index'] ),
563            'ChronologyClientId' => $cpPosInfo['clientId'] ?? null,
564        ] );
565        return $chronologyProtector;
566    },
567
568    'CollationFactory' => static function ( MediaWikiServices $services ): CollationFactory {
569        return new CollationFactory(
570            new ServiceOptions(
571                CollationFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
572            $services->getObjectFactory(),
573            $services->getHookContainer()
574        );
575    },
576
577    'CommentFormatter' => static function ( MediaWikiServices $services ): CommentFormatter {
578        return new CommentFormatter(
579            $services->getCommentParserFactory()
580        );
581    },
582
583    'CommentParserFactory' => static function ( MediaWikiServices $services ): CommentParserFactory {
584        return new CommentParserFactory(
585            $services->getLinkRendererFactory()->create( [ 'renderForComment' => true ] ),
586            $services->getLinkBatchFactory(),
587            $services->getLinkCache(),
588            $services->getRepoGroup(),
589            RequestContext::getMain()->getLanguage(),
590            $services->getContentLanguage(),
591            $services->getTitleParser(),
592            $services->getNamespaceInfo(),
593            $services->getHookContainer()
594        );
595    },
596
597    'CommentStore' => static function ( MediaWikiServices $services ): CommentStore {
598        return new CommentStore( $services->getContentLanguage() );
599    },
600
601    'ConfigFactory' => static function ( MediaWikiServices $services ): ConfigFactory {
602        // Use the bootstrap config to initialize the ConfigFactory.
603        $registry = $services->getBootstrapConfig()->get( MainConfigNames::ConfigRegistry );
604        $factory = new ConfigFactory();
605
606        foreach ( $registry as $name => $callback ) {
607            $factory->register( $name, $callback );
608        }
609        return $factory;
610    },
611
612    'ConfigRepository' => static function ( MediaWikiServices $services ): ConfigRepository {
613        return new ConfigRepository( $services->getConfigFactory() );
614    },
615
616    'ConfigSchema' => static function ( MediaWikiServices $services ): ConfigSchema {
617        /** @var SettingsBuilder $settings */
618        $settings = $services->get( '_SettingsBuilder' );
619        return $settings->getConfigSchema();
620    },
621
622    'ConfiguredReadOnlyMode' => static function ( MediaWikiServices $services ): ConfiguredReadOnlyMode {
623        $config = $services->getMainConfig();
624        return new ConfiguredReadOnlyMode(
625            $config->get( MainConfigNames::ReadOnly ),
626            $config->get( MainConfigNames::ReadOnlyFile )
627        );
628    },
629
630    'ConnectionProvider' => static function ( MediaWikiServices $services ): IConnectionProvider {
631        return $services->getDBLoadBalancerFactory();
632    },
633
634    'ContentHandlerFactory' => static function ( MediaWikiServices $services ): IContentHandlerFactory {
635        $contentHandlerConfig = $services->getMainConfig()->get( MainConfigNames::ContentHandlers );
636
637        return new ContentHandlerFactory(
638            $contentHandlerConfig,
639            $services->getObjectFactory(),
640            $services->getHookContainer(),
641            LoggerFactory::getInstance( 'ContentHandler' )
642        );
643    },
644
645    'ContentLanguage' => static function ( MediaWikiServices $services ): Language {
646        return $services->getLanguageFactory()->getLanguage(
647            $services->getMainConfig()->get( MainConfigNames::LanguageCode ) );
648    },
649
650    'ContentLanguageCode' => static function ( MediaWikiServices $services ): LanguageCode {
651        return $services->getLanguageFactory()->getLanguageCode(
652            $services->getMainConfig()->get( MainConfigNames::LanguageCode ) );
653    },
654
655    'ContentModelChangeFactory' => static function ( MediaWikiServices $services ): ContentModelChangeFactory {
656        return $services->getService( '_PageCommandFactory' );
657    },
658
659    'ContentModelStore' => static function ( MediaWikiServices $services ): NameTableStore {
660        return $services->getNameTableStoreFactory()->getContentModels();
661    },
662
663    'ContentRenderer' => static function ( MediaWikiServices $services ): ContentRenderer {
664        return new ContentRenderer(
665            $services->getContentHandlerFactory(),
666            $services->getGlobalIdGenerator()
667        );
668    },
669
670    'ContentTransformer' => static function ( MediaWikiServices $services ): ContentTransformer {
671        return new ContentTransformer( $services->getContentHandlerFactory() );
672    },
673
674    'CriticalSectionProvider' => static function ( MediaWikiServices $services ): CriticalSectionProvider {
675        $config = $services->getMainConfig();
676        $limit = MW_ENTRY_POINT === 'cli' ? INF : $config->get( MainConfigNames::CriticalSectionTimeLimit );
677        return RequestTimeout::singleton()->createCriticalSectionProvider( $limit );
678    },
679
680    'DatabaseBlockStore' => static function ( MediaWikiServices $services ): DatabaseBlockStore {
681        return $services->getDatabaseBlockStoreFactory()->getDatabaseBlockStore( DatabaseBlock::LOCAL );
682    },
683
684    'DatabaseBlockStoreFactory' => static function ( MediaWikiServices $services ): DatabaseBlockStoreFactory {
685        return new DatabaseBlockStoreFactory(
686            new ServiceOptions(
687                DatabaseBlockStoreFactory::CONSTRUCTOR_OPTIONS,
688                $services->getMainConfig()
689            ),
690            LoggerFactory::getInstance( 'DatabaseBlockStore' ),
691            $services->getActorStoreFactory(),
692            $services->getBlockRestrictionStoreFactory(),
693            $services->getCommentStore(),
694            $services->getHookContainer(),
695            $services->getDBLoadBalancerFactory(),
696            $services->getReadOnlyMode(),
697            $services->getUserFactory(),
698            $services->getTempUserConfig(),
699            $services->getBlockUtilsFactory(),
700            $services->getAutoblockExemptionList()
701        );
702    },
703
704    'DatabaseFactory' => static function ( MediaWikiServices $services ): DatabaseFactory {
705        return new DatabaseFactory(
706            [
707                'debugSql' => $services->getMainConfig()->get( MainConfigNames::DebugDumpSql ),
708                'tracer' => $services->getTracer(),
709            ]
710        );
711    },
712
713    'DateFormatterFactory' => static function ( MediaWikiServices $services ): DateFormatterFactory {
714        return new DateFormatterFactory();
715    },
716
717    'DBLoadBalancer' => static function ( MediaWikiServices $services ): Wikimedia\Rdbms\ILoadBalancer {
718        // just return the default LB from the DBLoadBalancerFactory service
719        return $services->getDBLoadBalancerFactory()->getMainLB();
720    },
721
722    'DBLoadBalancerFactory' => static function ( MediaWikiServices $services ): Wikimedia\Rdbms\LBFactory {
723        $mainConfig = $services->getMainConfig();
724        $lbFactoryConfigBuilder = $services->getDBLoadBalancerFactoryConfigBuilder();
725
726        $lbConf = $lbFactoryConfigBuilder->applyDefaultConfig(
727            $mainConfig->get( MainConfigNames::LBFactoryConf )
728        );
729
730        $class = $lbFactoryConfigBuilder->getLBFactoryClass( $lbConf );
731        $instance = new $class( $lbConf );
732
733        $lbFactoryConfigBuilder->setDomainAliases( $instance );
734
735        return $instance;
736    },
737
738    'DBLoadBalancerFactoryConfigBuilder' => static function ( MediaWikiServices $services ): MWLBFactory {
739        $mainConfig = $services->getMainConfig();
740        if ( $services->getObjectCacheFactory()->isDatabaseId(
741            $mainConfig->get( MainConfigNames::MainCacheType )
742        ) ) {
743            $wanCache = WANObjectCache::newEmpty();
744        } else {
745            $wanCache = $services->getMainWANObjectCache();
746        }
747        $srvCache = $services->getLocalServerObjectCache();
748        if ( $srvCache instanceof EmptyBagOStuff ) {
749            // Use process cache if no APCU or other local-server cache (e.g. on CLI)
750            $srvCache = new HashBagOStuff( [ 'maxKeys' => 100 ] );
751        }
752
753        return new MWLBFactory(
754            new ServiceOptions( MWLBFactory::APPLY_DEFAULT_CONFIG_OPTIONS, $services->getMainConfig() ),
755            new ConfiguredReadOnlyMode(
756                $mainConfig->get( MainConfigNames::ReadOnly ),
757                $mainConfig->get( MainConfigNames::ReadOnlyFile )
758            ),
759            $services->getChronologyProtector(),
760            $srvCache,
761            $wanCache,
762            $services->getCriticalSectionProvider(),
763            $services->getStatsdDataFactory(),
764            ExtensionRegistry::getInstance()->getAttribute( 'DatabaseVirtualDomains' ),
765            $services->getTracer(),
766        );
767    },
768
769    'DefaultOutputPipeline' => static function ( MediaWikiServices $services ): OutputTransformPipeline {
770        return ( new DefaultOutputPipelineFactory(
771            new ServiceOptions(
772                DefaultOutputPipelineFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig()
773            ),
774            $services->getMainConfig(),
775            LoggerFactory::getInstance( 'Parser' ),
776            $services->getObjectFactory()
777        ) )->buildPipeline();
778    },
779
780    'DeletePageFactory' => static function ( MediaWikiServices $services ): DeletePageFactory {
781        return $services->getService( '_PageCommandFactory' );
782    },
783
784    'DomainEventDispatcher' => static function ( MediaWikiServices $services ): DomainEventDispatcher {
785        return $services->getService( '_DomainEventDispatcher' );
786    },
787
788    'DomainEventSource' => static function ( MediaWikiServices $services ): DomainEventSource {
789        return $services->getService( '_DomainEventDispatcher' );
790    },
791
792    'Emailer' => static function ( MediaWikiServices $services ): IEmailer {
793        return new Emailer();
794    },
795
796    'EmailUserFactory' => static function ( MediaWikiServices $services ): EmailUserFactory {
797        return new EmailUserFactory(
798            new ServiceOptions( EmailUser::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
799            $services->getHookContainer(),
800            $services->getUserOptionsLookup(),
801            $services->getCentralIdLookup(),
802            $services->getUserFactory(),
803            $services->getEmailer(),
804            $services->getMessageFormatterFactory(),
805            $services->getMessageFormatterFactory()->getTextFormatter(
806                $services->getContentLanguageCode()->toString()
807            )
808        );
809    },
810
811    'EventRelayerGroup' => static function ( MediaWikiServices $services ): EventRelayerGroup {
812        return new EventRelayerGroup( $services->getMainConfig()->get( MainConfigNames::EventRelayerConfig ) );
813    },
814
815    'ExtensionRegistry' => static function ( MediaWikiServices $services ): ExtensionRegistry {
816        return ExtensionRegistry::getInstance();
817    },
818
819    'ExternalStoreAccess' => static function ( MediaWikiServices $services ): ExternalStoreAccess {
820        return new ExternalStoreAccess(
821            $services->getExternalStoreFactory(),
822            LoggerFactory::getInstance( 'ExternalStore' )
823        );
824    },
825
826    'ExternalStoreFactory' => static function ( MediaWikiServices $services ): ExternalStoreFactory {
827        $config = $services->getMainConfig();
828        $writeStores = $config->get( MainConfigNames::DefaultExternalStore );
829
830        return new ExternalStoreFactory(
831            $config->get( MainConfigNames::ExternalStores ),
832            ( $writeStores !== false ) ? (array)$writeStores : [],
833            $services->getDBLoadBalancer()->getLocalDomainID(),
834            LoggerFactory::getInstance( 'ExternalStore' )
835        );
836    },
837
838    'FileBackendGroup' => static function ( MediaWikiServices $services ): FileBackendGroup {
839        $mainConfig = $services->getMainConfig();
840
841        $ld = WikiMap::getCurrentWikiDbDomain();
842        $fallbackWikiId = WikiMap::getWikiIdFromDbDomain( $ld );
843        // If the local wiki ID and local domain ID do not match, probably due to a non-default
844        // schema, issue a warning. A non-default schema indicates that it might be used to
845        // disambiguate different wikis.
846        $legacyDomainId = strlen( $ld->getTablePrefix() )
847            ? "{$ld->getDatabase()}-{$ld->getTablePrefix()}"
848            : $ld->getDatabase();
849        if ( $ld->getSchema() !== null && $legacyDomainId !== $fallbackWikiId ) {
850            wfWarn(
851                "Legacy default 'domainId' is '$legacyDomainId' but wiki ID is '$fallbackWikiId'."
852            );
853        }
854
855        $cache = $services->getLocalServerObjectCache();
856        if ( $cache instanceof EmptyBagOStuff ) {
857            $cache = new HashBagOStuff();
858        }
859
860        return new FileBackendGroup(
861            new ServiceOptions( FileBackendGroup::CONSTRUCTOR_OPTIONS, $mainConfig,
862                [ 'fallbackWikiId' => $fallbackWikiId ] ),
863            $services->getReadOnlyMode(),
864            $cache,
865            $services->getMainWANObjectCache(),
866            $services->getMimeAnalyzer(),
867            $services->getLockManagerGroupFactory(),
868            $services->getTempFSFileFactory(),
869            $services->getObjectFactory()
870        );
871    },
872
873    'FormatterFactory' => static function ( MediaWikiServices $services ): FormatterFactory {
874        return new FormatterFactory(
875            $services->getMessageCache(),
876            $services->getTitleFormatter(),
877            $services->getHookContainer(),
878            $services->getUserIdentityUtils(),
879            $services->getLanguageFactory(),
880            LoggerFactory::getInstance( 'status' )
881        );
882    },
883
884    'GenderCache' => static function ( MediaWikiServices $services ): GenderCache {
885        $nsInfo = $services->getNamespaceInfo();
886        // Database layer may be disabled, so processing without database connection
887        $dbLoadBalancer = $services->isServiceDisabled( 'DBLoadBalancer' )
888            ? null
889            : $services->getDBLoadBalancerFactory();
890        return new GenderCache( $nsInfo, $dbLoadBalancer, $services->get( '_DefaultOptionsLookup' ) );
891    },
892
893    'GlobalIdGenerator' => static function ( MediaWikiServices $services ): GlobalIdGenerator {
894        $mainConfig = $services->getMainConfig();
895
896        return new GlobalIdGenerator(
897            $mainConfig->get( MainConfigNames::TmpDirectory ),
898            static function ( $command ) {
899                return wfShellExec( $command );
900            }
901        );
902    },
903
904    'GrantsInfo' => static function ( MediaWikiServices $services ): GrantsInfo {
905        return new GrantsInfo(
906            new ServiceOptions(
907                GrantsInfo::CONSTRUCTOR_OPTIONS,
908                $services->getMainConfig()
909            )
910        );
911    },
912
913    'GrantsLocalization' => static function ( MediaWikiServices $services ): GrantsLocalization {
914        return new GrantsLocalization(
915            $services->getGrantsInfo(),
916            $services->getLinkRenderer(),
917            $services->getLanguageFactory(),
918            $services->getContentLanguage()
919        );
920    },
921
922    'GroupPermissionsLookup' => static function ( MediaWikiServices $services ): GroupPermissionsLookup {
923        return new GroupPermissionsLookup(
924            new ServiceOptions( GroupPermissionsLookup::CONSTRUCTOR_OPTIONS, $services->getMainConfig() )
925        );
926    },
927
928    'HideUserUtils' => static function ( MediaWikiServices $services ): HideUserUtils {
929        return new HideUserUtils();
930    },
931
932    'HookContainer' => static function ( MediaWikiServices $services ): HookContainer {
933        // NOTE: This is called while $services is being initialized, in order to call the
934        //       MediaWikiServices hook.
935
936        $configHooks = $services->getBootstrapConfig()->get( MainConfigNames::Hooks );
937
938        // If we are instantiating this service after $wgHooks was replaced by a fake,
939        // get the original array out of the object. This should only happen in the installer,
940        // when it calls resetMediaWikiServices().
941        if ( $configHooks instanceof FauxGlobalHookArray ) {
942            $configHooks = $configHooks->getOriginalArray();
943        }
944
945        $extRegistry = ExtensionRegistry::getInstance();
946        $extHooks = $extRegistry->getAttribute( 'Hooks' );
947        $extDeprecatedHooks = $extRegistry->getAttribute( 'DeprecatedHooks' );
948
949        $hookRegistry = new StaticHookRegistry( $configHooks, $extHooks, $extDeprecatedHooks );
950        $hookContainer = new HookContainer(
951            $hookRegistry,
952            $services->getObjectFactory()
953        );
954
955        return $hookContainer;
956    },
957
958    'HtmlCacheUpdater' => static function ( MediaWikiServices $services ): HTMLCacheUpdater {
959        $config = $services->getMainConfig();
960
961        return new HTMLCacheUpdater(
962            $services->getHookContainer(),
963            $services->getTitleFactory(),
964            $config->get( MainConfigNames::CdnReboundPurgeDelay ),
965            $config->get( MainConfigNames::UseFileCache ),
966            $config->get( MainConfigNames::CdnMaxAge )
967        );
968    },
969
970    'HtmlTransformFactory' => static function ( MediaWikiServices $services ): HtmlTransformFactory {
971        return new HtmlTransformFactory(
972            $services->getService( '_Parsoid' ),
973            $services->getMainConfig()->get( MainConfigNames::ParsoidSettings ),
974            $services->getParsoidPageConfigFactory(),
975            $services->getContentHandlerFactory(),
976            $services->getParsoidSiteConfig(),
977            $services->getTitleFactory(),
978            $services->getLanguageConverterFactory(),
979            $services->getLanguageFactory()
980        );
981    },
982
983    'HttpRequestFactory' => static function ( MediaWikiServices $services ): HttpRequestFactory {
984        return new HttpRequestFactory(
985            new ServiceOptions(
986                HttpRequestFactory::CONSTRUCTOR_OPTIONS,
987                $services->getMainConfig()
988            ),
989            LoggerFactory::getInstance( 'http' ),
990            $services->getTracer()
991        );
992    },
993
994    'InterwikiLookup' => static function ( MediaWikiServices $services ): InterwikiLookup {
995        return new ClassicInterwikiLookup(
996            new ServiceOptions(
997                ClassicInterwikiLookup::CONSTRUCTOR_OPTIONS,
998                $services->getMainConfig(),
999                [ 'wikiId' => WikiMap::getCurrentWikiId() ]
1000            ),
1001            $services->getContentLanguage(),
1002            $services->getMainWANObjectCache(),
1003            $services->getHookContainer(),
1004            $services->getConnectionProvider(),
1005            $services->getLanguageNameUtils()
1006        );
1007    },
1008
1009    'IntroMessageBuilder' => static function ( MediaWikiServices $services ): IntroMessageBuilder {
1010        return new IntroMessageBuilder(
1011            $services->getMainConfig(),
1012            $services->getLinkRenderer(),
1013            $services->getPermissionManager(),
1014            $services->getUserNameUtils(),
1015            $services->getTempUserCreator(),
1016            $services->getUserFactory(),
1017            $services->getRestrictionStore(),
1018            $services->getDatabaseBlockStore(),
1019            $services->getReadOnlyMode(),
1020            $services->getSpecialPageFactory(),
1021            $services->getRepoGroup(),
1022            $services->getNamespaceInfo(),
1023            $services->getSkinFactory(),
1024            $services->getConnectionProvider(),
1025            $services->getUrlUtils()
1026        );
1027    },
1028
1029    'JobFactory' => static function ( MediaWikiServices $services ): JobFactory {
1030        return new JobFactory(
1031            $services->getObjectFactory(),
1032            $services->getMainConfig()->get( MainConfigNames::JobClasses )
1033        );
1034    },
1035
1036    'JobQueueGroup' => static function ( MediaWikiServices $services ): JobQueueGroup {
1037        return $services->getJobQueueGroupFactory()->makeJobQueueGroup();
1038    },
1039
1040    'JobQueueGroupFactory' => static function ( MediaWikiServices $services ): JobQueueGroupFactory {
1041        return new JobQueueGroupFactory(
1042            new ServiceOptions( JobQueueGroupFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1043            $services->getReadOnlyMode(),
1044            $services->getStatsdDataFactory(),
1045            $services->getMainWANObjectCache(),
1046            $services->getGlobalIdGenerator()
1047        );
1048    },
1049
1050    'JobRunner' => static function ( MediaWikiServices $services ): JobRunner {
1051        return new JobRunner(
1052            new ServiceOptions( JobRunner::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1053            $services->getDBLoadBalancerFactory(),
1054            $services->getJobQueueGroup(),
1055            $services->getReadOnlyMode(),
1056            $services->getLinkCache(),
1057            $services->getStatsdDataFactory(),
1058            LoggerFactory::getInstance( 'runJobs' )
1059        );
1060    },
1061
1062    'JsonCodec' => static function ( MediaWikiServices $services ): JsonCodec {
1063        return new JsonCodec( $services );
1064    },
1065
1066    'LanguageConverterFactory' => static function ( MediaWikiServices $services ): LanguageConverterFactory {
1067        return new LanguageConverterFactory(
1068            new ServiceOptions( LanguageConverterFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1069            $services->getObjectFactory(),
1070            static function () use ( $services ) {
1071                return $services->getContentLanguage();
1072            }
1073        );
1074    },
1075
1076    'LanguageFactory' => static function ( MediaWikiServices $services ): LanguageFactory {
1077        return new LanguageFactory(
1078            new ServiceOptions( LanguageFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1079            $services->getNamespaceInfo(),
1080            $services->getLocalisationCache(),
1081            $services->getLanguageNameUtils(),
1082            $services->getLanguageFallback(),
1083            $services->getLanguageConverterFactory(),
1084            $services->getHookContainer(),
1085            $services->getMainConfig()
1086        );
1087    },
1088
1089    'LanguageFallback' => static function ( MediaWikiServices $services ): LanguageFallback {
1090        return new LanguageFallback(
1091            $services->getMainConfig()->get( MainConfigNames::LanguageCode ),
1092            $services->getLocalisationCache(),
1093            $services->getLanguageNameUtils()
1094        );
1095    },
1096
1097    'LanguageNameUtils' => static function ( MediaWikiServices $services ): LanguageNameUtils {
1098        return new LanguageNameUtils(
1099            new ServiceOptions(
1100                LanguageNameUtils::CONSTRUCTOR_OPTIONS,
1101                $services->getMainConfig()
1102            ),
1103            $services->getHookContainer()
1104        );
1105    },
1106
1107    'LinkBatchFactory' => static function ( MediaWikiServices $services ): LinkBatchFactory {
1108        return new LinkBatchFactory(
1109            $services->getLinkCache(),
1110            $services->getTitleFormatter(),
1111            $services->getContentLanguage(),
1112            $services->getGenderCache(),
1113            $services->getConnectionProvider(),
1114            $services->getLinksMigration(),
1115            LoggerFactory::getInstance( 'LinkBatch' )
1116        );
1117    },
1118
1119    'LinkCache' => static function ( MediaWikiServices $services ): LinkCache {
1120        // Database layer may be disabled, so processing without database connection
1121        $dbLoadBalancer = $services->isServiceDisabled( 'DBLoadBalancer' )
1122            ? null
1123            : $services->getDBLoadBalancer();
1124        $linkCache = new LinkCache(
1125            $services->getTitleFormatter(),
1126            $services->getMainWANObjectCache(),
1127            $services->getNamespaceInfo(),
1128            $dbLoadBalancer
1129        );
1130        $linkCache->setLogger( LoggerFactory::getInstance( 'LinkCache' ) );
1131        return $linkCache;
1132    },
1133
1134    'LinkRenderer' => static function ( MediaWikiServices $services ): LinkRenderer {
1135        return $services->getLinkRendererFactory()->create();
1136    },
1137
1138    'LinkRendererFactory' => static function ( MediaWikiServices $services ): LinkRendererFactory {
1139        return new LinkRendererFactory(
1140            $services->getTitleFormatter(),
1141            $services->getLinkCache(),
1142            $services->getSpecialPageFactory(),
1143            $services->getHookContainer()
1144        );
1145    },
1146
1147    'LinksMigration' => static function ( MediaWikiServices $services ): LinksMigration {
1148        return new LinksMigration(
1149            $services->getMainConfig(),
1150            $services->getLinkTargetLookup()
1151        );
1152    },
1153
1154    'LinkTargetLookup' => static function ( MediaWikiServices $services ): LinkTargetLookup {
1155        return new LinkTargetStore(
1156            $services->getConnectionProvider(),
1157            $services->getLocalServerObjectCache(),
1158            $services->getMainWANObjectCache()
1159        );
1160    },
1161
1162    'LintErrorChecker' => static function ( MediaWikiServices $services ): LintErrorChecker {
1163        return new LintErrorChecker(
1164            $services->get( '_Parsoid' ),
1165            $services->getParsoidPageConfigFactory(),
1166            $services->getTitleFactory(),
1167            ExtensionRegistry::getInstance(),
1168            $services->getMainConfig(),
1169         );
1170    },
1171
1172    'LocalisationCache' => static function ( MediaWikiServices $services ): LocalisationCache {
1173        $conf = $services->getMainConfig()->get( MainConfigNames::LocalisationCacheConf );
1174
1175        $logger = LoggerFactory::getInstance( 'localisation' );
1176
1177        $store = LocalisationCache::getStoreFromConf(
1178            $conf, $services->getMainConfig()->get( MainConfigNames::CacheDirectory ) );
1179        $logger->debug( 'LocalisationCache using store ' . get_class( $store ) );
1180
1181        return new $conf['class'](
1182            new ServiceOptions(
1183                LocalisationCache::CONSTRUCTOR_OPTIONS,
1184                // Two of the options are stored in $wgLocalisationCacheConf
1185                $conf,
1186                // In case someone set that config variable and didn't reset all keys, set defaults.
1187                [
1188                    'forceRecache' => false,
1189                    'manualRecache' => false,
1190                ],
1191                // Some other options come from config itself
1192                $services->getMainConfig()
1193            ),
1194            $store,
1195            $logger,
1196            [ static function () use ( $services ) {
1197                // NOTE: Make sure we use the same cache object that is assigned in the
1198                // constructor of the MessageBlobStore class used by ResourceLoader.
1199                // T231866: Avoid circular dependency via ResourceLoader.
1200                MessageBlobStore::clearGlobalCacheEntry( $services->getMainWANObjectCache() );
1201            } ],
1202            $services->getLanguageNameUtils(),
1203            $services->getHookContainer()
1204        );
1205    },
1206
1207    'LocalServerObjectCache' => static function ( MediaWikiServices $services ): BagOStuff {
1208        return $services->getObjectCacheFactory()->getInstance( CACHE_ACCEL );
1209    },
1210
1211    'LockManagerGroupFactory' => static function ( MediaWikiServices $services ): LockManagerGroupFactory {
1212        return new LockManagerGroupFactory(
1213            WikiMap::getCurrentWikiDbDomain()->getId(),
1214            $services->getMainConfig()->get( MainConfigNames::LockManagers )
1215        );
1216    },
1217
1218    'LogFormatterFactory' => static function ( MediaWikiServices $services ): LogFormatterFactory {
1219        return new LogFormatterFactory(
1220            new ServiceOptions( LogFormatterFactory::SERVICE_OPTIONS, $services->getMainConfig() ),
1221            $services->getObjectFactory(),
1222            $services->getHookContainer(),
1223            $services->getLinkRenderer(),
1224            $services->getContentLanguage(),
1225            $services->getCommentFormatter(),
1226            $services->getUserEditTracker()
1227        );
1228    },
1229
1230    'MagicWordFactory' => static function ( MediaWikiServices $services ): MagicWordFactory {
1231        return new MagicWordFactory(
1232            $services->getContentLanguage(),
1233            $services->getHookContainer()
1234        );
1235    },
1236
1237    'MainConfig' => static function ( MediaWikiServices $services ): Config {
1238        // Use the 'main' config from the ConfigFactory service.
1239        return $services->getConfigFactory()->makeConfig( 'main' );
1240    },
1241
1242    'MainObjectStash' => static function ( MediaWikiServices $services ): BagOStuff {
1243        $mainConfig = $services->getMainConfig();
1244
1245        $id = $mainConfig->get( MainConfigNames::MainStash );
1246        $store = $services->getObjectCacheFactory()->getInstance( $id );
1247        $store->getLogger()->debug( 'MainObjectStash using store {class}', [
1248            'class' => get_class( $store )
1249        ] );
1250
1251        return $store;
1252    },
1253
1254    'MainWANObjectCache' => static function ( MediaWikiServices $services ): WANObjectCache {
1255        $mainConfig = $services->getMainConfig();
1256
1257        $store = $services->getObjectCacheFactory()->getLocalClusterInstance();
1258        $logger = $store->getLogger();
1259        $logger->debug( 'MainWANObjectCache using store {class}', [
1260            'class' => get_class( $store )
1261        ] );
1262
1263        $wanParams = $mainConfig->get( MainConfigNames::WANObjectCache ) + [
1264            'cache' => $store,
1265            'logger' => $logger,
1266            'tracer' => $services->getTracer(),
1267            'secret' => $mainConfig->get( MainConfigNames::SecretKey ),
1268        ];
1269        if ( MW_ENTRY_POINT !== 'cli' ) {
1270            // Send the statsd data post-send on HTTP requests; avoid in CLI mode (T181385)
1271            $wanParams['stats'] = $services->getStatsFactory();
1272            // Let pre-emptive refreshes happen post-send on HTTP requests
1273            $wanParams['asyncHandler'] = [ DeferredUpdates::class, 'addCallableUpdate' ];
1274        }
1275        return new WANObjectCache( $wanParams );
1276    },
1277
1278    'MediaHandlerFactory' => static function ( MediaWikiServices $services ): MediaHandlerFactory {
1279        return new MediaHandlerFactory(
1280            LoggerFactory::getInstance( 'MediaHandlerFactory' ),
1281            $services->getMainConfig()->get( MainConfigNames::MediaHandlers )
1282        );
1283    },
1284
1285    'MergeHistoryFactory' => static function ( MediaWikiServices $services ): MergeHistoryFactory {
1286        return $services->getService( '_PageCommandFactory' );
1287    },
1288
1289    'MessageCache' => static function ( MediaWikiServices $services ): MessageCache {
1290        $mainConfig = $services->getMainConfig();
1291        $clusterCache = $services->getObjectCacheFactory()
1292            ->getInstance( $mainConfig->get( MainConfigNames::MessageCacheType ) );
1293        $srvCache = $mainConfig->get( MainConfigNames::UseLocalMessageCache )
1294            ? $services->getLocalServerObjectCache()
1295            : new EmptyBagOStuff();
1296
1297        $logger = LoggerFactory::getInstance( 'MessageCache' );
1298        $logger->debug( 'MessageCache using store {class}', [
1299            'class' => get_class( $clusterCache )
1300        ] );
1301
1302        $options = new ServiceOptions( MessageCache::CONSTRUCTOR_OPTIONS, $mainConfig );
1303
1304        return new MessageCache(
1305            $services->getMainWANObjectCache(),
1306            $clusterCache,
1307            $srvCache,
1308            $services->getContentLanguage(),
1309            $services->getLanguageConverterFactory(),
1310            $logger,
1311            $options,
1312            $services->getLanguageFactory(),
1313            $services->getLocalisationCache(),
1314            $services->getLanguageNameUtils(),
1315            $services->getLanguageFallback(),
1316            $services->getHookContainer(),
1317            $services->getParserFactory()
1318        );
1319    },
1320
1321    'MessageFormatterFactory' => static function ( MediaWikiServices $services ): IMessageFormatterFactory {
1322        return new MessageFormatterFactory();
1323    },
1324
1325    'MicroStash' => static function ( MediaWikiServices $services ): BagOStuff {
1326        $mainConfig = $services->getMainConfig();
1327
1328        $id = $mainConfig->get( MainConfigNames::MicroStashType );
1329        $store = $services->getObjectCacheFactory()->getInstance( $id );
1330
1331        $store->getLogger()->debug( 'MicroStash using store {class}', [
1332            'class' => get_class( $store )
1333        ] );
1334
1335        return $store;
1336    },
1337
1338    'MimeAnalyzer' => static function ( MediaWikiServices $services ): MimeAnalyzer {
1339        $logger = LoggerFactory::getInstance( 'Mime' );
1340        $mainConfig = $services->getMainConfig();
1341        $hookRunner = new HookRunner( $services->getHookContainer() );
1342        $params = [
1343            'typeFile' => $mainConfig->get( MainConfigNames::MimeTypeFile ),
1344            'infoFile' => $mainConfig->get( MainConfigNames::MimeInfoFile ),
1345            'xmlTypes' => $mainConfig->get( MainConfigNames::XMLMimeTypes ),
1346            'guessCallback' => static function (
1347                $mimeAnalyzer, &$head, &$tail, $file, &$mime
1348            ) use ( $logger, $hookRunner ) {
1349                // Also test DjVu
1350                $deja = new DjVuImage( $file );
1351                if ( $deja->isValid() ) {
1352                    $logger->info( "Detected $file as image/vnd.djvu\n" );
1353                    $mime = 'image/vnd.djvu';
1354
1355                    return;
1356                }
1357                // Some strings by reference for performance - assuming well-behaved hooks
1358                $hookRunner->onMimeMagicGuessFromContent(
1359                    $mimeAnalyzer, $head, $tail, $file, $mime );
1360            },
1361            'extCallback' => static function ( $mimeAnalyzer, $ext, &$mime ) use ( $hookRunner ) {
1362                // Media handling extensions can improve the MIME detected
1363                $hookRunner->onMimeMagicImproveFromExtension( $mimeAnalyzer, $ext, $mime );
1364            },
1365            'initCallback' => static function ( $mimeAnalyzer ) use ( $hookRunner ) {
1366                // Allow media handling extensions adding MIME-types and MIME-info
1367                $hookRunner->onMimeMagicInit( $mimeAnalyzer );
1368            },
1369            'logger' => $logger
1370        ];
1371
1372        if ( $params['infoFile'] === 'includes/mime.info' ) {
1373            $params['infoFile'] = MimeAnalyzer::USE_INTERNAL;
1374        }
1375
1376        if ( $params['typeFile'] === 'includes/mime.types' ) {
1377            $params['typeFile'] = MimeAnalyzer::USE_INTERNAL;
1378        }
1379
1380        $detectorCmd = $mainConfig->get( MainConfigNames::MimeDetectorCommand );
1381        if ( $detectorCmd ) {
1382            $factory = $services->getShellCommandFactory();
1383            $params['detectCallback'] = static function ( $file ) use ( $detectorCmd, $factory ) {
1384                $result = $factory->create()
1385                    // $wgMimeDetectorCommand can contain commands with parameters
1386                    ->unsafeParams( $detectorCmd )
1387                    ->params( $file )
1388                    ->execute();
1389                return $result->getStdout();
1390            };
1391        }
1392
1393        return new MimeAnalyzer( $params );
1394    },
1395
1396    'MovePageFactory' => static function ( MediaWikiServices $services ): MovePageFactory {
1397        return $services->getService( '_PageCommandFactory' );
1398    },
1399
1400    'NamespaceInfo' => static function ( MediaWikiServices $services ): NamespaceInfo {
1401        return new NamespaceInfo(
1402            new ServiceOptions( NamespaceInfo::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1403            $services->getHookContainer(),
1404            ExtensionRegistry::getInstance()->getAttribute( 'ExtensionNamespaces' ),
1405            ExtensionRegistry::getInstance()->getAttribute( 'ImmovableNamespaces' )
1406        );
1407    },
1408
1409    'NameTableStoreFactory' => static function ( MediaWikiServices $services ): NameTableStoreFactory {
1410        return new NameTableStoreFactory(
1411            $services->getDBLoadBalancerFactory(),
1412            $services->getMainWANObjectCache(),
1413            LoggerFactory::getInstance( 'NameTableSqlStore' )
1414        );
1415    },
1416
1417    'ObjectCacheFactory' => static function ( MediaWikiServices $services ): ObjectCacheFactory {
1418        return new ObjectCacheFactory(
1419            new ServiceOptions(
1420                ObjectCacheFactory::CONSTRUCTOR_OPTIONS,
1421                $services->getMainConfig()
1422            ),
1423            $services->getStatsFactory(),
1424            LoggerFactory::getProvider(),
1425            // Prevent a recursive service instantiation on DBLoadBalancerFactory
1426            // and ensure the service keeps working when DB storage is disabled.
1427            static function () use ( $services ) {
1428                return $services->getDBLoadBalancerFactory();
1429            },
1430            WikiMap::getCurrentWikiDbDomain()->getId(),
1431            $services->getTracer()
1432        );
1433    },
1434
1435    'ObjectFactory' => static function ( MediaWikiServices $services ): ObjectFactory {
1436        return new ObjectFactory( $services );
1437    },
1438
1439    'OldRevisionImporter' => static function ( MediaWikiServices $services ): OldRevisionImporter {
1440        return new ImportableOldRevisionImporter(
1441            true,
1442            LoggerFactory::getInstance( 'OldRevisionImporter' ),
1443            $services->getConnectionProvider(),
1444            $services->getRevisionStoreFactory()->getRevisionStoreForImport(),
1445            $services->getSlotRoleRegistry(),
1446            $services->getWikiPageFactory(),
1447            $services->getPageUpdaterFactory(),
1448            $services->getUserFactory()
1449        );
1450    },
1451
1452    'PageEditStash' => static function ( MediaWikiServices $services ): PageEditStash {
1453        return new PageEditStash(
1454            $services->getObjectCacheFactory()->getLocalClusterInstance(),
1455            $services->getConnectionProvider(),
1456            LoggerFactory::getInstance( 'StashEdit' ),
1457            $services->getStatsFactory(),
1458            $services->getUserEditTracker(),
1459            $services->getUserFactory(),
1460            $services->getWikiPageFactory(),
1461            $services->getHookContainer(),
1462            defined( 'MEDIAWIKI_JOB_RUNNER' ) || MW_ENTRY_POINT === 'cli'
1463                ? PageEditStash::INITIATOR_JOB_OR_CLI
1464                : PageEditStash::INITIATOR_USER
1465        );
1466    },
1467
1468    'PageProps' => static function ( MediaWikiServices $services ): PageProps {
1469        return new PageProps(
1470            $services->getLinkBatchFactory(),
1471            $services->getConnectionProvider()
1472        );
1473    },
1474
1475    'PageRestHelperFactory' => static function ( MediaWikiServices $services ): PageRestHelperFactory {
1476        return new PageRestHelperFactory(
1477            new ServiceOptions( PageRestHelperFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1478            $services->getRevisionLookup(),
1479            $services->getRevisionRenderer(),
1480            $services->getTitleFormatter(),
1481            $services->getPageStore(),
1482            $services->getParsoidOutputStash(),
1483            $services->getStatsdDataFactory(),
1484            $services->getParserOutputAccess(),
1485            $services->getParsoidSiteConfig(),
1486            $services->getHtmlTransformFactory(),
1487            $services->getContentHandlerFactory(),
1488            $services->getLanguageFactory(),
1489            $services->getRedirectStore(),
1490            $services->getLanguageConverterFactory(),
1491            $services->getTitleFactory(),
1492            $services->getConnectionProvider(),
1493            $services->getChangeTagsStore(),
1494            $services->getStatsFactory()
1495        );
1496    },
1497
1498    'PageStore' => static function ( MediaWikiServices $services ): PageStore {
1499        return $services->getPageStoreFactory()->getPageStore();
1500    },
1501
1502    'PageStoreFactory' => static function ( MediaWikiServices $services ): PageStoreFactory {
1503        $options = new ServiceOptions(
1504            PageStoreFactory::CONSTRUCTOR_OPTIONS,
1505            $services->getMainConfig()
1506        );
1507
1508        return new PageStoreFactory(
1509            $options,
1510            $services->getDBLoadBalancerFactory(),
1511            $services->getNamespaceInfo(),
1512            $services->getTitleParser(),
1513            $services->getLinkCache(),
1514            $services->getStatsFactory()
1515        );
1516    },
1517
1518    'PageUpdaterFactory' => static function (
1519        MediaWikiServices $services
1520    ): PageUpdaterFactory {
1521        $editResultCache = new EditResultCache(
1522            $services->getMainObjectStash(),
1523            $services->getConnectionProvider(),
1524            new ServiceOptions(
1525                EditResultCache::CONSTRUCTOR_OPTIONS,
1526                $services->getMainConfig()
1527            )
1528        );
1529
1530        return new PageUpdaterFactory(
1531            $services->getRevisionStore(),
1532            $services->getRevisionRenderer(),
1533            $services->getSlotRoleRegistry(),
1534            $services->getParserCache(),
1535            $services->getJobQueueGroup(),
1536            $services->getContentLanguage(),
1537            $services->getDBLoadBalancerFactory(),
1538            $services->getContentHandlerFactory(),
1539            $services->getDomainEventDispatcher(),
1540            $services->getHookContainer(),
1541            $editResultCache,
1542            LoggerFactory::getInstance( 'SavePage' ),
1543            new ServiceOptions(
1544                PageUpdaterFactory::CONSTRUCTOR_OPTIONS,
1545                $services->getMainConfig()
1546            ),
1547            $services->getUserGroupManager(),
1548            $services->getTitleFormatter(),
1549            $services->getContentTransformer(),
1550            $services->getPageEditStash(),
1551            $services->getMainWANObjectCache(),
1552            $services->getWikiPageFactory(),
1553            $services->getChangeTagsStore(),
1554            $services->getChangeTagsStore()->getSoftwareTags()
1555        );
1556    },
1557
1558    'Parser' => static function ( MediaWikiServices $services ): Parser {
1559        // This service exists as convenience function to get the global parser in global code.
1560        // Do not use this service for dependency injection or in service wiring (T343070).
1561        // Use the 'ParserFactory' service instead.
1562        return $services->getParserFactory()->getMainInstance();
1563    },
1564
1565    'ParserCache' => static function ( MediaWikiServices $services ): ParserCache {
1566        return $services->getParserCacheFactory()
1567            ->getParserCache( ParserCacheFactory::DEFAULT_NAME );
1568    },
1569
1570    'ParserCacheFactory' => static function ( MediaWikiServices $services ): ParserCacheFactory {
1571        $config = $services->getMainConfig();
1572        $cache = $services->getObjectCacheFactory()->getInstance( $config->get( MainConfigNames::ParserCacheType ) );
1573        $wanCache = $services->getMainWANObjectCache();
1574
1575        $options = new ServiceOptions( ParserCacheFactory::CONSTRUCTOR_OPTIONS, $config );
1576
1577        return new ParserCacheFactory(
1578            $cache,
1579            $wanCache,
1580            $services->getHookContainer(),
1581            $services->getJsonCodec(),
1582            $services->getStatsFactory(),
1583            LoggerFactory::getInstance( 'ParserCache' ),
1584            $options,
1585            $services->getTitleFactory(),
1586            $services->getWikiPageFactory(),
1587            $services->getGlobalIdGenerator()
1588        );
1589    },
1590
1591    'ParserFactory' => static function ( MediaWikiServices $services ): ParserFactory {
1592        $options = new ServiceOptions( Parser::CONSTRUCTOR_OPTIONS,
1593            $services->getMainConfig()
1594        );
1595
1596        return new ParserFactory(
1597            $options,
1598            $services->getMagicWordFactory(),
1599            $services->getContentLanguage(),
1600            $services->getUrlUtils(),
1601            $services->getSpecialPageFactory(),
1602            $services->getLinkRendererFactory(),
1603            $services->getNamespaceInfo(),
1604            LoggerFactory::getInstance( 'Parser' ),
1605            $services->getBadFileLookup(),
1606            $services->getLanguageConverterFactory(),
1607            $services->getLanguageNameUtils(),
1608            $services->getHookContainer(),
1609            $services->getTidy(),
1610            $services->getMainWANObjectCache(),
1611            $services->getUserOptionsLookup(),
1612            $services->getUserFactory(),
1613            $services->getTitleFormatter(),
1614            $services->getHttpRequestFactory(),
1615            $services->getTrackingCategories(),
1616            $services->getSignatureValidatorFactory(),
1617            $services->getUserNameUtils()
1618        );
1619    },
1620
1621    'ParserOutputAccess' => static function ( MediaWikiServices $services ): ParserOutputAccess {
1622        return new ParserOutputAccess(
1623            $services->getParserCacheFactory(),
1624            $services->getRevisionLookup(),
1625            $services->getRevisionRenderer(),
1626            $services->getStatsFactory(),
1627            $services->getDBLoadBalancerFactory(),
1628            $services->getChronologyProtector(),
1629            LoggerFactory::getProvider(),
1630            $services->getWikiPageFactory(),
1631            $services->getTitleFormatter(),
1632            $services->getTracer()
1633        );
1634    },
1635
1636    'ParsoidDataAccess' => static function ( MediaWikiServices $services ): DataAccess {
1637        $mainConfig = $services->getMainConfig();
1638        return new MWDataAccess(
1639            new ServiceOptions( MWDataAccess::CONSTRUCTOR_OPTIONS, $mainConfig ),
1640            $services->getRepoGroup(),
1641            $services->getBadFileLookup(),
1642            $services->getHookContainer(),
1643            $services->getContentTransformer(),
1644            $services->getTrackingCategories(),
1645            $services->getReadOnlyMode(),
1646            $services->getParserFactory(), // *legacy* parser factory
1647            $services->getLinkBatchFactory()
1648        );
1649    },
1650
1651    'ParsoidOutputStash' => static function ( MediaWikiServices $services ): ParsoidOutputStash {
1652        // TODO: Determine storage requirements and config options for stashing parsoid
1653        //       output for VE edits (T309016).
1654        $config = $services->getMainConfig()->get( MainConfigNames::ParsoidCacheConfig );
1655        $backend = $config['StashType']
1656            ? $services->getObjectCacheFactory()->getInstance( $config['StashType'] )
1657            : $services->getMainObjectStash();
1658
1659        return new SimpleParsoidOutputStash(
1660            $services->getContentHandlerFactory(),
1661            $backend,
1662            $config['StashDuration']
1663        );
1664    },
1665
1666    'ParsoidPageConfigFactory' => static function ( MediaWikiServices $services ): MWPageConfigFactory {
1667        return new MWPageConfigFactory(
1668            $services->getRevisionStore(),
1669            $services->getSlotRoleRegistry(),
1670            $services->getLanguageFactory()
1671        );
1672    },
1673
1674    'ParsoidParserFactory' => static function ( MediaWikiServices $services ): ParsoidParserFactory {
1675        return new ParsoidParserFactory(
1676            $services->getParsoidSiteConfig(),
1677            $services->getParsoidDataAccess(),
1678            $services->getParsoidPageConfigFactory(),
1679            $services->getLanguageConverterFactory(),
1680            $services->getParserFactory()
1681        );
1682    },
1683
1684    'ParsoidSiteConfig' => static function ( MediaWikiServices $services ): MWSiteConfig {
1685        $mainConfig = $services->getMainConfig();
1686        $parsoidSettings = $mainConfig->get( MainConfigNames::ParsoidSettings );
1687        return new MWSiteConfig(
1688            new ServiceOptions( MWSiteConfig::CONSTRUCTOR_OPTIONS, $mainConfig ),
1689            $parsoidSettings,
1690            $services->getObjectFactory(),
1691            $services->getContentLanguage(),
1692            $services->getStatsdDataFactory(),
1693            $services->getStatsFactory(),
1694            $services->getMagicWordFactory(),
1695            $services->getNamespaceInfo(),
1696            $services->getSpecialPageFactory(),
1697            $services->getInterwikiLookup(),
1698            $services->getUserOptionsLookup(),
1699            $services->getLanguageFactory(),
1700            $services->getLanguageConverterFactory(),
1701            $services->getLanguageNameUtils(),
1702            $services->getUrlUtils(),
1703            $services->getContentHandlerFactory(),
1704            ExtensionRegistry::getInstance()->getAttribute( 'ParsoidModules' ),
1705            // These arguments are temporary and will be removed once
1706            // better solutions are found.
1707            $services->getParserFactory(), // T268776
1708            $mainConfig, // T268777
1709            ExtensionRegistry::getInstance()->isLoaded( 'TimedMediaHandler' )
1710        );
1711    },
1712
1713    'PasswordFactory' => static function ( MediaWikiServices $services ): PasswordFactory {
1714        $config = $services->getMainConfig();
1715        return new PasswordFactory(
1716            $config->get( MainConfigNames::PasswordConfig ),
1717            $config->get( MainConfigNames::PasswordDefault )
1718        );
1719    },
1720
1721    'PasswordReset' => static function ( MediaWikiServices $services ): PasswordReset {
1722        $options = new ServiceOptions( PasswordReset::CONSTRUCTOR_OPTIONS, $services->getMainConfig() );
1723        return new PasswordReset(
1724            $options,
1725            LoggerFactory::getInstance( 'authentication' ),
1726            $services->getAuthManager(),
1727            $services->getHookContainer(),
1728            $services->getUserIdentityLookup(),
1729            $services->getUserFactory(),
1730            $services->getUserNameUtils(),
1731            $services->getUserOptionsLookup()
1732        );
1733    },
1734
1735    'PerDbNameStatsdDataFactory' => static function ( MediaWikiServices $services ): StatsdDataFactoryInterface {
1736        $config = $services->getMainConfig();
1737        $wiki = $config->get( MainConfigNames::DBname );
1738        return new PrefixingStatsdDataFactoryProxy(
1739            $services->getStatsdDataFactory(),
1740            $wiki
1741        );
1742    },
1743
1744    'PermissionManager' => static function ( MediaWikiServices $services ): PermissionManager {
1745        return new PermissionManager(
1746            new ServiceOptions(
1747                PermissionManager::CONSTRUCTOR_OPTIONS, $services->getMainConfig()
1748            ),
1749            $services->getSpecialPageFactory(),
1750            $services->getNamespaceInfo(),
1751            $services->getGroupPermissionsLookup(),
1752            $services->getUserGroupManager(),
1753            $services->getBlockManager(),
1754            $services->getFormatterFactory()->getBlockErrorFormatter(
1755                new LazyLocalizationContext( static function () {
1756                    return RequestContext::getMain();
1757                } )
1758            ),
1759            $services->getHookContainer(),
1760            $services->getUserIdentityLookup(),
1761            $services->getRedirectLookup(),
1762            $services->getRestrictionStore(),
1763            $services->getTitleFormatter(),
1764            $services->getTempUserConfig(),
1765            $services->getUserFactory(),
1766            $services->getActionFactory()
1767        );
1768    },
1769
1770    'Pingback' => static function ( MediaWikiServices $services ): Pingback {
1771        return new Pingback(
1772            $services->getMainConfig(),
1773            $services->getConnectionProvider(),
1774            $services->getObjectCacheFactory()->getLocalClusterInstance(),
1775            $services->getHttpRequestFactory(),
1776            LoggerFactory::getInstance( 'Pingback' )
1777        );
1778    },
1779
1780    'PoolCounterFactory' => static function ( MediaWikiServices $services ): PoolCounterFactory {
1781        $mainConfig = $services->getMainConfig();
1782        return new PoolCounterFactory(
1783            $mainConfig->get( MainConfigNames::PoolCounterConf ),
1784            $mainConfig->get( MainConfigNames::PoolCountClientConf ),
1785            LoggerFactory::getInstance( 'poolcounter' ),
1786            $services->getTracer()
1787        );
1788    },
1789
1790    'PreferencesFactory' => static function ( MediaWikiServices $services ): PreferencesFactory {
1791        $factory = new DefaultPreferencesFactory(
1792            new ServiceOptions(
1793                DefaultPreferencesFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1794            $services->getContentLanguage(),
1795            $services->getAuthManager(),
1796            $services->getLinkRendererFactory()->create(),
1797            $services->getNamespaceInfo(),
1798            $services->getPermissionManager(),
1799            $services->getLanguageConverterFactory()->getLanguageConverter(),
1800            $services->getLanguageNameUtils(),
1801            $services->getHookContainer(),
1802            $services->getUserOptionsManager(),
1803            $services->getLanguageConverterFactory(),
1804            $services->getParserFactory(),
1805            $services->getSkinFactory(),
1806            $services->getUserGroupManager(),
1807            $services->getSignatureValidatorFactory()
1808        );
1809        $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) );
1810
1811        return $factory;
1812    },
1813
1814    'PreloadedContentBuilder' => static function ( MediaWikiServices $services ): PreloadedContentBuilder {
1815        return new PreloadedContentBuilder(
1816            $services->getContentHandlerFactory(),
1817            $services->getWikiPageFactory(),
1818            $services->getRedirectLookup(),
1819            $services->getSpecialPageFactory(),
1820            $services->getContentTransformer(),
1821            $services->getHookContainer(),
1822        );
1823    },
1824
1825    'ProxyLookup' => static function ( MediaWikiServices $services ): ProxyLookup {
1826        $mainConfig = $services->getMainConfig();
1827        return new ProxyLookup(
1828            $mainConfig->get( MainConfigNames::CdnServers ),
1829            $mainConfig->get( MainConfigNames::CdnServersNoPurge ),
1830            $services->getHookContainer()
1831        );
1832    },
1833
1834    'RateLimiter' => static function ( MediaWikiServices $services ): RateLimiter {
1835        $rateLimiter = new RateLimiter(
1836            new ServiceOptions( RateLimiter::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1837            $services->getWRStatsFactory(),
1838            $services->getCentralIdLookupFactory()->getNonLocalLookup(),
1839            $services->getUserFactory(),
1840            $services->getUserGroupManager(),
1841            $services->getHookContainer()
1842        );
1843
1844        $rateLimiter->setStats( $services->getStatsFactory() );
1845
1846        return $rateLimiter;
1847    },
1848
1849    'ReadOnlyMode' => static function ( MediaWikiServices $services ): ReadOnlyMode {
1850        return new ReadOnlyMode(
1851            new ConfiguredReadOnlyMode(
1852                $services->getMainConfig()->get( MainConfigNames::ReadOnly ),
1853                $services->getMainConfig()->get( MainConfigNames::ReadOnlyFile )
1854            ),
1855            $services->getDBLoadBalancerFactory()
1856        );
1857    },
1858
1859    'RedirectLookup' => static function ( MediaWikiServices $services ): RedirectLookup {
1860        return $services->getRedirectStore();
1861    },
1862
1863    'RedirectStore' => static function ( MediaWikiServices $services ): RedirectStore {
1864        return new RedirectStore(
1865            $services->getConnectionProvider(),
1866            $services->getPageStore(),
1867            $services->getTitleParser(),
1868            $services->getRepoGroup(),
1869            LoggerFactory::getInstance( 'RedirectStore' )
1870        );
1871    },
1872
1873    'RenameUserFactory' => static function ( MediaWikiServices $services ): RenameUserFactory {
1874        return new RenameUserFactory(
1875            new ServiceOptions( RenameUserFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
1876            $services->getCentralIdLookupFactory(),
1877            $services->getJobQueueGroupFactory(),
1878            $services->getMovePageFactory(),
1879            $services->getUserFactory(),
1880            $services->getUserNameUtils(),
1881            $services->getPermissionManager(),
1882            $services->getTitleFactory(),
1883        );
1884    },
1885
1886    'RepoGroup' => static function ( MediaWikiServices $services ): RepoGroup {
1887        $config = $services->getMainConfig();
1888        return new RepoGroup(
1889            $config->get( MainConfigNames::LocalFileRepo ),
1890            $config->get( MainConfigNames::ForeignFileRepos ),
1891            $services->getMainWANObjectCache(),
1892            $services->getMimeAnalyzer()
1893        );
1894    },
1895
1896    'ResourceLoader' => static function ( MediaWikiServices $services ): ResourceLoader {
1897        $config = $services->getMainConfig();
1898
1899        $maxage = $config->get( MainConfigNames::ResourceLoaderMaxage );
1900        $rl = new ResourceLoader(
1901            $config,
1902            LoggerFactory::getInstance( 'resourceloader' ),
1903            new DependencyStore( $services->getMainObjectStash() ),
1904            [
1905                'loadScript' => $config->get( MainConfigNames::LoadScript ),
1906                'maxageVersioned' => $maxage['versioned'] ?? null,
1907                'maxageUnversioned' => $maxage['unversioned'] ?? null,
1908            ]
1909        );
1910
1911        $extRegistry = ExtensionRegistry::getInstance();
1912        // Attribute has precedence over config
1913        $modules = $extRegistry->getAttribute( 'ResourceModules' )
1914            + $config->get( MainConfigNames::ResourceModules );
1915        $moduleSkinStyles = $extRegistry->getAttribute( 'ResourceModuleSkinStyles' )
1916            + $config->get( MainConfigNames::ResourceModuleSkinStyles );
1917
1918        $rl->setModuleSkinStyles( $moduleSkinStyles );
1919        $rl->addSource( $config->get( MainConfigNames::ResourceLoaderSources ) );
1920
1921        // Core modules, then extension/skin modules
1922        $rl->register( include MW_INSTALL_PATH . '/resources/Resources.php' );
1923        $rl->register( $modules );
1924        $hookRunner = new \MediaWiki\ResourceLoader\HookRunner( $services->getHookContainer() );
1925        $hookRunner->onResourceLoaderRegisterModules( $rl );
1926
1927        $msgPosterAttrib = $extRegistry->getAttribute( 'MessagePosterModule' );
1928        $rl->register( 'mediawiki.messagePoster', [
1929            'localBasePath' => MW_INSTALL_PATH,
1930            'debugRaw' => false,
1931            'scripts' => array_merge(
1932                [
1933                    "resources/src/mediawiki.messagePoster/factory.js",
1934                    "resources/src/mediawiki.messagePoster/MessagePoster.js",
1935                    "resources/src/mediawiki.messagePoster/WikitextMessagePoster.js",
1936                ],
1937                $msgPosterAttrib['scripts'] ?? []
1938            ),
1939            'dependencies' => array_merge(
1940                [
1941                    'oojs',
1942                    'mediawiki.api',
1943                    'mediawiki.ForeignApi',
1944                ],
1945                $msgPosterAttrib['dependencies'] ?? []
1946            ),
1947        ] );
1948
1949        if ( $config->get( MainConfigNames::EnableJavaScriptTest ) === true ) {
1950            $rl->registerTestModules();
1951        }
1952
1953        return $rl;
1954    },
1955
1956    'RestrictionStore' => static function ( MediaWikiServices $services ): RestrictionStore {
1957        return new RestrictionStore(
1958            new ServiceOptions(
1959                RestrictionStore::CONSTRUCTOR_OPTIONS, $services->getMainConfig()
1960            ),
1961            $services->getMainWANObjectCache(),
1962            $services->getDBLoadBalancer(),
1963            $services->getLinkCache(),
1964            $services->getLinksMigration(),
1965            $services->getCommentStore(),
1966            $services->getHookContainer(),
1967            $services->getPageStore()
1968        );
1969    },
1970
1971    'RevertedTagUpdateManager' => static function ( MediaWikiServices $services ): RevertedTagUpdateManager {
1972        $editResultCache = new EditResultCache(
1973            $services->getMainObjectStash(),
1974            $services->getConnectionProvider(),
1975            new ServiceOptions(
1976                EditResultCache::CONSTRUCTOR_OPTIONS,
1977                $services->getMainConfig()
1978            )
1979        );
1980
1981        return new RevertedTagUpdateManager(
1982            $editResultCache,
1983            $services->getJobQueueGroup()
1984        );
1985    },
1986
1987    'RevisionFactory' => static function ( MediaWikiServices $services ): RevisionFactory {
1988        return $services->getRevisionStore();
1989    },
1990
1991    'RevisionLookup' => static function ( MediaWikiServices $services ): RevisionLookup {
1992        return $services->getRevisionStore();
1993    },
1994
1995    'RevisionRenderer' => static function ( MediaWikiServices $services ): RevisionRenderer {
1996        $renderer = new RevisionRenderer(
1997            $services->getDBLoadBalancer(),
1998            $services->getSlotRoleRegistry(),
1999            $services->getContentRenderer()
2000        );
2001
2002        $renderer->setLogger( LoggerFactory::getInstance( 'SaveParse' ) );
2003        return $renderer;
2004    },
2005
2006    'RevisionStore' => static function ( MediaWikiServices $services ): RevisionStore {
2007        return $services->getRevisionStoreFactory()->getRevisionStore();
2008    },
2009
2010    'RevisionStoreFactory' => static function ( MediaWikiServices $services ): RevisionStoreFactory {
2011        return new RevisionStoreFactory(
2012            $services->getDBLoadBalancerFactory(),
2013            $services->getBlobStoreFactory(),
2014            $services->getNameTableStoreFactory(),
2015            $services->getSlotRoleRegistry(),
2016            $services->getMainWANObjectCache(),
2017            $services->getLocalServerObjectCache(),
2018            $services->getCommentStore(),
2019            $services->getActorStoreFactory(),
2020            LoggerFactory::getInstance( 'RevisionStore' ),
2021            $services->getContentHandlerFactory(),
2022            $services->getPageStoreFactory(),
2023            $services->getTitleFactory(),
2024            $services->getHookContainer()
2025        );
2026    },
2027
2028    'RollbackPageFactory' => static function ( MediaWikiServices $services ): RollbackPageFactory {
2029        return $services->get( '_PageCommandFactory' );
2030    },
2031
2032    'RowCommentFormatter' => static function ( MediaWikiServices $services ): RowCommentFormatter {
2033        return new RowCommentFormatter(
2034            $services->getCommentParserFactory(),
2035            $services->getCommentStore()
2036        );
2037    },
2038
2039    'SearchEngineConfig' => static function ( MediaWikiServices $services ): SearchEngineConfig {
2040        return new SearchEngineConfig(
2041            new ServiceOptions(
2042                SearchEngineConfig::CONSTRUCTOR_OPTIONS,
2043                $services->getMainConfig()
2044            ),
2045            $services->getContentLanguage(),
2046            $services->getHookContainer(),
2047            ExtensionRegistry::getInstance()->getAttribute( 'SearchMappings' ),
2048            $services->getUserOptionsLookup()
2049        );
2050    },
2051
2052    'SearchEngineFactory' => static function ( MediaWikiServices $services ): SearchEngineFactory {
2053        return new SearchEngineFactory(
2054            $services->getSearchEngineConfig(),
2055            $services->getHookContainer(),
2056            $services->getConnectionProvider()
2057        );
2058    },
2059
2060    'SearchResultThumbnailProvider' => static function ( MediaWikiServices $services ): SearchResultThumbnailProvider {
2061        return new SearchResultThumbnailProvider(
2062            $services->getRepoGroup(),
2063            $services->getHookContainer()
2064        );
2065    },
2066
2067    'SessionManager' => static function ( MediaWikiServices $services ): SessionManager {
2068        // TODO use proper dependency injection
2069        return SessionManager::singleton();
2070    },
2071
2072    'ShellboxClientFactory' => static function ( MediaWikiServices $services ): ShellboxClientFactory {
2073        $urls = $services->getMainConfig()->get( MainConfigNames::ShellboxUrls );
2074
2075        return new ShellboxClientFactory(
2076            $services->getHttpRequestFactory(),
2077            $urls,
2078            $services->getMainConfig()->get( MainConfigNames::ShellboxSecretKey )
2079        );
2080    },
2081
2082    'ShellCommandFactory' => static function ( MediaWikiServices $services ): CommandFactory {
2083        $config = $services->getMainConfig();
2084
2085        $limits = [
2086            'time' => $config->get( MainConfigNames::MaxShellTime ),
2087            'walltime' => $config->get( MainConfigNames::MaxShellWallClockTime ),
2088            'memory' => $config->get( MainConfigNames::MaxShellMemory ),
2089            'filesize' => $config->get( MainConfigNames::MaxShellFileSize ),
2090        ];
2091        $cgroup = $config->get( MainConfigNames::ShellCgroup );
2092        $restrictionMethod = $config->get( MainConfigNames::ShellRestrictionMethod );
2093
2094        $factory = new CommandFactory( $services->getShellboxClientFactory(),
2095            $limits, $cgroup, $restrictionMethod );
2096        $factory->setLogger( LoggerFactory::getInstance( 'exec' ) );
2097        $factory->logStderr();
2098
2099        return $factory;
2100    },
2101
2102    'SignatureValidatorFactory' => static function ( MediaWikiServices $services ): SignatureValidatorFactory {
2103        return new SignatureValidatorFactory(
2104            new ServiceOptions(
2105                SignatureValidator::CONSTRUCTOR_OPTIONS,
2106                $services->getMainConfig()
2107            ),
2108            // Use closures for these to avoid a circular dependency on Parser
2109            static function () use ( $services ) {
2110                return $services->getParserFactory();
2111            },
2112            static function () use ( $services ) {
2113                return $services->getLintErrorChecker();
2114            },
2115            $services->getSpecialPageFactory(),
2116            $services->getTitleFactory(),
2117        );
2118    },
2119
2120    'SiteLookup' => static function ( MediaWikiServices $services ): SiteLookup {
2121        // Use SiteStore as the SiteLookup as well. This was originally separated
2122        // to allow for a cacheable read-only interface, but this was never used.
2123        // SiteStore has caching (see below).
2124        return $services->getSiteStore();
2125    },
2126
2127    'SiteStore' => static function ( MediaWikiServices $services ): SiteStore {
2128        $rawSiteStore = new DBSiteStore( $services->getConnectionProvider() );
2129
2130        $cache = $services->getLocalServerObjectCache();
2131        if ( $cache instanceof EmptyBagOStuff ) {
2132            $cache = $services->getObjectCacheFactory()->getLocalClusterInstance();
2133        }
2134
2135        return new CachingSiteStore( $rawSiteStore, $cache );
2136    },
2137
2138    /** @suppress PhanTypeInvalidCallableArrayKey */
2139    'SkinFactory' => static function ( MediaWikiServices $services ): SkinFactory {
2140        $factory = new SkinFactory(
2141            $services->getObjectFactory(),
2142            (array)$services->getMainConfig()->get( MainConfigNames::SkipSkins )
2143        );
2144
2145        $names = $services->getMainConfig()->get( MainConfigNames::ValidSkinNames );
2146
2147        foreach ( $names as $name => $skin ) {
2148            if ( is_array( $skin ) ) {
2149                $spec = $skin;
2150                $displayName = $skin['displayname'] ?? $name;
2151                $skippable = $skin['skippable'] ?? null;
2152            } else {
2153                $displayName = $skin;
2154                $skippable = null;
2155                $spec = [
2156                    'name' => $name,
2157                    'class' => "Skin$skin"
2158                ];
2159            }
2160            $factory->register( $name, $displayName, $spec, $skippable );
2161        }
2162
2163        // Register a hidden "fallback" skin
2164        $factory->register( 'fallback', 'Fallback', [
2165            'class' => SkinFallback::class,
2166            'args' => [
2167                [
2168                    'name' => 'fallback',
2169                    'styles' => [ 'mediawiki.skinning.interface', 'mediawiki.codex.messagebox.styles' ],
2170                    'supportsMwHeading' => true,
2171                    'templateDirectory' => __DIR__ . '/skins/templates/fallback',
2172                ]
2173            ]
2174        ], true );
2175        // Register a hidden skin for api output
2176        $factory->register( 'apioutput', 'ApiOutput', [
2177            'class' => SkinApi::class,
2178            'args' => [
2179                [
2180                    'name' => 'apioutput',
2181                    'styles' => [ 'mediawiki.skinning.interface' ],
2182                    'supportsMwHeading' => true,
2183                    'templateDirectory' => __DIR__ . '/skins/templates/apioutput',
2184                ]
2185            ]
2186        ], true );
2187        // Register a hidden skin for Special:UserLogin and Special:CreateAccount
2188        $factory->register( 'authentication-popup', 'Authentication popup', [
2189            'class' => SkinAuthenticationPopup::class,
2190            'args' => [
2191                [
2192                    'name' => 'authentication-popup',
2193                    'styles' => [
2194                        'mediawiki.skinning.interface',
2195                        'mediawiki.special.userlogin.authentication-popup',
2196                    ],
2197                    'bodyClasses' => [ 'mw-authentication-popup' ],
2198                    'responsive' => true,
2199                    'messages' => [
2200                        'sitesubtitle',
2201                        'sitetitle',
2202                    ],
2203                    'templateDirectory' => __DIR__ . '/skins/templates/authentication-popup',
2204                ]
2205            ]
2206        ], true );
2207        // Register a hidden skin for outputting skin json
2208        $factory->register( 'json', 'SkinJSON', [
2209            'class' => SkinApi::class,
2210            'args' => [
2211                [
2212                    'name' => 'json',
2213                    'styles' => [],
2214                    'supportsMwHeading' => true,
2215                    'format' => 'json',
2216                    'templateDirectory' => __DIR__ . '/skins/templates/apioutput',
2217                ]
2218            ]
2219        ], true );
2220
2221        return $factory;
2222    },
2223
2224    'SlotRoleRegistry' => static function ( MediaWikiServices $services ): SlotRoleRegistry {
2225        $registry = new SlotRoleRegistry(
2226            $services->getSlotRoleStore()
2227        );
2228
2229        $config = $services->getMainConfig();
2230        $contentHandlerFactory = $services->getContentHandlerFactory();
2231        $hookContainer = $services->getHookContainer();
2232        $titleFactory = $services->getTitleFactory();
2233        $registry->defineRole(
2234            SlotRecord::MAIN,
2235            static function () use ( $config, $contentHandlerFactory, $hookContainer, $titleFactory ) {
2236                return new MainSlotRoleHandler(
2237                    $config->get( MainConfigNames::NamespaceContentModels ),
2238                    $contentHandlerFactory,
2239                    $hookContainer,
2240                    $titleFactory
2241                );
2242            }
2243        );
2244
2245        return $registry;
2246    },
2247
2248    'SlotRoleStore' => static function ( MediaWikiServices $services ): NameTableStore {
2249        return $services->getNameTableStoreFactory()->getSlotRoles();
2250    },
2251
2252    'SpamChecker' => static function ( MediaWikiServices $services ): SpamChecker {
2253        return new SpamChecker(
2254            (array)$services->getMainConfig()->get( MainConfigNames::SpamRegex ),
2255            (array)$services->getMainConfig()->get( MainConfigNames::SummarySpamRegex )
2256        );
2257    },
2258
2259    'SpecialPageFactory' => static function ( MediaWikiServices $services ): SpecialPageFactory {
2260        return new SpecialPageFactory(
2261            new ServiceOptions(
2262                SpecialPageFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ),
2263            $services->getContentLanguage(),
2264            $services->getObjectFactory(),
2265            $services->getTitleFactory(),
2266            $services->getHookContainer()
2267        );
2268    },
2269
2270    'StatsdDataFactory' => static function ( MediaWikiServices $services ): IBufferingStatsdDataFactory {
2271        return new BufferingStatsdDataFactory(
2272            rtrim( $services->getMainConfig()->get( MainConfigNames::StatsdMetricPrefix ), '.' )
2273        );
2274    },
2275
2276    'StatsFactory' => static function ( MediaWikiServices $services ): StatsFactory {
2277        $config = $services->getMainConfig();
2278        $format = \Wikimedia\Stats\OutputFormats::getFormatFromString(
2279            $config->get( MainConfigNames::StatsFormat ) ?? 'null'
2280        );
2281        $cache = new StatsCache;
2282        $emitter = \Wikimedia\Stats\OutputFormats::getNewEmitter(
2283            $config->get( MainConfigNames::StatsPrefix ) ?? 'MediaWiki',
2284            $cache,
2285            \Wikimedia\Stats\OutputFormats::getNewFormatter( $format ),
2286            $config->get( MainConfigNames::StatsTarget )
2287        );
2288        $factory = new StatsFactory( $cache, $emitter, LoggerFactory::getInstance( 'Stats' ) );
2289        return $factory->withStatsdDataFactory( $services->getStatsdDataFactory() );
2290    },
2291
2292    'TalkPageNotificationManager' => static function (
2293        MediaWikiServices $services
2294    ): TalkPageNotificationManager {
2295        return new TalkPageNotificationManager(
2296            new ServiceOptions(
2297                TalkPageNotificationManager::CONSTRUCTOR_OPTIONS, $services->getMainConfig()
2298            ),
2299            $services->getConnectionProvider(),
2300            $services->getReadOnlyMode(),
2301            $services->getRevisionLookup(),
2302            $services->getHookContainer(),
2303            $services->getUserFactory()
2304        );
2305    },
2306
2307    'TempFSFileFactory' => static function ( MediaWikiServices $services ): TempFSFileFactory {
2308        return new TempFSFileFactory( $services->getMainConfig()->get( MainConfigNames::TmpDirectory ) );
2309    },
2310
2311    'TempUserConfig' => static function ( MediaWikiServices $services ): RealTempUserConfig {
2312        return new RealTempUserConfig(
2313            $services->getMainConfig()->get( MainConfigNames::AutoCreateTempUser )
2314        );
2315    },
2316
2317    'TempUserCreator' => static function ( MediaWikiServices $services ): TempUserCreator {
2318        return new TempUserCreator(
2319            $services->getTempUserConfig(),
2320            $services->getObjectFactory(),
2321            $services->getUserFactory(),
2322            $services->getAuthManager(),
2323            $services->getCentralIdLookup(),
2324            // This is supposed to match ThrottlePreAuthenticationProvider
2325            new Throttler(
2326                $services->getMainConfig()->get( MainConfigNames::TempAccountCreationThrottle ),
2327                [
2328                    'type' => 'tempacctcreate',
2329                    'cache' => $services->getObjectCacheFactory()->getLocalClusterInstance(),
2330                ]
2331            ),
2332            new Throttler(
2333                $services->getMainConfig()->get( MainConfigNames::TempAccountNameAcquisitionThrottle ),
2334                [
2335                    'type' => 'tempacctnameacquisition',
2336                    'cache' => $services->getObjectCacheFactory()->getLocalClusterInstance(),
2337                ]
2338            )
2339        );
2340    },
2341
2342    'Tidy' => static function ( MediaWikiServices $services ): TidyDriverBase {
2343        return new RemexDriver(
2344            new ServiceOptions(
2345                RemexDriver::CONSTRUCTOR_OPTIONS, $services->getMainConfig()
2346            )
2347        );
2348    },
2349
2350    'TitleFactory' => static function ( MediaWikiServices $services ): TitleFactory {
2351        return new TitleFactory();
2352    },
2353
2354    'TitleFormatter' => static function ( MediaWikiServices $services ): TitleFormatter {
2355        return $services->getService( '_MediaWikiTitleCodec' );
2356    },
2357
2358    'TitleMatcher' => static function ( MediaWikiServices $services ): TitleMatcher {
2359        return new TitleMatcher(
2360            new ServiceOptions(
2361                TitleMatcher::CONSTRUCTOR_OPTIONS,
2362                $services->getMainConfig()
2363            ),
2364            $services->getContentLanguage(),
2365            $services->getLanguageConverterFactory(),
2366            $services->getHookContainer(),
2367            $services