Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3use MediaWiki\Config\ServiceOptions;
4use MediaWiki\Context\RequestContext;
5use MediaWiki\Extension\AbuseFilter\AbuseFilterLogDetailsLookup;
6use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager as PermManager;
7use MediaWiki\Extension\AbuseFilter\AbuseLogConditionFactory;
8use MediaWiki\Extension\AbuseFilter\AbuseLoggerFactory;
9use MediaWiki\Extension\AbuseFilter\BlockAutopromoteStore;
10use MediaWiki\Extension\AbuseFilter\BlockedDomains\BlockedDomainConfigProvider;
11use MediaWiki\Extension\AbuseFilter\BlockedDomains\BlockedDomainFilter;
12use MediaWiki\Extension\AbuseFilter\BlockedDomains\BlockedDomainValidator;
13use MediaWiki\Extension\AbuseFilter\BlockedDomains\CustomBlockedDomainStorage;
14use MediaWiki\Extension\AbuseFilter\BlockedDomains\IBlockedDomainFilter;
15use MediaWiki\Extension\AbuseFilter\BlockedDomains\IBlockedDomainStorage;
16use MediaWiki\Extension\AbuseFilter\BlockedDomains\NoopBlockedDomainFilter;
17use MediaWiki\Extension\AbuseFilter\CentralDBManager;
18use MediaWiki\Extension\AbuseFilter\ChangeTags\ChangeTagger;
19use MediaWiki\Extension\AbuseFilter\ChangeTags\ChangeTagsManager;
20use MediaWiki\Extension\AbuseFilter\ChangeTags\ChangeTagValidator;
21use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesExecutor;
22use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesExecutorFactory as ConsExecutorFactory;
23use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesFactory;
24use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesLookup;
25use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
26use MediaWiki\Extension\AbuseFilter\EchoNotifier;
27use MediaWiki\Extension\AbuseFilter\EditBox\EditBoxBuilderFactory;
28use MediaWiki\Extension\AbuseFilter\EditRevUpdater;
29use MediaWiki\Extension\AbuseFilter\EmergencyCache;
30use MediaWiki\Extension\AbuseFilter\FilterCompare;
31use MediaWiki\Extension\AbuseFilter\FilterImporter;
32use MediaWiki\Extension\AbuseFilter\FilterLookup;
33use MediaWiki\Extension\AbuseFilter\FilterProfiler;
34use MediaWiki\Extension\AbuseFilter\FilterRunner;
35use MediaWiki\Extension\AbuseFilter\FilterRunnerFactory;
36use MediaWiki\Extension\AbuseFilter\FilterStore;
37use MediaWiki\Extension\AbuseFilter\FilterUser;
38use MediaWiki\Extension\AbuseFilter\FilterValidator;
39use MediaWiki\Extension\AbuseFilter\Hooks\AbuseFilterHookRunner;
40use MediaWiki\Extension\AbuseFilter\KeywordsManager;
41use MediaWiki\Extension\AbuseFilter\Parser\RuleCheckerFactory;
42use MediaWiki\Extension\AbuseFilter\SpecsFormatter;
43use MediaWiki\Extension\AbuseFilter\TemporaryAccountIPsViewerSpecification;
44use MediaWiki\Extension\AbuseFilter\TextExtractor;
45use MediaWiki\Extension\AbuseFilter\VariableGenerator\VariableGeneratorFactory;
46use MediaWiki\Extension\AbuseFilter\Variables\AbuseFilterProtectedVariablesLookup;
47use MediaWiki\Extension\AbuseFilter\Variables\LazyVariableComputer;
48use MediaWiki\Extension\AbuseFilter\Variables\VariablesBlobStore;
49use MediaWiki\Extension\AbuseFilter\Variables\VariablesFormatter;
50use MediaWiki\Extension\AbuseFilter\Variables\VariablesManager;
51use MediaWiki\Extension\AbuseFilter\Watcher\EmergencyWatcher;
52use MediaWiki\Extension\AbuseFilter\Watcher\UpdateHitCountWatcher;
53use MediaWiki\Extension\CommunityConfiguration\CommunityConfigurationServices;
54use MediaWiki\Logger\LoggerFactory;
55use MediaWiki\MediaWikiServices;
56use MediaWiki\Registration\ExtensionRegistry;
57use MediaWiki\WikiMap\WikiMap;
58use Wikimedia\Equivset\Equivset;
59
60// This file is actually covered by AbuseFilterServicesTest, but it's not possible to specify a path
61// in @covers annotations (https://github.com/sebastianbergmann/phpunit/issues/3794)
62// @codeCoverageIgnoreStart
63
64return [
65    AbuseFilterHookRunner::SERVICE_NAME => static function ( MediaWikiServices $services ): AbuseFilterHookRunner {
66        return new AbuseFilterHookRunner( $services->getHookContainer() );
67    },
68    KeywordsManager::SERVICE_NAME => static function ( MediaWikiServices $services ): KeywordsManager {
69        return new KeywordsManager( $services->get( AbuseFilterHookRunner::SERVICE_NAME ) );
70    },
71    FilterProfiler::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterProfiler {
72        return new FilterProfiler(
73            $services->getWRStatsFactory(),
74            new ServiceOptions(
75                FilterProfiler::CONSTRUCTOR_OPTIONS,
76                $services->getMainConfig()
77            ),
78            WikiMap::getCurrentWikiDbDomain()->getId(),
79            $services->getStatsdDataFactory(),
80            LoggerFactory::getInstance( 'AbuseFilter' )
81        );
82    },
83    PermManager::SERVICE_NAME => static function ( MediaWikiServices $services ): PermManager {
84        return new PermManager(
85            $services->getTempUserConfig(),
86            $services->getExtensionRegistry(),
87            $services->get( AbuseFilterProtectedVariablesLookup::SERVICE_NAME ),
88            $services->get( RuleCheckerFactory::SERVICE_NAME ),
89            $services->get( AbuseFilterHookRunner::SERVICE_NAME )
90        );
91    },
92    ChangeTagger::SERVICE_NAME => static function ( MediaWikiServices $services ): ChangeTagger {
93        return new ChangeTagger(
94            $services->getService( ChangeTagsManager::SERVICE_NAME )
95        );
96    },
97    ChangeTagsManager::SERVICE_NAME => static function ( MediaWikiServices $services ): ChangeTagsManager {
98        return new ChangeTagsManager(
99            $services->getChangeTagsStore(),
100            $services->getDBLoadBalancerFactory(),
101            $services->getMainWANObjectCache(),
102            $services->get( CentralDBManager::SERVICE_NAME )
103        );
104    },
105    ChangeTagValidator::SERVICE_NAME => static function ( MediaWikiServices $services ): ChangeTagValidator {
106        return new ChangeTagValidator(
107            $services->getService( ChangeTagsManager::SERVICE_NAME )
108        );
109    },
110    CentralDBManager::SERVICE_NAME => static function ( MediaWikiServices $services ): CentralDBManager {
111        return new CentralDBManager(
112            $services->getDBLoadBalancerFactory(),
113            $services->getMainConfig()->get( 'AbuseFilterCentralDB' ),
114            $services->getMainConfig()->get( 'AbuseFilterIsCentral' )
115        );
116    },
117    BlockAutopromoteStore::SERVICE_NAME => static function ( MediaWikiServices $services ): BlockAutopromoteStore {
118        return new BlockAutopromoteStore(
119            $services->getMainObjectStash(),
120            LoggerFactory::getInstance( 'AbuseFilter' ),
121            $services->get( FilterUser::SERVICE_NAME )
122        );
123    },
124    FilterUser::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterUser {
125        return new FilterUser(
126            // TODO We need a proper MessageLocalizer, see T247127
127            RequestContext::getMain(),
128            $services->getUserGroupManager(),
129            $services->getUserNameUtils(),
130            LoggerFactory::getInstance( 'AbuseFilter' )
131        );
132    },
133    RuleCheckerFactory::SERVICE_NAME => static function ( MediaWikiServices $services ): RuleCheckerFactory {
134        return new RuleCheckerFactory(
135            $services->getContentLanguage(),
136            $services->getObjectCacheFactory()->getLocalServerInstance( CACHE_HASH ),
137            LoggerFactory::getInstance( 'AbuseFilter' ),
138            $services->getService( KeywordsManager::SERVICE_NAME ),
139            $services->get( VariablesManager::SERVICE_NAME ),
140            $services->getStatsdDataFactory(),
141            new Equivset(),
142            $services->getMainConfig()->get( 'AbuseFilterConditionLimit' )
143        );
144    },
145    FilterLookup::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterLookup {
146        return new FilterLookup(
147            $services->getDBLoadBalancer(),
148            $services->getMainWANObjectCache(),
149            $services->get( CentralDBManager::SERVICE_NAME )
150        );
151    },
152    EmergencyCache::SERVICE_NAME => static function ( MediaWikiServices $services ): EmergencyCache {
153        return new EmergencyCache(
154            $services->getMainObjectStash(),
155            $services->getMainConfig()->get( 'AbuseFilterEmergencyDisableAge' )
156        );
157    },
158    EmergencyWatcher::SERVICE_NAME => static function ( MediaWikiServices $services ): EmergencyWatcher {
159        return new EmergencyWatcher(
160            $services->getService( EmergencyCache::SERVICE_NAME ),
161            $services->getDBLoadBalancerFactory(),
162            $services->getService( FilterLookup::SERVICE_NAME ),
163            $services->getService( EchoNotifier::SERVICE_NAME ),
164            new ServiceOptions(
165                EmergencyWatcher::CONSTRUCTOR_OPTIONS,
166                $services->getMainConfig()
167            )
168        );
169    },
170    EchoNotifier::SERVICE_NAME => static function ( MediaWikiServices $services ): EchoNotifier {
171        return new EchoNotifier(
172            $services->getService( FilterLookup::SERVICE_NAME ),
173            $services->getService( ConsequencesRegistry::SERVICE_NAME ),
174            ExtensionRegistry::getInstance()->isLoaded( 'Echo' )
175        );
176    },
177    FilterValidator::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterValidator {
178        return new FilterValidator(
179            $services->get( ChangeTagValidator::SERVICE_NAME ),
180            $services->get( RuleCheckerFactory::SERVICE_NAME ),
181            $services->get( PermManager::SERVICE_NAME ),
182            new ServiceOptions(
183                FilterValidator::CONSTRUCTOR_OPTIONS,
184                $services->getMainConfig()
185            )
186        );
187    },
188    FilterCompare::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterCompare {
189        return new FilterCompare(
190            $services->get( ConsequencesRegistry::SERVICE_NAME )
191        );
192    },
193    FilterImporter::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterImporter {
194        return new FilterImporter(
195            new ServiceOptions(
196                FilterImporter::CONSTRUCTOR_OPTIONS,
197                $services->getMainConfig()
198            ),
199            $services->get( ConsequencesRegistry::SERVICE_NAME )
200        );
201    },
202    FilterStore::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterStore {
203        return new FilterStore(
204            $services->get( ConsequencesRegistry::SERVICE_NAME ),
205            $services->getDBLoadBalancerFactory(),
206            $services->getActorNormalization(),
207            $services->get( FilterProfiler::SERVICE_NAME ),
208            $services->get( FilterLookup::SERVICE_NAME ),
209            $services->get( ChangeTagsManager::SERVICE_NAME ),
210            $services->get( FilterValidator::SERVICE_NAME ),
211            $services->get( FilterCompare::SERVICE_NAME ),
212            $services->get( EmergencyCache::SERVICE_NAME )
213        );
214    },
215    ConsequencesFactory::SERVICE_NAME => static function ( MediaWikiServices $services ): ConsequencesFactory {
216        return new ConsequencesFactory(
217            new ServiceOptions(
218                ConsequencesFactory::CONSTRUCTOR_OPTIONS,
219                $services->getMainConfig()
220            ),
221            LoggerFactory::getInstance( 'AbuseFilter' ),
222            $services->getBlockUserFactory(),
223            $services->getUnblockUserFactory(),
224            $services->getDatabaseBlockStore(),
225            $services->getUserGroupManager(),
226            $services->getMainObjectStash(),
227            $services->get( ChangeTagger::SERVICE_NAME ),
228            $services->get( BlockAutopromoteStore::SERVICE_NAME ),
229            $services->get( FilterUser::SERVICE_NAME ),
230            // TODO: Use a proper MessageLocalizer once available (T247127)
231            RequestContext::getMain(),
232            $services->getUserEditTracker(),
233            $services->getUserRegistrationLookup(),
234            $services->getUserIdentityUtils()
235        );
236    },
237    EditBoxBuilderFactory::SERVICE_NAME => static function ( MediaWikiServices $services ): EditBoxBuilderFactory {
238        $config = $services->getMainConfig();
239        return new EditBoxBuilderFactory(
240            $services->get( PermManager::SERVICE_NAME ),
241            $services->get( KeywordsManager::SERVICE_NAME ),
242            $config->get( 'AbuseFilterUseCodeEditor' ) && ExtensionRegistry::getInstance()->isLoaded( 'CodeEditor' ),
243            $config->get( 'AbuseFilterUseCodeMirror' ) && ExtensionRegistry::getInstance()->isLoaded( 'CodeMirror' )
244        );
245    },
246    ConsequencesLookup::SERVICE_NAME => static function ( MediaWikiServices $services ): ConsequencesLookup {
247        return new ConsequencesLookup(
248            $services->getDBLoadBalancerFactory(),
249            $services->get( CentralDBManager::SERVICE_NAME ),
250            $services->get( ConsequencesRegistry::SERVICE_NAME ),
251            LoggerFactory::getInstance( 'AbuseFilter' )
252        );
253    },
254    ConsequencesRegistry::SERVICE_NAME => static function ( MediaWikiServices $services ): ConsequencesRegistry {
255        return new ConsequencesRegistry(
256            $services->get( AbuseFilterHookRunner::SERVICE_NAME ),
257            $services->getMainConfig()->get( 'AbuseFilterActions' )
258        );
259    },
260    AbuseLoggerFactory::SERVICE_NAME => static function ( MediaWikiServices $services ): AbuseLoggerFactory {
261        return new AbuseLoggerFactory(
262            $services->get( CentralDBManager::SERVICE_NAME ),
263            $services->get( FilterLookup::SERVICE_NAME ),
264            $services->get( VariablesBlobStore::SERVICE_NAME ),
265            $services->get( VariablesManager::SERVICE_NAME ),
266            $services->get( EditRevUpdater::SERVICE_NAME ),
267            $services->get( PermManager::SERVICE_NAME ),
268            $services->get( RuleCheckerFactory::SERVICE_NAME ),
269            $services->getDBLoadBalancerFactory(),
270            $services->getActorStore(),
271            $services->getTitleFactory(),
272            new ServiceOptions(
273                AbuseLoggerFactory::CONSTRUCTOR_OPTIONS,
274                $services->getMainConfig()
275            ),
276            WikiMap::getCurrentWikiDbDomain()->getId(),
277            RequestContext::getMain()->getRequest()->getIP(),
278            LoggerFactory::getInstance( 'AbuseFilter' ),
279            $services->get( AbuseFilterHookRunner::SERVICE_NAME )
280        );
281    },
282    UpdateHitCountWatcher::SERVICE_NAME => static function ( MediaWikiServices $services ): UpdateHitCountWatcher {
283        return new UpdateHitCountWatcher(
284            $services->getDBLoadBalancerFactory(),
285            $services->get( CentralDBManager::SERVICE_NAME )
286        );
287    },
288    VariablesBlobStore::SERVICE_NAME => static function ( MediaWikiServices $services ): VariablesBlobStore {
289        return new VariablesBlobStore(
290            $services->get( VariablesManager::SERVICE_NAME ),
291            $services->get( PermManager::SERVICE_NAME ),
292            $services->getBlobStoreFactory(),
293            $services->getBlobStore(),
294            $services->getMainConfig()->get( 'AbuseFilterCentralDB' )
295        );
296    },
297    ConsExecutorFactory::SERVICE_NAME => static function ( MediaWikiServices $services ): ConsExecutorFactory {
298        return new ConsExecutorFactory(
299            $services->get( ConsequencesLookup::SERVICE_NAME ),
300            $services->get( ConsequencesFactory::SERVICE_NAME ),
301            $services->get( ConsequencesRegistry::SERVICE_NAME ),
302            $services->get( FilterLookup::SERVICE_NAME ),
303            LoggerFactory::getInstance( 'AbuseFilter' ),
304            $services->getUserIdentityUtils(),
305            new ServiceOptions(
306                ConsequencesExecutor::CONSTRUCTOR_OPTIONS,
307                $services->getMainConfig()
308            )
309        );
310    },
311    FilterRunnerFactory::SERVICE_NAME => static function ( MediaWikiServices $services ): FilterRunnerFactory {
312        return new FilterRunnerFactory(
313            $services->get( AbuseFilterHookRunner::SERVICE_NAME ),
314            $services->get( FilterProfiler::SERVICE_NAME ),
315            $services->get( ChangeTagger::SERVICE_NAME ),
316            $services->get( FilterLookup::SERVICE_NAME ),
317            $services->get( RuleCheckerFactory::SERVICE_NAME ),
318            $services->get( ConsExecutorFactory::SERVICE_NAME ),
319            $services->get( AbuseLoggerFactory::SERVICE_NAME ),
320            $services->get( VariablesManager::SERVICE_NAME ),
321            $services->get( EmergencyCache::SERVICE_NAME ),
322            $services->get( UpdateHitCountWatcher::SERVICE_NAME ),
323            $services->get( EmergencyWatcher::SERVICE_NAME ),
324            $services->getObjectCacheFactory()->getLocalClusterInstance(),
325            LoggerFactory::getInstance( 'AbuseFilter' ),
326            LoggerFactory::getInstance( 'StashEdit' ),
327            $services->getStatsdDataFactory(),
328            new ServiceOptions(
329                FilterRunner::CONSTRUCTOR_OPTIONS,
330                $services->getMainConfig()
331            )
332        );
333    },
334    VariablesFormatter::SERVICE_NAME => static function ( MediaWikiServices $services ): VariablesFormatter {
335        return new VariablesFormatter(
336            $services->get( KeywordsManager::SERVICE_NAME ),
337            $services->get( VariablesManager::SERVICE_NAME ),
338            // TODO: Use a proper MessageLocalizer once available (T247127)
339            RequestContext::getMain()
340        );
341    },
342    SpecsFormatter::SERVICE_NAME => static function ( MediaWikiServices $services ): SpecsFormatter {
343        return new SpecsFormatter(
344            // TODO: Use a proper MessageLocalizer once available (T247127)
345            RequestContext::getMain()
346        );
347    },
348    LazyVariableComputer::SERVICE_NAME => static function ( MediaWikiServices $services ): LazyVariableComputer {
349        return new LazyVariableComputer(
350            $services->get( TextExtractor::SERVICE_NAME ),
351            $services->get( AbuseFilterHookRunner::SERVICE_NAME ),
352            LoggerFactory::getInstance( 'AbuseFilter' ),
353            $services->getDBLoadBalancerFactory(),
354            $services->getMainWANObjectCache(),
355            $services->getRevisionLookup(),
356            $services->getRevisionStore(),
357            $services->getContentLanguage(),
358            $services->getParserFactory(),
359            $services->getUserEditTracker(),
360            $services->getUserGroupManager(),
361            $services->getPermissionManager(),
362            $services->getRestrictionStore(),
363            $services->getUserIdentityUtils(),
364            $services->getUserNameUtils(),
365            WikiMap::getCurrentWikiDbDomain()->getId()
366        );
367    },
368    TextExtractor::SERVICE_NAME => static function ( MediaWikiServices $services ): TextExtractor {
369        return new TextExtractor( $services->get( AbuseFilterHookRunner::SERVICE_NAME ) );
370    },
371    VariablesManager::SERVICE_NAME => static function ( MediaWikiServices $services ): VariablesManager {
372        return new VariablesManager(
373            $services->get( KeywordsManager::SERVICE_NAME ),
374            $services->get( LazyVariableComputer::SERVICE_NAME )
375        );
376    },
377    VariableGeneratorFactory::SERVICE_NAME => static function (
378        MediaWikiServices $services
379    ): VariableGeneratorFactory {
380        return new VariableGeneratorFactory(
381            $services->get( AbuseFilterHookRunner::SERVICE_NAME ),
382            $services->get( TextExtractor::SERVICE_NAME ),
383            $services->getMimeAnalyzer(),
384            $services->getRepoGroup(),
385            $services->getWikiPageFactory(),
386            $services->getUserFactory()
387        );
388    },
389    EditRevUpdater::SERVICE_NAME => static function ( MediaWikiServices $services ): EditRevUpdater {
390        return new EditRevUpdater(
391            $services->get( CentralDBManager::SERVICE_NAME ),
392            $services->getRevisionLookup(),
393            $services->getDBLoadBalancerFactory(),
394            WikiMap::getCurrentWikiDbDomain()->getId()
395        );
396    },
397    IBlockedDomainStorage::SERVICE_NAME => static function (
398        MediaWikiServices $services
399    ): IBlockedDomainStorage {
400        if ( $services->getExtensionRegistry()->isLoaded( 'CommunityConfiguration' ) ) {
401            $provider = CommunityConfigurationServices::wrap( $services )
402                ->getConfigurationProviderFactory()
403                ->newProvider( BlockedDomainConfigProvider::PROVIDER_ID );
404            if ( !$provider instanceof BlockedDomainConfigProvider ) {
405                throw new LogicException(
406                    BlockedDomainConfigProvider::PROVIDER_ID . ' is expected to be ' .
407                    'an instance of ' . BlockedDomainConfigProvider::class
408                );
409            }
410            return $provider;
411        } else {
412            return new CustomBlockedDomainStorage(
413                $services->getLocalServerObjectCache(),
414                $services->getRevisionLookup(),
415                $services->getWikiPageFactory(),
416                $services->get( BlockedDomainValidator::SERVICE_NAME )
417            );
418        }
419    },
420    BlockedDomainValidator::SERVICE_NAME => static function (
421        MediaWikiServices $services
422    ): BlockedDomainValidator {
423        return new BlockedDomainValidator(
424            $services->getUrlUtils()
425        );
426    },
427    IBlockedDomainFilter::SERVICE_NAME => static function (
428        MediaWikiServices $services
429    ): IBlockedDomainFilter {
430        if (
431            $services->getMainConfig()->get( 'AbuseFilterEnableBlockedExternalDomain' )
432        ) {
433            return new BlockedDomainFilter(
434                $services->get( VariablesManager::SERVICE_NAME ),
435                $services->get( IBlockedDomainStorage::SERVICE_NAME )
436            );
437        } else {
438            return new NoopBlockedDomainFilter();
439        }
440    },
441    AbuseFilterProtectedVariablesLookup::SERVICE_NAME => static function ( MediaWikiServices $services ) {
442        return new AbuseFilterProtectedVariablesLookup(
443            new ServiceOptions(
444                AbuseFilterProtectedVariablesLookup::CONSTRUCTOR_OPTIONS,
445                $services->getMainConfig()
446            ),
447            $services->get( AbuseFilterHookRunner::SERVICE_NAME )
448        );
449    },
450    AbuseFilterLogDetailsLookup::SERVICE_NAME => static function ( MediaWikiServices $services ) {
451        return new AbuseFilterLogDetailsLookup(
452            $services->getConnectionProvider(),
453            $services->get( PermManager::SERVICE_NAME ),
454            $services->get( FilterLookup::SERVICE_NAME )
455        );
456    },
457    AbuseLogConditionFactory::SERVICE_NAME => static function (
458        MediaWikiServices $services
459    ): AbuseLogConditionFactory {
460        return new AbuseLogConditionFactory(
461            $services->getConnectionProvider(),
462            $services->getTempUserConfig()
463        );
464    },
465    TemporaryAccountIPsViewerSpecification::SERVICE_NAME => static function (
466        MediaWikiServices $services
467    ): TemporaryAccountIPsViewerSpecification {
468        return new TemporaryAccountIPsViewerSpecification(
469            $services->getTempUserConfig(),
470            $services->hasService( 'CheckUserPermissionManager' ) ?
471                $services->get( 'CheckUserPermissionManager' ) :
472                null
473        );
474    },
475    // b/c for extensions
476    'AbuseFilterRunnerFactory' => static function ( MediaWikiServices $services ): FilterRunnerFactory {
477        return $services->get( FilterRunnerFactory::SERVICE_NAME );
478    },
479];
480
481// @codeCoverageIgnoreEnd