Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.26% covered (warning)
89.26%
291 / 326
94.20% covered (success)
94.20%
211 / 224
CRAP
0.00% covered (danger)
0.00%
0 / 1
MediaWikiServices
89.26% covered (warning)
89.26%
291 / 326
94.20% covered (success)
94.20%
211 / 224
327.34
0.00% covered (danger)
0.00%
0 / 1
 allowGlobalInstance
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 disallowGlobalInstanceInUnitTests
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 allowGlobalInstanceAfterUnitTests
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 hasInstance
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 getInstance
30.00% covered (danger)
30.00%
3 / 10
0.00% covered (danger)
0.00%
0 / 1
9.49
 getService
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
3.33
 forceGlobalInstance
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 resetGlobalInstance
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
4.00
 salvage
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
4.25
 newInstance
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 disableStorageBackend
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 disableStorage
79.07% covered (warning)
79.07%
34 / 43
0.00% covered (danger)
0.00%
0 / 1
2.04
 isStorageDisabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 resetChildProcessServices
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 resetServiceForTesting
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
3.33
 failIfResetNotAllowed
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
6.17
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getActionFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorMigration
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorNormalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArchivedRevisionLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAuthManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAutoblockExemptionList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBacklinkCacheFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBadFileLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlobStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlobStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockActionInfo
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockErrorFormatter
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getBlockManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockPermissionCheckerFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockRestrictionStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockRestrictionStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockUserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockUtils
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBlockUtilsFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBootstrapConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBotPasswordStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCentralIdLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCentralIdLookupFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getChangeTagDefStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getChangeTagsStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getChronologyProtector
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCollationFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCommentFormatter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCommentParserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCommentStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConfigFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConfigRepository
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getConfigSchema
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConfiguredReadOnlyMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConnectionProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentHandlerFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentLanguage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentLanguageCode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentModelChangeFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentModelStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentRenderer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentTransformer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCriticalSectionProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDatabaseBlockStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDatabaseBlockStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDatabaseFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDateFormatterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDBLoadBalancer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDBLoadBalancerFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDBLoadBalancerFactoryConfigBuilder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDefaultOutputPipeline
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDeletePageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDomainEventDispatcher
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDomainEventSource
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEmailer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEmailUserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEventRelayerGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExtensionRegistry
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExternalStoreAccess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExternalStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFileBackendGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFormatterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGenderCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGlobalIdGenerator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGrantsInfo
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGrantsLocalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGroupPermissionsLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHideUserUtils
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHookContainer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHtmlCacheUpdater
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHtmlTransformFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHttpRequestFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getInterwikiLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIntroMessageBuilder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getJobFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getJobQueueGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getJobQueueGroupFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getJobRunner
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getJsonCodec
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageConverterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageFallback
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageNameUtils
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkBatchFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkRenderer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkRendererFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinksMigration
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkTargetLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLintErrorChecker
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLocalisationCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLocalServerObjectCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLockManagerGroupFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLogFormatterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMagicWordFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMainConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMainObjectStash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMainWANObjectCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMediaHandlerFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMergeHistoryFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMessageCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMessageFormatterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMicroStash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMimeAnalyzer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMovePageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNamespaceInfo
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNameTableStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getObjectCacheFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getObjectFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOldRevisionImporter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPageEditStash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPageProps
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPageRestHelperFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPageStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPageStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPageUpdaterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParser
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParserCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParserCacheFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParserOutputAccess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParsoidDataAccess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParsoidOutputStash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParsoidPageConfigFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParsoidParserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParsoidSiteConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPasswordFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPasswordReset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPerDbNameStatsdDataFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPermissionManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPingback
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPoolCounterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPreferencesFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPreloadedContentBuilder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getProxyLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRateLimiter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReadOnlyMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRedirectLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRedirectStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRenameUserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRepoGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getResourceLoader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRestrictionStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevertedTagUpdateManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionRenderer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionStoreFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRollbackPageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRowCommentFormatter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 newSearchEngine
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSearchEngineConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSearchEngineFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSearchResultThumbnailProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSessionManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getShellboxClientFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getShellCommandFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSignatureValidatorFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSiteLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSiteStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSkinFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSlotRoleRegistry
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSlotRoleStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSpamChecker
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSpecialPageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStatsdDataFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStatsFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTalkPageNotificationManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTempFSFileFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTempUserConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTempUserCreator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTidy
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTitleFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTitleFormatter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTitleMatcher
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTitleParser
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTracer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTrackingCategories
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUnblockUserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUndeletePageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUploadRevisionImporter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUrlUtils
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserEditTracker
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserGroupManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserGroupManagerFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserIdentityLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserIdentityUtils
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserNamePrefixSearch
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserNameUtils
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserOptionsLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserOptionsManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserRegistrationLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWatchedItemQueryService
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWatchedItemStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWatchlistManager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWikiExporterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWikiImporterFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWikiPageFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWikiRevisionOldRevisionImporter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWikiRevisionOldRevisionImporterNoUpdates
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWikiRevisionUploadImporter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWRStatsFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki;
22
23use ExternalStoreAccess;
24use ExternalStoreFactory;
25use JobQueueGroup;
26use JobRunner;
27use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
28use LocalisationCache;
29use LogFormatterFactory;
30use LogicException;
31use MediaHandlerFactory;
32use MediaWiki\Actions\ActionFactory;
33use MediaWiki\Auth\AuthManager;
34use MediaWiki\Block\AutoblockExemptionList;
35use MediaWiki\Block\BlockActionInfo;
36use MediaWiki\Block\BlockErrorFormatter;
37use MediaWiki\Block\BlockManager;
38use MediaWiki\Block\BlockPermissionCheckerFactory;
39use MediaWiki\Block\BlockRestrictionStore;
40use MediaWiki\Block\BlockRestrictionStoreFactory;
41use MediaWiki\Block\BlockUserFactory;
42use MediaWiki\Block\BlockUtils;
43use MediaWiki\Block\BlockUtilsFactory;
44use MediaWiki\Block\DatabaseBlockStore;
45use MediaWiki\Block\DatabaseBlockStoreFactory;
46use MediaWiki\Block\HideUserUtils;
47use MediaWiki\Block\UnblockUserFactory;
48use MediaWiki\Cache\BacklinkCacheFactory;
49use MediaWiki\Cache\GenderCache;
50use MediaWiki\Cache\HTMLCacheUpdater;
51use MediaWiki\Cache\LinkBatchFactory;
52use MediaWiki\Cache\LinkCache;
53use MediaWiki\Cache\UserCache;
54use MediaWiki\Category\TrackingCategories;
55use MediaWiki\ChangeTags\ChangeTagsStore;
56use MediaWiki\Collation\CollationFactory;
57use MediaWiki\CommentFormatter\CommentFormatter;
58use MediaWiki\CommentFormatter\CommentParserFactory;
59use MediaWiki\CommentFormatter\RowCommentFormatter;
60use MediaWiki\CommentStore\CommentStore;
61use MediaWiki\Config\Config;
62use MediaWiki\Config\ConfigFactory;
63use MediaWiki\Config\ConfigRepository;
64use MediaWiki\Config\GlobalVarConfig;
65use MediaWiki\Content\IContentHandlerFactory;
66use MediaWiki\Content\Renderer\ContentRenderer;
67use MediaWiki\Content\Transform\ContentTransformer;
68use MediaWiki\DomainEvent\DomainEventDispatcher;
69use MediaWiki\DomainEvent\DomainEventSource;
70use MediaWiki\Edit\ParsoidOutputStash;
71use MediaWiki\EditPage\IntroMessageBuilder;
72use MediaWiki\EditPage\PreloadedContentBuilder;
73use MediaWiki\EditPage\SpamChecker;
74use MediaWiki\Export\WikiExporterFactory;
75use MediaWiki\FileBackend\FileBackendGroup;
76use MediaWiki\FileBackend\FSFile\TempFSFileFactory;
77use MediaWiki\FileBackend\LockManager\LockManagerGroupFactory;
78use MediaWiki\HookContainer\HookContainer;
79use MediaWiki\HookContainer\HookRunner;
80use MediaWiki\Http\HttpRequestFactory;
81use MediaWiki\Installer\Pingback;
82use MediaWiki\Interwiki\InterwikiLookup;
83use MediaWiki\Interwiki\NullInterwikiLookup;
84use MediaWiki\JobQueue\JobFactory;
85use MediaWiki\JobQueue\JobQueueGroupFactory;
86use MediaWiki\Json\JsonCodec;
87use MediaWiki\Language\FormatterFactory;
88use MediaWiki\Language\Language;
89use MediaWiki\Language\LanguageCode;
90use MediaWiki\Languages\LanguageConverterFactory;
91use MediaWiki\Languages\LanguageFactory;
92use MediaWiki\Languages\LanguageFallback;
93use MediaWiki\Languages\LanguageNameUtils;
94use MediaWiki\Linker\LinkRenderer;
95use MediaWiki\Linker\LinkRendererFactory;
96use MediaWiki\Linker\LinksMigration;
97use MediaWiki\Linker\LinkTargetLookup;
98use MediaWiki\Mail\EmailUserFactory;
99use MediaWiki\Mail\IEmailer;
100use MediaWiki\OutputTransform\OutputTransformPipeline;
101use MediaWiki\Page\ContentModelChangeFactory;
102use MediaWiki\Page\DeletePageFactory;
103use MediaWiki\Page\File\BadFileLookup;
104use MediaWiki\Page\MergeHistoryFactory;
105use MediaWiki\Page\MovePageFactory;
106use MediaWiki\Page\PageProps;
107use MediaWiki\Page\PageStore;
108use MediaWiki\Page\PageStoreFactory;
109use MediaWiki\Page\ParserOutputAccess;
110use MediaWiki\Page\RedirectLookup;
111use MediaWiki\Page\RedirectStore;
112use MediaWiki\Page\RollbackPageFactory;
113use MediaWiki\Page\UndeletePageFactory;
114use MediaWiki\Page\WikiPageFactory;
115use MediaWiki\Parser\DateFormatterFactory;
116use MediaWiki\Parser\MagicWordFactory;
117use MediaWiki\Parser\Parser;
118use MediaWiki\Parser\ParserCache;
119use MediaWiki\Parser\ParserCacheFactory;
120use MediaWiki\Parser\ParserFactory;
121use MediaWiki\Parser\Parsoid\Config\DataAccess;
122use MediaWiki\Parser\Parsoid\Config\PageConfigFactory;
123use MediaWiki\Parser\Parsoid\Config\SiteConfig;
124use MediaWiki\Parser\Parsoid\HtmlTransformFactory;
125use MediaWiki\Parser\Parsoid\LintErrorChecker;
126use MediaWiki\Parser\Parsoid\ParsoidParserFactory;
127use MediaWiki\Password\PasswordFactory;
128use MediaWiki\Permissions\GrantsInfo;
129use MediaWiki\Permissions\GrantsLocalization;
130use MediaWiki\Permissions\GroupPermissionsLookup;
131use MediaWiki\Permissions\PermissionManager;
132use MediaWiki\Permissions\RateLimiter;
133use MediaWiki\Permissions\RestrictionStore;
134use MediaWiki\PoolCounter\PoolCounterFactory;
135use MediaWiki\Preferences\PreferencesFactory;
136use MediaWiki\Preferences\SignatureValidatorFactory;
137use MediaWiki\Registration\ExtensionRegistry;
138use MediaWiki\RenameUser\RenameUserFactory;
139use MediaWiki\Request\ProxyLookup;
140use MediaWiki\ResourceLoader\ResourceLoader;
141use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory;
142use MediaWiki\Revision\ArchivedRevisionLookup;
143use MediaWiki\Revision\RevisionFactory;
144use MediaWiki\Revision\RevisionLookup;
145use MediaWiki\Revision\RevisionRenderer;
146use MediaWiki\Revision\RevisionStore;
147use MediaWiki\Revision\RevisionStoreFactory;
148use MediaWiki\Revision\SlotRoleRegistry;
149use MediaWiki\Search\SearchResultThumbnailProvider;
150use MediaWiki\Search\TitleMatcher;
151use MediaWiki\Session\SessionManager;
152use MediaWiki\Settings\Config\ConfigSchema;
153use MediaWiki\Shell\CommandFactory;
154use MediaWiki\Shell\ShellboxClientFactory;
155use MediaWiki\Site\SiteLookup;
156use MediaWiki\Site\SiteStore;
157use MediaWiki\SpecialPage\SpecialPageFactory;
158use MediaWiki\Storage\BlobStore;
159use MediaWiki\Storage\BlobStoreFactory;
160use MediaWiki\Storage\NameTableStore;
161use MediaWiki\Storage\NameTableStoreFactory;
162use MediaWiki\Storage\PageEditStash;
163use MediaWiki\Storage\PageUpdaterFactory;
164use MediaWiki\Storage\RevertedTagUpdateManager;
165use MediaWiki\Tidy\TidyDriverBase;
166use MediaWiki\Title\NamespaceInfo;
167use MediaWiki\Title\TitleFactory;
168use MediaWiki\Title\TitleFormatter;
169use MediaWiki\Title\TitleParser;
170use MediaWiki\User\ActorMigration;
171use MediaWiki\User\ActorNormalization;
172use MediaWiki\User\ActorStore;
173use MediaWiki\User\ActorStoreFactory;
174use MediaWiki\User\BotPasswordStore;
175use MediaWiki\User\CentralId\CentralIdLookup;
176use MediaWiki\User\CentralId\CentralIdLookupFactory;
177use MediaWiki\User\Options\StaticUserOptionsLookup;
178use MediaWiki\User\Options\UserOptionsLookup;
179use MediaWiki\User\Options\UserOptionsManager;
180use MediaWiki\User\PasswordReset;
181use MediaWiki\User\Registration\UserRegistrationLookup;
182use MediaWiki\User\TalkPageNotificationManager;
183use MediaWiki\User\TempUser\RealTempUserConfig;
184use MediaWiki\User\TempUser\TempUserCreator;
185use MediaWiki\User\UserEditTracker;
186use MediaWiki\User\UserFactory;
187use MediaWiki\User\UserGroupManager;
188use MediaWiki\User\UserGroupManagerFactory;
189use MediaWiki\User\UserIdentityLookup;
190use MediaWiki\User\UserIdentityUtils;
191use MediaWiki\User\UserNamePrefixSearch;
192use MediaWiki\User\UserNameUtils;
193use MediaWiki\Utils\UrlUtils;
194use MediaWiki\Watchlist\WatchedItemQueryService;
195use MediaWiki\Watchlist\WatchedItemStoreInterface;
196use MediaWiki\Watchlist\WatchlistManager;
197use MessageCache;
198use MWLBFactory;
199use ObjectCacheFactory;
200use OldRevisionImporter;
201use RepoGroup;
202use SearchEngine;
203use SearchEngineConfig;
204use SearchEngineFactory;
205use SkinFactory;
206use UploadRevisionImporter;
207use WikiImporterFactory;
208use Wikimedia\EventRelayer\EventRelayerGroup;
209use Wikimedia\Message\IMessageFormatterFactory;
210use Wikimedia\Mime\MimeAnalyzer;
211use Wikimedia\NonSerializable\NonSerializableTrait;
212use Wikimedia\ObjectCache\BagOStuff;
213use Wikimedia\ObjectCache\WANObjectCache;
214use Wikimedia\ObjectFactory\ObjectFactory;
215use Wikimedia\Rdbms\ChronologyProtector;
216use Wikimedia\Rdbms\ConfiguredReadOnlyMode;
217use Wikimedia\Rdbms\DatabaseFactory;
218use Wikimedia\Rdbms\IConnectionProvider;
219use Wikimedia\Rdbms\ILoadBalancer;
220use Wikimedia\Rdbms\LBFactory;
221use Wikimedia\Rdbms\LBFactorySingle;
222use Wikimedia\Rdbms\LoadBalancerDisabled;
223use Wikimedia\Rdbms\ReadOnlyMode;
224use Wikimedia\RequestTimeout\CriticalSectionProvider;
225use Wikimedia\Services\NoSuchServiceException;
226use Wikimedia\Services\SalvageableService;
227use Wikimedia\Services\ServiceContainer;
228use Wikimedia\Stats\IBufferingStatsdDataFactory;
229use Wikimedia\Stats\StatsFactory;
230use Wikimedia\Telemetry\TracerInterface;
231use Wikimedia\UUID\GlobalIdGenerator;
232use Wikimedia\WRStats\WRStatsFactory;
233
234/**
235 * Service locator for MediaWiki core services.
236 *
237 * Refer to includes/ServiceWiring.php for the default implementations.
238 *
239 * @see [Dependency Injection](@ref dependencyinjection) in docs/Injection.md
240 * for the principles of DI and how to use it MediaWiki core.
241 *
242 * @since 1.27
243 */
244class MediaWikiServices extends ServiceContainer {
245    use NonSerializableTrait;
246
247    /**
248     * @var bool
249     */
250    private static $globalInstanceAllowed = false;
251
252    /**
253     * @var self|null
254     */
255    private static $instance = null;
256
257    /**
258     * @see disableStorage()
259     * @var bool
260     */
261    private bool $storageDisabled = false;
262
263    /**
264     * Allows a global service container instance to exist.
265     *
266     * This should be called only after configuration settings have been read and extensions
267     * have been registered. Any change made to configuration after this method has been called
268     * may be ineffective or even harmful.
269     *
270     * @see getInstance()
271     *
272     * @since 1.36
273     */
274    public static function allowGlobalInstance() {
275        self::$globalInstanceAllowed = true;
276
277        if ( self::$instance ) {
278            // TODO: in 1.37, getInstance() should fail if $globalInstanceAllowed is false! (T153256)
279            // Until then, we have to reset service instances that have already been created.
280            // No need to warn here, getService() has already triggered a deprecation warning.
281            self::resetGlobalInstance( null, 'quick' );
282        }
283    }
284
285    /**
286     * @internal Should only be used in MediaWikiUnitTestCase
287     */
288    public static function disallowGlobalInstanceInUnitTests(): void {
289        if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
290            throw new LogicException( 'Can only be called in tests' );
291        }
292        self::$globalInstanceAllowed = false;
293    }
294
295    /**
296     * @internal Should only be used in MediaWikiUnitTestCase
297     */
298    public static function allowGlobalInstanceAfterUnitTests(): void {
299        if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
300            throw new LogicException( 'Can only be called in tests' );
301        }
302        self::$globalInstanceAllowed = true;
303    }
304
305    /**
306     * Returns true if an instance has already been initialized and can be
307     * obtained from getInstance(). This can be used to avoid accessing
308     * services if it's not safe or un necessary, e.g. in certain cases
309     * in unit tests or during early setup.
310     */
311    public static function hasInstance(): bool {
312        // NOTE: an instance could have been set by a call to forceGlobalInstance,
313        // but would still be unusable if $globalInstanceAllowed is false.
314        // This shouldn't happen, but it can during testing.
315        return self::$instance !== null && self::$globalInstanceAllowed;
316    }
317
318    /**
319     * Returns the global default instance of the top level service locator.
320     *
321     * @note if called before allowGlobalInstance(), this method will fail.
322     *
323     * @since 1.27
324     *
325     * The default instance is initialized using the service instantiator functions
326     * defined in ServiceWiring.php.
327     *
328     * @note This should only be called by static functions! The instance returned here
329     * should not be passed around! Objects that need access to a service should have
330     * that service injected into the constructor, never a service locator!
331     */
332    public static function getInstance(): self {
333        if ( !self::$globalInstanceAllowed ) {
334            if ( defined( 'MW_PHPUNIT_TEST' ) ) {
335                // Fail hard in PHPUnit tests only
336                throw new LogicException( 'Premature access to service container' );
337            }
338            // TODO: getInstance() should always fail if $globalInstanceAllowed is false! (T153256)
339            wfDeprecatedMsg( 'Premature access to service container', '1.36' );
340        }
341
342        if ( self::$instance === null ) {
343            // NOTE: constructing GlobalVarConfig here is not particularly pretty,
344            // but some information from the global scope has to be injected here,
345            // even if it's just a file name or database credentials to load
346            // configuration from.
347            $bootstrapConfig = new GlobalVarConfig();
348            self::$instance = self::newInstance( $bootstrapConfig, 'load' );
349
350            // Provides a traditional hook point to allow extensions to configure services.
351            // NOTE: Ideally this would be in newInstance() but it causes an infinite run loop
352            $runner = new HookRunner( self::$instance->getHookContainer() );
353            $runner->onMediaWikiServices( self::$instance );
354        }
355        return self::$instance;
356    }
357
358    public function getService( $name ) {
359        // TODO: in 1.37, getInstance() should fail if $globalInstanceAllowed is false! (T153256)
360        if ( !self::$globalInstanceAllowed && $this === self::$instance ) {
361            wfDeprecatedMsg( "Premature access to service '$name'", '1.36', false, 3 );
362        }
363
364        return parent::getService( $name );
365    }
366
367    /**
368     * Replaces the global MediaWikiServices instance.
369     *
370     * @since 1.28
371     *
372     * @note This is for use in PHPUnit tests only!
373     *
374     * @param self $services The new MediaWikiServices object.
375     *
376     * @return self The old MediaWikiServices object, so it can be restored later.
377     */
378    public static function forceGlobalInstance( self $services ): self {
379        if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
380            throw new LogicException( __METHOD__ . ' must not be used outside unit tests.' );
381        }
382
383        $old = self::getInstance();
384        self::$instance = $services;
385
386        return $old;
387    }
388
389    /**
390     * Creates a new instance of MediaWikiServices and sets it as the global default
391     * instance. getInstance() will return a different MediaWikiServices object
392     * after every call to resetGlobalInstance().
393     *
394     * @since 1.28
395     *
396     * @warning This should not be used during normal operation. It is intended for use
397     * when the configuration has changed significantly since bootstrap time, e.g.
398     * during the installation process or during testing. The method must not be called after
399     * MW_SERVICE_BOOTSTRAP_COMPLETE has been defined in Setup.php, unless MW_PHPUNIT_TEST or
400     * MEDIAWIKI_INSTALL or RUN_MAINTENANCE_IF_MAIN is defined).
401     *
402     * @warning Calling resetGlobalInstance() may leave the application in an inconsistent
403     * state. Calling this is only safe under the ASSUMPTION that NO REFERENCE to
404     * any of the services managed by MediaWikiServices exist. If any service objects
405     * managed by the old MediaWikiServices instance remain in use, they may INTERFERE
406     * with the operation of the services managed by the new MediaWikiServices.
407     * Operating with a mix of services created by the old and the new
408     * MediaWikiServices instance may lead to INCONSISTENCIES and even DATA LOSS!
409     * Any class implementing LAZY LOADING is especially prone to this problem,
410     * since instances would typically retain a reference to a storage layer service.
411     *
412     * @see forceGlobalInstance()
413     * @see resetGlobalInstance()
414     * @see resetBetweenTest()
415     *
416     * @param Config|null $bootstrapConfig The Config object to be registered as the
417     *        'BootstrapConfig' service. This has to contain at least the information
418     *        needed to set up the 'ConfigFactory' service. If not given, the bootstrap
419     *        config of the old instance of MediaWikiServices will be re-used. If there
420     *        was no previous instance, a new GlobalVarConfig object will be used to
421     *        bootstrap the services.
422     * @param string $mode May be one of:
423     *   - quick: allow expensive resources to be re-used. See SalvageableService for details.
424     *   - reset: discard expensive resources but reuse service wiring (default)
425     *   - reload: discard expensive resources and reload the service wiring
426     */
427    public static function resetGlobalInstance( ?Config $bootstrapConfig = null, $mode = 'reset' ) {
428        if ( self::$instance === null ) {
429            // no global instance yet, nothing to reset
430            return;
431        }
432
433        self::failIfResetNotAllowed( __METHOD__ );
434
435        $oldInstance = self::$instance;
436        self::$instance = self::newInstance(
437            $bootstrapConfig ?? self::$instance->getBootstrapConfig(),
438            'load'
439        );
440
441        // Provides a traditional hook point to allow extensions to configure services.
442        $runner = new HookRunner( $oldInstance->getHookContainer() );
443        $runner->onMediaWikiServices( self::$instance );
444
445        if ( $mode !== 'reload' ) {
446            self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
447        }
448
449        if ( $mode === 'quick' ) {
450            self::$instance->salvage( $oldInstance );
451        } else {
452            $oldInstance->destroy();
453        }
454    }
455
456    /** @noinspection PhpDocSignatureInspection */
457
458    /**
459     * Salvages the state of any salvageable service instances in $other.
460     *
461     * @note $other will have been destroyed when salvage() returns.
462     */
463    private function salvage( self $other ) {
464        foreach ( $this->getServiceNames() as $name ) {
465            // The service could be new in the new instance and not registered in the
466            // other instance (e.g. an extension that was loaded after the instantiation of
467            // the other instance. Skip this service in this case. See T143974
468            try {
469                $oldService = $other->peekService( $name );
470            } catch ( NoSuchServiceException $e ) {
471                continue;
472            }
473
474            if ( $oldService instanceof SalvageableService ) {
475                /** @var SalvageableService $newService */
476                $newService = $this->getService( $name );
477                $newService->salvage( $oldService );
478            }
479        }
480
481        $other->destroy();
482    }
483
484    /**
485     * Creates a new MediaWikiServices instance and initializes it according to the
486     * given $bootstrapConfig. In particular, all wiring files defined in the
487     * ServiceWiringFiles setting are loaded, and the MediaWikiServices hook is called.
488     *
489     * @param Config $bootstrapConfig The Config object to be registered as the
490     *        'BootstrapConfig' service.
491     * @param string $loadWiring set this to 'load' to load the wiring files specified
492     *        in the 'ServiceWiringFiles' setting in $bootstrapConfig.
493     */
494    private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ): self {
495        $instance = new self( $bootstrapConfig );
496
497        // Load the default wiring from the specified files.
498        if ( $loadWiring === 'load' ) {
499            $wiringFiles = $bootstrapConfig->get( MainConfigNames::ServiceWiringFiles );
500            $instance->loadWiringFiles( $wiringFiles );
501        }
502
503        return $instance;
504    }
505
506    /**
507     * Disables all storage layer services. After calling this, any attempt to access the
508     * storage layer will result in an error.
509     *
510     * @since 1.28
511     * @deprecated since 1.40, use disableStorage() instead.
512     *
513     * @warning This is intended for extreme situations, see the documentation of disableStorage() for details.
514     *
515     * @see resetGlobalInstance()
516     * @see resetChildProcessServices()
517     */
518    public static function disableStorageBackend() {
519        $services = self::getInstance();
520        $services->disableStorage();