1<?php
2
3namespace MediaWiki;
4
5use ActorMigration;
6use BagOStuff;
7use CentralIdLookup;
8use CommentStore;
9use Config;
10use ConfigFactory;
11use ConfiguredReadOnlyMode;
12use CryptHKDF;
13use DateFormatterFactory;
14use EventRelayerGroup;
15use ExternalStoreAccess;
16use ExternalStoreFactory;
17use FileBackendGroup;
18use GenderCache;
19use GlobalVarConfig;
20use HtmlCacheUpdater;
21use IBufferingStatsdDataFactory;
22use JobQueueGroup;
23use JobRunner;
24use Language;
25use LinkCache;
26use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
27use LocalisationCache;
28use MagicWordFactory;
29use MediaHandlerFactory;
30use MediaWiki\Actions\ActionFactory;
31use MediaWiki\Auth\AuthManager;
32use MediaWiki\Block\BlockActionInfo;
33use MediaWiki\Block\BlockErrorFormatter;
34use MediaWiki\Block\BlockManager;
35use MediaWiki\Block\BlockPermissionCheckerFactory;
36use MediaWiki\Block\BlockRestrictionStore;
37use MediaWiki\Block\BlockUserFactory;
38use MediaWiki\Block\BlockUtils;
39use MediaWiki\Block\DatabaseBlockStore;
40use MediaWiki\Block\UnblockUserFactory;
41use MediaWiki\Cache\BacklinkCacheFactory;
42use MediaWiki\Cache\LinkBatchFactory;
43use MediaWiki\Collation\CollationFactory;
44use MediaWiki\Config\ConfigRepository;
45use MediaWiki\Content\IContentHandlerFactory;
46use MediaWiki\Content\Transform\ContentTransformer;
47use MediaWiki\EditPage\SpamChecker;
48use MediaWiki\FileBackend\FSFile\TempFSFileFactory;
49use MediaWiki\FileBackend\LockManager\LockManagerGroupFactory;
50use MediaWiki\HookContainer\HookContainer;
51use MediaWiki\HookContainer\HookRunner;
52use MediaWiki\Http\HttpRequestFactory;
53use MediaWiki\Interwiki\InterwikiLookup;
54use MediaWiki\JobQueue\JobQueueGroupFactory;
55use MediaWiki\Json\JsonCodec;
56use MediaWiki\Languages\LanguageConverterFactory;
57use MediaWiki\Languages\LanguageFactory;
58use MediaWiki\Languages\LanguageFallback;
59use MediaWiki\Languages\LanguageNameUtils;
60use MediaWiki\Linker\LinkRenderer;
61use MediaWiki\Linker\LinkRendererFactory;
62use MediaWiki\Mail\IEmailer;
63use MediaWiki\Page\ContentModelChangeFactory;
64use MediaWiki\Page\DeletePageFactory;
65use MediaWiki\Page\MergeHistoryFactory;
66use MediaWiki\Page\MovePageFactory;
67use MediaWiki\Page\PageStore;
68use MediaWiki\Page\PageStoreFactory;
69use MediaWiki\Page\ParserOutputAccess;
70use MediaWiki\Page\RollbackPageFactory;
71use MediaWiki\Page\WikiPageFactory;
72use MediaWiki\Parser\ParserCacheFactory;
73use MediaWiki\Permissions\GroupPermissionsLookup;
74use MediaWiki\Permissions\PermissionManager;
75use MediaWiki\Permissions\RestrictionStore;
76use MediaWiki\Preferences\PreferencesFactory;
77use MediaWiki\Revision\ContributionsLookup;
78use MediaWiki\Revision\RevisionFactory;
79use MediaWiki\Revision\RevisionLookup;
80use MediaWiki\Revision\RevisionRenderer;
81use MediaWiki\Revision\RevisionStore;
82use MediaWiki\Revision\RevisionStoreFactory;
83use MediaWiki\Revision\SlotRoleRegistry;
84use MediaWiki\Shell\CommandFactory;
85use MediaWiki\Shell\ShellboxClientFactory;
86use MediaWiki\SpecialPage\SpecialPageFactory;
87use MediaWiki\Storage\BlobStore;
88use MediaWiki\Storage\BlobStoreFactory;
89use MediaWiki\Storage\NameTableStore;
90use MediaWiki\Storage\NameTableStoreFactory;
91use MediaWiki\Storage\PageEditStash;
92use MediaWiki\Storage\PageUpdaterFactory;
93use MediaWiki\Storage\RevertedTagUpdateManager;
94use MediaWiki\Tidy\TidyDriverBase;
95use MediaWiki\User\ActorNormalization;
96use MediaWiki\User\ActorStore;
97use MediaWiki\User\ActorStoreFactory;
98use MediaWiki\User\BotPasswordStore;
99use MediaWiki\User\CentralId\CentralIdLookupFactory;
100use MediaWiki\User\TalkPageNotificationManager;
101use MediaWiki\User\UserEditTracker;
102use MediaWiki\User\UserFactory;
103use MediaWiki\User\UserGroupManager;
104use MediaWiki\User\UserGroupManagerFactory;
105use MediaWiki\User\UserIdentityLookup;
106use MediaWiki\User\UserNamePrefixSearch;
107use MediaWiki\User\UserNameUtils;
108use MediaWiki\User\UserOptionsLookup;
109use MediaWiki\User\UserOptionsManager;
110use MediaWiki\Watchlist\WatchlistManager;
111use MessageCache;
112use MimeAnalyzer;
113use MWException;
114use NamespaceInfo;
115use ObjectCache;
116use OldRevisionImporter;
117use PageProps;
118use Parser;
119use ParserCache;
120use ParserFactory;
121use PasswordFactory;
122use PasswordReset;
123use ProxyLookup;
124use ReadOnlyMode;
125use RepoGroup;
126use ResourceLoader;
127use SearchEngine;
128use SearchEngineConfig;
129use SearchEngineFactory;
130use SiteLookup;
131use SiteStore;
132use SkinFactory;
133use TitleFactory;
134use TitleFormatter;
135use TitleParser;
136use UploadRevisionImporter;
137use UserCache;
138use VirtualRESTServiceClient;
139use WANObjectCache;
140use WatchedItemQueryService;
141use WatchedItemStoreInterface;
142use WikiImporterFactory;
143use Wikimedia\Message\IMessageFormatterFactory;
144use Wikimedia\NonSerializable\NonSerializableTrait;
145use Wikimedia\ObjectFactory;
146use Wikimedia\Rdbms\ILoadBalancer;
147use Wikimedia\Rdbms\LBFactory;
148use Wikimedia\RequestTimeout\CriticalSectionProvider;
149use Wikimedia\Services\NoSuchServiceException;
150use Wikimedia\Services\SalvageableService;
151use Wikimedia\Services\ServiceContainer;
152use Wikimedia\UUID\GlobalIdGenerator;
153
154/**
155 * Service locator for MediaWiki core services.
156 *
157 * This program is free software; you can redistribute it and/or modify
158 * it under the terms of the GNU General Public License as published by
159 * the Free Software Foundation; either version 2 of the License, or
160 * (at your option) any later version.
161 *
162 * This program is distributed in the hope that it will be useful,
163 * but WITHOUT ANY WARRANTY; without even the implied warranty of
164 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165 * GNU General Public License for more details.
166 *
167 * You should have received a copy of the GNU General Public License along
168 * with this program; if not, write to the Free Software Foundation, Inc.,
169 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
170 * http://www.gnu.org/copyleft/gpl.html
171 *
172 * @file
173 *
174 * @since 1.27
175 */
176
177/**
178 * MediaWikiServices is the service locator for the application scope of MediaWiki.
179 * Its implemented as a simple configurable DI container.
180 * MediaWikiServices acts as a top level factory/registry for top level services, and builds
181 * the network of service objects that defines MediaWiki's application logic.
182 * It acts as an entry point to MediaWiki's dependency injection mechanism.
183 *
184 * Services are defined in the "wiring" array passed to the constructor,
185 * or by calling defineService().
186 *
187 * @see docs/Injection.md for an overview of using dependency injection in the
188 *      MediaWiki code base.
189 */
190class MediaWikiServices extends ServiceContainer {
191	use NonSerializableTrait;
192
193	/**
194	 * @var bool
195	 */
196	private static $globalInstanceAllowed = false;
197
198	/**
199	 * @var MediaWikiServices|null
200	 */
201	private static $instance = null;
202
203	/**
204	 * Allows a global service container instance to exist.
205	 *
206	 * This should be called only after configuration settings have been read and extensions
207	 * have been registered. Any change made to configuration after this method has been called
208	 * may be ineffective or even harmful.
209	 *
210	 * @see getInstance()
211	 *
212	 * @since 1.36
213	 */
214	public static function allowGlobalInstance() {
215		self::$globalInstanceAllowed = true;
216
217		if ( self::$instance ) {
218			// TODO: in 1.37, getInstance() should fail if $globalInstanceAllowed is false! (T153256)
219			// Until then, we have to reset service instances that have already been created.
220			// No need to warn here, getService() has already triggered a deprecation warning.
221			self::resetGlobalInstance( null, 'quick' );
222		}
223	}
224
225	/**
226	 * Returns true if an instance has already been initialized. This can be used to avoid accessing
227	 * services if it's not safe, such as in unit tests or early setup.
228	 *
229	 * @return bool
230	 */
231	public static function hasInstance() {
232		return self::$instance !== null;
233	}
234
235	/**
236	 * Returns the global default instance of the top level service locator.
237	 *
238	 * @note if called before allowGlobalInstance(), this method will fail.
239	 *
240	 * @since 1.27
241	 *
242	 * The default instance is initialized using the service instantiator functions
243	 * defined in ServiceWiring.php.
244	 *
245	 * @note This should only be called by static functions! The instance returned here
246	 * should not be passed around! Objects that need access to a service should have
247	 * that service injected into the constructor, never a service locator!
248	 *
249	 * @return MediaWikiServices
250	 */
251	public static function getInstance(): self {
252		// TODO: in 1.37, getInstance() should fail if $globalInstanceAllowed is false! (T153256)
253		if ( !self::$globalInstanceAllowed ) {
254			wfDeprecatedMsg( 'Premature access to service container', '1.36' );
255		}
256
257		if ( self::$instance === null ) {
258			// NOTE: constructing GlobalVarConfig here is not particularly pretty,
259			// but some information from the global scope has to be injected here,
260			// even if it's just a file name or database credentials to load
261			// configuration from.
262			$bootstrapConfig = new GlobalVarConfig();
263			self::$instance = self::newInstance( $bootstrapConfig, 'load' );
264
265			// Provides a traditional hook point to allow extensions to configure services.
266			// NOTE: Ideally this would be in newInstance() but it causes an infinite run loop
267			$runner = new HookRunner( self::$instance->getHookContainer() );
268			$runner->onMediaWikiServices( self::$instance );
269		}
270		return self::$instance;
271	}
272
273	public function getService( $name ) {
274		// TODO: in 1.37, getInstance() should fail if $globalInstanceAllowed is false! (T153256)
275		if ( !self::$globalInstanceAllowed && $this === self::$instance ) {
276			wfDeprecatedMsg( "Premature access to service '$name'", '1.36', false, 3 );
277		}
278
279		return parent::getService( $name );
280	}
281
282	/**
283	 * Replaces the global MediaWikiServices instance.
284	 *
285	 * @since 1.28
286	 *
287	 * @note This is for use in PHPUnit tests only!
288	 *
289	 * @throws MWException if called outside of PHPUnit tests.
290	 *
291	 * @param MediaWikiServices $services The new MediaWikiServices object.
292	 *
293	 * @return MediaWikiServices The old MediaWikiServices object, so it can be restored later.
294	 */
295	public static function forceGlobalInstance( MediaWikiServices $services ) {
296		if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
297			throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
298		}
299
300		$old = self::getInstance();
301		self::$instance = $services;
302
303		return $old;
304	}
305
306	/**
307	 * Creates a new instance of MediaWikiServices and sets it as the global default
308	 * instance. getInstance() will return a different MediaWikiServices object
309	 * after every call to resetGlobalInstance().
310	 *
311	 * @since 1.28
312	 *
313	 * @warning This should not be used during normal operation. It is intended for use
314	 * when the configuration has changed significantly since bootstrap time, e.g.
315	 * during the installation process or during testing.
316	 *
317	 * @warning Calling resetGlobalInstance() may leave the application in an inconsistent
318	 * state. Calling this is only safe under the ASSUMPTION that NO REFERENCE to
319	 * any of the services managed by MediaWikiServices exist. If any service objects
320	 * managed by the old MediaWikiServices instance remain in use, they may INTERFERE
321	 * with the operation of the services managed by the new MediaWikiServices.
322	 * Operating with a mix of services created by the old and the new
323	 * MediaWikiServices instance may lead to INCONSISTENCIES and even DATA LOSS!
324	 * Any class implementing LAZY LOADING is especially prone to this problem,
325	 * since instances would typically retain a reference to a storage layer service.
326	 *
327	 * @see forceGlobalInstance()
328	 * @see resetGlobalInstance()
329	 * @see resetBetweenTest()
330	 *
331	 * @param Config|null $bootstrapConfig The Config object to be registered as the
332	 *        'BootstrapConfig' service. This has to contain at least the information
333	 *        needed to set up the 'ConfigFactory' service. If not given, the bootstrap
334	 *        config of the old instance of MediaWikiServices will be re-used. If there
335	 *        was no previous instance, a new GlobalVarConfig object will be used to
336	 *        bootstrap the services.
337	 *
338	 * @param string $quick Set this to "quick" to allow expensive resources to be re-used.
339	 * See SalvageableService for details.
340	 *
341	 * @throws MWException If called after MW_SERVICE_BOOTSTRAP_COMPLETE has been defined in
342	 *         Setup.php (unless MW_PHPUNIT_TEST or MEDIAWIKI_INSTALL or RUN_MAINTENANCE_IF_MAIN
343	 *          is defined).
344	 */
345	public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
346		if ( self::$instance === null ) {
347			// no global instance yet, nothing to reset
348			return;
349		}
350
351		self::failIfResetNotAllowed( __METHOD__ );
352
353		if ( $bootstrapConfig === null ) {
354			$bootstrapConfig = self::$instance->getBootstrapConfig();
355		}
356
357		$oldInstance = self::$instance;
358
359		self::$instance = self::newInstance( $bootstrapConfig, 'load' );
360
361		// Provides a traditional hook point to allow extensions to configure services.
362		$runner = new HookRunner( $oldInstance->getHookContainer() );
363		$runner->onMediaWikiServices( self::$instance );
364
365		self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
366
367		if ( $quick === 'quick' ) {
368			self::$instance->salvage( $oldInstance );
369		} else {
370			$oldInstance->destroy();
371		}
372	}
373
374	/** @noinspection PhpDocSignatureInspection */
375
376	/**
377	 * Salvages the state of any salvageable service instances in $other.
378	 *
379	 * @note $other will have been destroyed when salvage() returns.
380	 *
381	 * @param MediaWikiServices $other
382	 */
383	private function salvage( self $other ) {
384		foreach ( $this->getServiceNames() as $name ) {
385			// The service could be new in the new instance and not registered in the
386			// other instance (e.g. an extension that was loaded after the instantiation of
387			// the other instance. Skip this service in this case. See T143974
388			try {
389				$oldService = $other->peekService( $name );
390			} catch ( NoSuchServiceException $e ) {
391				continue;
392			}
393
394			if ( $oldService instanceof SalvageableService ) {
395				/** @var SalvageableService $newService */
396				$newService = $this->getService( $name );
397				$newService->salvage( $oldService );
398			}
399		}
400
401		$other->destroy();
402	}
403
404	/**
405	 * Creates a new MediaWikiServices instance and initializes it according to the
406	 * given $bootstrapConfig. In particular, all wiring files defined in the
407	 * ServiceWiringFiles setting are loaded, and the MediaWikiServices hook is called.
408	 *
409	 * @param Config $bootstrapConfig The Config object to be registered as the
410	 *        'BootstrapConfig' service.
411	 *
412	 * @param string $loadWiring set this to 'load' to load the wiring files specified
413	 *        in the 'ServiceWiringFiles' setting in $bootstrapConfig.
414	 *
415	 * @return MediaWikiServices
416	 * @throws MWException
417	 * @throws \FatalError
418	 */
419	private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
420		$instance = new self( $bootstrapConfig );
421
422		// Load the default wiring from the specified files.
423		if ( $loadWiring === 'load' ) {
424			$wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
425			$instance->loadWiringFiles( $wiringFiles );
426		}
427
428		return $instance;
429	}
430
431	/**
432	 * Disables all storage layer services. After calling this, any attempt to access the
433	 * storage layer will result in an error. Use resetGlobalInstance() to restore normal
434	 * operation.
435	 *
436	 * @since 1.28
437	 *
438	 * @warning This is intended for extreme situations only and should never be used
439	 * while serving normal web requests. Legitimate use cases for this method include
440	 * the installation process. Test fixtures may also use this, if the fixture relies
441	 * on globalState.
442	 *
443	 * @see resetGlobalInstance()
444	 * @see resetChildProcessServices()
445	 */
446	public static function disableStorageBackend() {
447		// TODO: also disable some Caches, JobQueues, etc
448		$destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
449		$services = self::getInstance();
450
451		foreach ( $destroy as $name ) {
452			$services->disableService( $name );
453		}
454
455		ObjectCache::clear();
456	}
457
458	/**
459	 * Resets any services that may have become stale after a child process
460	 * returns from after pcntl_fork(). It's also safe, but generally unnecessary,
461	 * to call this method from the parent process.
462	 *
463	 * @since 1.28
464	 *
465	 * @note This is intended for use in the context of process forking only!
466	 *
467	 * @see resetGlobalInstance()
468	 * @see disableStorageBackend()
469	 */
470	public static function resetChildProcessServices() {
471		// NOTE: for now, just reset everything. Since we don't know the interdependencies
472		// between services, we can't do this more selectively at this time.
473		self::resetGlobalInstance();
474
475		// Child, reseed because there is no bug in PHP:
476		// https://bugs.php.net/bug.php?id=42465
477		mt_srand( getmypid() );
478	}
479
480	/**
481	 * Resets the given service for testing purposes.
482	 *
483	 * @since 1.28
484	 *
485	 * @warning This is generally unsafe! Other services may still retain references
486	 * to the stale service instance, leading to failures and inconsistencies. Subclasses
487	 * may use this method to reset specific services under specific instances, but
488	 * it should not be exposed to application logic.
489	 *
490	 * @note With proper dependency injection used throughout the codebase, this method
491	 * should not be needed. It is provided to allow tests that pollute global service
492	 * instances to clean up.
493	 *
494	 * @param string $name
495	 * @param bool $destroy Whether the service instance should be destroyed if it exists.
496	 *        When set to false, any existing service instance will effectively be detached
497	 *        from the container.
498	 *
499	 * @throws MWException if called outside of PHPUnit tests.
500	 */
501	public function resetServiceForTesting( $name, $destroy = true ) {
502		if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
503			throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
504		}
505
506		$this->resetService( $name, $destroy );
507	}
508
509	/**
510	 * Convenience method that throws an exception unless it is called during a phase in which
511	 * resetting of global services is allowed. In general, services should not be reset
512	 * individually, since that may introduce inconsistencies.
513	 *
514	 * @since 1.28
515	 *
516	 * This method will throw an exception if:
517	 *
518	 * - self::$resetInProgress is false (to allow all services to be reset together
519	 *   via resetGlobalInstance)
520	 * - and MEDIAWIKI_INSTALL is not defined (to allow services to be reset during installation)
521	 * - and MW_PHPUNIT_TEST is not defined (to allow services to be reset during testing)
522	 *
523	 * This method is intended to be used to safeguard against accidentally resetting
524	 * global service instances that are not yet managed by MediaWikiServices. It is
525	 * defined here in the MediaWikiServices services class to have a central place
526	 * for managing service bootstrapping and resetting.
527	 *
528	 * @param string $method the name of the caller method, as given by __METHOD__.
529	 *
530	 * @throws MWException if called outside bootstrap mode.
531	 *
532	 * @see resetGlobalInstance()
533	 * @see forceGlobalInstance()
534	 * @see disableStorageBackend()
535	 */
536	public static function failIfResetNotAllowed( $method ) {
537		if ( !defined( 'MW_PHPUNIT_TEST' )
538			&& !defined( 'MW_PARSER_TEST' )
539			&& !defined( 'MEDIAWIKI_INSTALL' )
540			&& !defined( 'RUN_MAINTENANCE_IF_MAIN' )
541			&& defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
542		) {
543			throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
544		}
545	}
546
547	/**
548	 * @param Config $config The Config object to be registered as the 'BootstrapConfig' service.
549	 *        This has to contain at least the information needed to set up the 'ConfigFactory'
550	 *        service.
551	 */
552	public function __construct( Config $config ) {
553		parent::__construct();
554
555		// Register the given Config object as the bootstrap config service.
556		$this->defineService( 'BootstrapConfig', static function () use ( $config ) {
557			return $config;
558		} );
559	}
560
561	// CONVENIENCE GETTERS ////////////////////////////////////////////////////
562
563	/**
564	 * @since 1.37
565	 * @return ActionFactory
566	 */
567	public function getActionFactory(): ActionFactory {
568		return $this->getService( 'ActionFactory' );
569	}
570
571	/**
572	 * @since 1.31
573	 * @return ActorMigration
574	 */
575	public function getActorMigration(): ActorMigration {
576		return $this->getService( 'ActorMigration' );
577	}
578
579	/**
580	 * @return ActorNormalization
581	 * @since 1.36
582	 */
583	public function getActorNormalization(): ActorNormalization {
584		return $this->getService( 'ActorNormalization' );
585	}
586
587	/**
588	 * @return ActorStore
589	 * @since 1.36
590	 */
591	public function getActorStore(): ActorStore {
592		return $this->getService( 'ActorStore' );
593	}
594
595	/**
596	 * @since 1.36
597	 * @return ActorStoreFactory
598	 */
599	public function getActorStoreFactory(): ActorStoreFactory {
600		return $this->getService( 'ActorStoreFactory' );
601	}
602
603	/**
604	 * @since 1.35
605	 * @return AuthManager
606	 */
607	public function getAuthManager(): AuthManager {
608		return $this->getService( 'AuthManager' );
609	}
610
611	/**
612	 * @since 1.37
613	 * @return BacklinkCacheFactory
614	 */
615	public function getBacklinkCacheFactory(): BacklinkCacheFactory {
616		return $this->getService( 'BacklinkCacheFactory' );
617	}
618
619	/**
620	 * @since 1.34
621	 * @return BadFileLookup
622	 */
623	public function getBadFileLookup(): BadFileLookup {
624		return $this->getService( 'BadFileLookup' );
625	}
626
627	/**
628	 * @since 1.31
629	 * @return BlobStore
630	 */
631	public function getBlobStore(): BlobStore {
632		return $this->getService( 'BlobStore' );
633	}
634
635	/**
636	 * @since 1.31
637	 * @return BlobStoreFactory
638	 */
639	public function getBlobStoreFactory(): BlobStoreFactory {
640		return $this->getService( 'BlobStoreFactory' );
641	}
642
643	/**
644	 * @since 1.37
645	 * @return BlockActionInfo
646	 */
647	public function getBlockActionInfo(): BlockActionInfo {
648		return $this->getService( 'BlockActionInfo' );
649	}
650
651	/**
652	 * @since 1.35
653	 * @return BlockErrorFormatter
654	 */
655	public function getBlockErrorFormatter(): BlockErrorFormatter {
656		return $this->getService( 'BlockErrorFormatter' );
657	}
658
659	/**
660	 * @since 1.34
661	 * @return BlockManager
662	 */
663	public function getBlockManager(): BlockManager {
664		return $this->getService( 'BlockManager' );
665	}
666
667	/**
668	 * @since 1.35
669	 * @return BlockPermissionCheckerFactory
670	 */
671	public function getBlockPermissionCheckerFactory(): BlockPermissionCheckerFactory {
672		return $this->getService( 'BlockPermissionCheckerFactory' );
673	}
674
675	/**
676	 * @since 1.33
677	 * @return BlockRestrictionStore
678	 */
679	public function getBlockRestrictionStore(): BlockRestrictionStore {
680		return $this->getService( 'BlockRestrictionStore' );
681	}
682
683	/**
684	 * @since 1.36
685	 * @return BlockUserFactory
686	 */
687	public function getBlockUserFactory(): BlockUserFactory {
688		return $this->getService( 'BlockUserFactory' );
689	}
690
691	/**
692	 * @since 1.36
693	 * @return BlockUtils
694	 */
695	public function getBlockUtils(): BlockUtils {
696		return $this->getService( 'BlockUtils' );
697	}
698
699	/**
700	 * Returns the Config object containing the bootstrap configuration.
701	 * Bootstrap configuration would typically include database credentials
702	 * and other information that may be needed before the ConfigFactory
703	 * service can be instantiated.
704	 *
705	 * @note This should only be used during bootstrapping, in particular
706	 * when creating the MainConfig service. Application logic should
707	 * use getMainConfig() to get a Config instances.
708	 *
709	 * @since 1.27
710	 * @return Config
711	 */
712	public function getBootstrapConfig(): Config {
713		return $this->getService( 'BootstrapConfig' );
714	}
715
716	/**
717	 * @since 1.37
718	 * @return BotPasswordStore
719	 */
720	public function getBotPasswordStore(): BotPasswordStore {
721		return $this->getService( 'BotPasswordStore' );
722	}
723
724	/**
725	 * @since 1.37
726	 * @return CentralIdLookup
727	 */
728	public function getCentralIdLookup(): CentralIdLookup {
729		return $this->getService( 'CentralIdLookup' );
730	}
731
732	/**
733	 * @since 1.37
734	 * @return CentralIdLookupFactory
735	 */
736	public function getCentralIdLookupFactory(): CentralIdLookupFactory {
737		return $this->getService( 'CentralIdLookupFactory' );
738	}
739
740	/**
741	 * @since 1.32
742	 * @return NameTableStore
743	 */
744	public function getChangeTagDefStore(): NameTableStore {
745		return $this->getService( 'ChangeTagDefStore' );
746	}
747
748	/**
749	 * @since 1.37
750	 * @return CollationFactory
751	 */
752	public function getCollationFactory(): CollationFactory {
753		return $this->getService( 'CollationFactory' );
754	}
755
756	/**
757	 * @since 1.31
758	 * @return CommentStore
759	 */
760	public function getCommentStore(): CommentStore {
761		return $this->getService( 'CommentStore' );
762	}
763
764	/**
765	 * @since 1.27
766	 * @return ConfigFactory
767	 */
768	public function getConfigFactory(): ConfigFactory {
769		return $this->getService( 'ConfigFactory' );
770	}
771
772	/**
773	 * @since 1.32
774	 * @return ConfigRepository
775	 */
776	public function getConfigRepository(): ConfigRepository {
777		return $this->getService( 'ConfigRepository' );
778	}
779
780	/**
781	 * @since 1.29
782	 * @return ConfiguredReadOnlyMode
783	 */
784	public function getConfiguredReadOnlyMode(): ConfiguredReadOnlyMode {
785		return $this->getService( 'ConfiguredReadOnlyMode' );
786	}
787
788	/**
789	 * @since 1.35
790	 * @return IContentHandlerFactory
791	 */
792	public function getContentHandlerFactory(): IContentHandlerFactory {
793		return $this->getService( 'ContentHandlerFactory' );
794	}
795
796	/**
797	 * @since 1.32
798	 * @return Language
799	 */
800	public function getContentLanguage(): Language {
801		return $this->getService( 'ContentLanguage' );
802	}
803
804	/**
805	 * @since 1.35
806	 * @return ContentModelChangeFactory
807	 */
808	public function getContentModelChangeFactory(): ContentModelChangeFactory {
809		return $this->getService( 'ContentModelChangeFactory' );
810	}
811
812	/**
813	 * @since 1.31
814	 * @return NameTableStore
815	 */
816	public function getContentModelStore(): NameTableStore {
817		return $this->getService( 'ContentModelStore' );
818	}
819
820	/**
821	 * @since 1.37
822	 * @return ContentTransformer
823	 */
824	public function getContentTransformer(): ContentTransformer {
825		return $this->getService( 'ContentTransformer' );
826	}
827
828	/**
829	 * @since 1.35
830	 * @return ContributionsLookup
831	 */
832	public function getContributionsLookup(): ContributionsLookup {
833		return $this->getService( 'ContributionsLookup' );
834	}
835
836	/**
837	 * @since 1.36
838	 * @return CriticalSectionProvider
839	 */
840	public function getCriticalSectionProvider(): CriticalSectionProvider {
841		return $this->getService( 'CriticalSectionProvider' );
842	}
843
844	/**
845	 * @since 1.28
846	 * @return CryptHKDF
847	 */
848	public function getCryptHKDF(): CryptHKDF {
849		return $this->getService( 'CryptHKDF' );
850	}
851
852	/**
853	 * @since 1.36
854	 * @return DatabaseBlockStore
855	 */
856	public function getDatabaseBlockStore(): DatabaseBlockStore {
857		return $this->getService( 'DatabaseBlockStore' );
858	}
859
860	/**
861	 * @since 1.33
862	 * @return DateFormatterFactory
863	 */
864	public function getDateFormatterFactory(): DateFormatterFactory {
865		return $this->getService( 'DateFormatterFactory' );
866	}
867
868	/**
869	 * @since 1.28
870	 * @return ILoadBalancer The main DB load balancer for the local wiki.
871	 */
872	public function getDBLoadBalancer(): ILoadBalancer {
873		return $this->getService( 'DBLoadBalancer' );
874	}
875
876	/**
877	 * @since 1.28
878	 * @return LBFactory
879	 */
880	public function getDBLoadBalancerFactory(): LBFactory {
881		return $this->getService( 'DBLoadBalancerFactory' );
882	}
883
884	/**
885	 * @since 1.37
886	 * @return DeletePageFactory
887	 */
888	public function getDeletePageFactory(): DeletePageFactory {
889		return $this->getService( 'DeletePageFactory' );
890	}
891
892	/**
893	 * @since 1.35
894	 * @return IEmailer
895	 */
896	public function getEmailer(): IEmailer {
897		return $this->getService( 'Emailer' );
898	}
899
900	/**
901	 * @since 1.27
902	 * @return EventRelayerGroup
903	 */
904	public function getEventRelayerGroup(): EventRelayerGroup {
905		return $this->getService( 'EventRelayerGroup' );
906	}
907
908	/**
909	 * @since 1.34
910	 * @return ExternalStoreAccess
911	 */
912	public function getExternalStoreAccess(): ExternalStoreAccess {
913		return $this->getService( 'ExternalStoreAccess' );
914	}
915
916	/**
917	 * @since 1.31
918	 * @return ExternalStoreFactory
919	 */
920	public function getExternalStoreFactory(): ExternalStoreFactory {
921		return $this->getService( 'ExternalStoreFactory' );
922	}
923
924	/**
925	 * @since 1.35
926	 * @return FileBackendGroup
927	 */
928	public function getFileBackendGroup(): FileBackendGroup {
929		return $this->getService( 'FileBackendGroup' );
930	}
931
932	/**
933	 * @since 1.28
934	 * @return GenderCache
935	 */
936	public function getGenderCache(): GenderCache {
937		return $this->getService( 'GenderCache' );
938	}
939
940	/**
941	 * @since 1.35
942	 * @return GlobalIdGenerator
943	 */
944	public function getGlobalIdGenerator(): GlobalIdGenerator {
945		return $this->getService( 'GlobalIdGenerator' );
946	}
947
948	/**
949	 * @since 1.36
950	 * @return GroupPermissionsLookup
951	 */
952	public function getGroupPermissionsLookup(): GroupPermissionsLookup {
953		return $this->getService( 'GroupPermissionsLookup' );
954	}
955
956	/**
957	 * @since 1.35
958	 * @return HookContainer
959	 */
960	public function getHookContainer(): HookContainer {
961		return $this->getService( 'HookContainer' );
962	}
963
964	/**
965	 * @since 1.35
966	 * @return HtmlCacheUpdater
967	 */
968	public function getHtmlCacheUpdater(): HtmlCacheUpdater {
969		return $this->getService( 'HtmlCacheUpdater' );
970	}
971
972	/**
973	 * @since 1.31
974	 * @return HttpRequestFactory
975	 */
976	public function getHttpRequestFactory(): HttpRequestFactory {
977		return $this->getService( 'HttpRequestFactory' );
978	}
979
980	/**
981	 * @since 1.28
982	 * @return InterwikiLookup
983	 */
984	public function getInterwikiLookup(): InterwikiLookup {
985		return $this->getService( 'InterwikiLookup' );
986	}
987
988	/**
989	 * @since 1.37
990	 * @return JobQueueGroup
991	 */
992	public function getJobQueueGroup(): JobQueueGroup {
993		return $this->getService( 'JobQueueGroup' );
994	}
995
996	/**
997	 * @since 1.37
998	 * @return JobQueueGroupFactory
999	 */
1000	public function getJobQueueGroupFactory(): JobQueueGroupFactory {
1001		return $this->getService( 'JobQueueGroupFactory' );
1002	}
1003
1004	/**
1005	 * @since 1.35
1006	 * @return JobRunner
1007	 */
1008	public function getJobRunner(): JobRunner {
1009		return $this->getService( 'JobRunner' );
1010	}
1011
1012	/**
1013	 * @since 1.36
1014	 * @return JsonCodec
1015	 */
1016	public function getJsonCodec(): JsonCodec {
1017		return $this->getService( 'JsonCodec' );
1018	}
1019
1020	/**
1021	 * @since 1.35
1022	 * @return LanguageConverterFactory
1023	 */
1024	public function getLanguageConverterFactory(): LanguageConverterFactory {
1025		return $this->getService( 'LanguageConverterFactory' );
1026	}
1027
1028	/**
1029	 * @since 1.35
1030	 * @return LanguageFactory
1031	 */
1032	public function getLanguageFactory(): LanguageFactory {
1033		return $this->getService( 'LanguageFactory' );
1034	}
1035
1036	/**
1037	 * @since 1.35
1038	 * @return LanguageFallback
1039	 */
1040	public function getLanguageFallback(): LanguageFallback {
1041		return $this->getService( 'LanguageFallback' );
1042	}
1043
1044	/**
1045	 * @since 1.34
1046	 * @return LanguageNameUtils
1047	 */
1048	public function getLanguageNameUtils(): LanguageNameUtils {
1049		return $this->getService( 'LanguageNameUtils' );
1050	}
1051
1052	/**
1053	 * @since 1.35
1054	 * @return LinkBatchFactory
1055	 */
1056	public function getLinkBatchFactory(): LinkBatchFactory {
1057		return $this->getService( 'LinkBatchFactory' );
1058	}
1059
1060	/**
1061	 * @since 1.28
1062	 * @return LinkCache
1063	 */
1064	public function getLinkCache(): LinkCache {
1065		return $this->getService( 'LinkCache' );
1066	}
1067
1068	/**
1069	 * LinkRenderer instance that can be used
1070	 * if no custom options are needed
1071	 *
1072	 * @since 1.28
1073	 * @return LinkRenderer
1074	 */
1075	public function getLinkRenderer(): LinkRenderer {
1076		return $this->getService( 'LinkRenderer' );
1077	}
1078
1079	/**
1080	 * @since 1.28
1081	 * @return LinkRendererFactory
1082	 */
1083	public function getLinkRendererFactory(): LinkRendererFactory {
1084		return $this->getService( 'LinkRendererFactory' );
1085	}
1086
1087	/**
1088	 * @since 1.34
1089	 * @return LocalisationCache
1090	 */
1091	public function getLocalisationCache(): LocalisationCache {
1092		return $this->getService( 'LocalisationCache' );
1093	}
1094
1095	/**
1096	 * Returns the main server-local cache, yielding EmptyBagOStuff if there is none
1097	 *
1098	 * In web request mode, the cache should at least be shared among web workers.
1099	 * In CLI mode, the cache should at least be shared among processes run by the same user.
1100	 *
1101	 * @since 1.28
1102	 * @return BagOStuff
1103	 */
1104	public function getLocalServerObjectCache(): BagOStuff {
1105		return $this->getService( 'LocalServerObjectCache' );
1106	}
1107
1108	/**
1109	 * @since 1.34
1110	 * @return LockManagerGroupFactory
1111	 */
1112	public function getLockManagerGroupFactory(): LockManagerGroupFactory {
1113		return $this->getService( 'LockManagerGroupFactory' );
1114	}
1115
1116	/**
1117	 * @since 1.32
1118	 * @return MagicWordFactory
1119	 */
1120	public function getMagicWordFactory(): MagicWordFactory {
1121		return $this->getService( 'MagicWordFactory' );
1122	}
1123
1124	/**
1125	 * Returns the Config object that provides configuration for MediaWiki core.
1126	 * This may or may not be the same object that is returned by getBootstrapConfig().
1127	 *
1128	 * @since 1.27
1129	 * @return Config
1130	 */
1131	public function getMainConfig(): Config {
1132		return $this->getService( 'MainConfig' );
1133	}
1134
1135	/**
1136	 * Returns the main object stash, yielding EmptyBagOStuff if there is none
1137	 *
1138	 * The stash should be shared among all datacenters
1139	 *
1140	 * @since 1.28
1141	 * @return BagOStuff
1142	 */
1143	public function getMainObjectStash(): BagOStuff {
1144		return $this->getService( 'MainObjectStash' );
1145	}
1146
1147	/**
1148	 * Returns the main WAN cache, yielding EmptyBagOStuff if there is none
1149	 *
1150	 * The cache should relay any purge operations to all datacenterss
1151	 *
1152	 * @since 1.28
1153	 * @return WANObjectCache
1154	 */
1155	public function getMainWANObjectCache(): WANObjectCache {
1156		return $this->getService( 'MainWANObjectCache' );
1157	}
1158
1159	/**
1160	 * @since 1.28
1161	 * @return MediaHandlerFactory
1162	 */
1163	public function getMediaHandlerFactory(): MediaHandlerFactory {
1164		return $this->getService( 'MediaHandlerFactory' );
1165	}
1166
1167	/**
1168	 * @since 1.35
1169	 * @return MergeHistoryFactory
1170	 */
1171	public function getMergeHistoryFactory(): MergeHistoryFactory {
1172		return $this->getService( 'MergeHistoryFactory' );
1173	}
1174
1175	/**
1176	 * @since 1.34
1177	 * @return MessageCache
1178	 */
1179	public function getMessageCache(): MessageCache {
1180		return $this->getService( 'MessageCache' );
1181	}
1182
1183	/**
1184	 * @since 1.34
1185	 * @return IMessageFormatterFactory
1186	 */
1187	public function getMessageFormatterFactory(): IMessageFormatterFactory {
1188		return $this->getService( 'MessageFormatterFactory' );
1189	}
1190
1191	/**
1192	 * @since 1.28
1193	 * @return MimeAnalyzer
1194	 */
1195	public function getMimeAnalyzer(): MimeAnalyzer {
1196		return $this->getService( 'MimeAnalyzer' );
1197	}
1198
1199	/**
1200	 * @since 1.34
1201	 * @return MovePageFactory
1202	 */
1203	public function getMovePageFactory(): MovePageFactory {
1204		return $this->getService( 'MovePageFactory' );
1205	}
1206
1207	/**
1208	 * @since 1.34
1209	 * @return NamespaceInfo
1210	 */
1211	public function getNamespaceInfo(): NamespaceInfo {
1212		return $this->getService( 'NamespaceInfo' );
1213	}
1214
1215	/**
1216	 * @since 1.32
1217	 * @return NameTableStoreFactory
1218	 */
1219	public function getNameTableStoreFactory(): NameTableStoreFactory {
1220		return $this->getService( 'NameTableStoreFactory' );
1221	}
1222
1223	/**
1224	 * ObjectFactory is intended for instantiating "handlers" from declarative definitions,
1225	 * such as Action API modules, special pages, or REST API handlers.
1226	 *
1227	 * @since 1.34
1228	 * @return ObjectFactory
1229	 */
1230	public function getObjectFactory(): ObjectFactory {
1231		return $this->getService( 'ObjectFactory' );
1232	}
1233
1234	/**
1235	 * @since 1.32
1236	 * @return OldRevisionImporter
1237	 */
1238	public function getOldRevisionImporter(): OldRevisionImporter {
1239		return $this->getService( 'OldRevisionImporter' );
1240	}
1241
1242	/**
1243	 * @return PageEditStash
1244	 * @since 1.34
1245	 */
1246	public function getPageEditStash(): PageEditStash {
1247		return $this->getService( 'PageEditStash' );
1248	}
1249
1250	/**
1251	 * @return PageProps
1252	 * @since 1.36
1253	 */
1254	public function getPageProps(): PageProps {
1255		return $this->getService( 'PageProps' );
1256	}
1257
1258	/**
1259	 * @return PageStore
1260	 * @since 1.36
1261	 */
1262	public function getPageStore(): PageStore {
1263		return $this->getService( 'PageStore' );
1264	}
1265
1266	/**
1267	 * @return PageStoreFactory
1268	 * @since 1.36
1269	 */
1270	public function getPageStoreFactory(): PageStoreFactory {
1271		return $this->getService( 'PageStoreFactory' );
1272	}
1273
1274	/**
1275	 * @since 1.37
1276	 * @return PageUpdaterFactory
1277	 */
1278	public function getPageUpdaterFactory(): PageUpdaterFactory {
1279		return $this->getService( 'PageUpdaterFactory' );
1280	}
1281
1282	/**
1283	 * @since 1.29
1284	 * @return Parser
1285	 */
1286	public function getParser(): Parser {
1287		return $this->getService( 'Parser' );
1288	}
1289
1290	/**
1291	 * @since 1.30
1292	 * @return ParserCache
1293	 */
1294	public function getParserCache(): ParserCache {
1295		return $this->getService( 'ParserCache' );
1296	}
1297
1298	/**
1299	 * @since 1.36
1300	 * @return ParserCacheFactory
1301	 */
1302	public function getParserCacheFactory(): ParserCacheFactory {
1303		return $this->getService( 'ParserCacheFactory' );
1304	}
1305
1306	/**
1307	 * @since 1.32
1308	 * @return ParserFactory
1309	 */
1310	public function getParserFactory(): ParserFactory {
1311		return $this->getService( 'ParserFactory' );
1312	}
1313
1314	/**
1315	 * @return ParserOutputAccess
1316	 * @since 1.36
1317	 */
1318	public function getParserOutputAccess(): ParserOutputAccess {
1319		return $this->getService( 'ParserOutputAccess' );
1320	}
1321
1322	/**
1323	 * @since 1.32
1324	 * @return PasswordFactory
1325	 */
1326	public function getPasswordFactory(): PasswordFactory {
1327		return $this->getService( 'PasswordFactory' );
1328	}
1329
1330	/**
1331	 * @since 1.34
1332	 * @return PasswordReset
1333	 */
1334	public function getPasswordReset(): PasswordReset {
1335		return $this->getService( 'PasswordReset' );
1336	}
1337
1338	/**
1339	 * @since 1.32
1340	 * @return StatsdDataFactoryInterface
1341	 */
1342	public function getPerDbNameStatsdDataFactory(): StatsdDataFactoryInterface {
1343		return $this->getService( 'PerDbNameStatsdDataFactory' );
1344	}
1345
1346	/**
1347	 * @since 1.33
1348	 * @return PermissionManager
1349	 */
1350	public function getPermissionManager(): PermissionManager {
1351		return $this->getService( 'PermissionManager' );
1352	}
1353
1354	/**
1355	 * @since 1.31
1356	 * @return PreferencesFactory
1357	 */
1358	public function getPreferencesFactory(): PreferencesFactory {
1359		return $this->getService( 'PreferencesFactory' );
1360	}
1361
1362	/**
1363	 * @since 1.28
1364	 * @return ProxyLookup
1365	 */
1366	public function getProxyLookup(): ProxyLookup {
1367		return $this->getService( 'ProxyLookup' );
1368	}
1369
1370	/**
1371	 * @since 1.29
1372	 * @return ReadOnlyMode
1373	 */
1374	public function getReadOnlyMode(): ReadOnlyMode {
1375		return $this->getService( 'ReadOnlyMode' );
1376	}
1377
1378	/**
1379	 * @since 1.34
1380	 * @return RepoGroup
1381	 */
1382	public function getRepoGroup(): RepoGroup {
1383		return $this->getService( 'RepoGroup' );
1384	}
1385
1386	/**
1387	 * @since 1.33
1388	 * @return ResourceLoader
1389	 */
1390	public function getResourceLoader(): ResourceLoader {
1391		return $this->getService( 'ResourceLoader' );
1392	}
1393
1394	/**
1395	 * @since 1.37
1396	 * @return RestrictionStore
1397	 */
1398	public function getRestrictionStore(): RestrictionStore {
1399		return $this->getService( 'RestrictionStore' );
1400	}
1401
1402	/**
1403	 * @since 1.36
1404	 * @return RevertedTagUpdateManager
1405	 */
1406	public function getRevertedTagUpdateManager(): RevertedTagUpdateManager {
1407		return $this->getService( 'RevertedTagUpdateManager' );
1408	}
1409
1410	/**
1411	 * @since 1.31
1412	 * @return RevisionFactory
1413	 */
1414	public function getRevisionFactory(): RevisionFactory {
1415		return $this->getService( 'RevisionFactory' );
1416	}
1417
1418	/**
1419	 * @since 1.31
1420	 * @return RevisionLookup
1421	 */
1422	public function getRevisionLookup(): RevisionLookup {
1423		return $this->getService( 'RevisionLookup' );
1424	}
1425
1426	/**
1427	 * @since 1.32
1428	 * @return RevisionRenderer
1429	 */
1430	public function getRevisionRenderer(): RevisionRenderer {
1431		return $this->getService( 'RevisionRenderer' );
1432	}
1433
1434	/**
1435	 * @since 1.31
1436	 * @return RevisionStore
1437	 */
1438	public function getRevisionStore(): RevisionStore {
1439		return $this->getService( 'RevisionStore' );
1440	}
1441
1442	/**
1443	 * @since 1.32
1444	 * @return RevisionStoreFactory
1445	 */
1446	public function getRevisionStoreFactory(): RevisionStoreFactory {
1447		return $this->getService( 'RevisionStoreFactory' );
1448	}
1449
1450	/**
1451	 * @since 1.37
1452	 * @return RollbackPageFactory
1453	 */
1454	public function getRollbackPageFactory(): RollbackPageFactory {
1455		return $this->getService( 'RollbackPageFactory' );
1456	}
1457
1458	/**
1459	 * @since 1.27
1460	 * @return SearchEngine
1461	 */
1462	public function newSearchEngine(): SearchEngine {
1463		// New engine object every time, since they keep state
1464		return $this->getService( 'SearchEngineFactory' )->create();
1465	}
1466
1467	/**
1468	 * @since 1.27
1469	 * @return SearchEngineConfig
1470	 */
1471	public function getSearchEngineConfig(): SearchEngineConfig {
1472		return $this->getService( 'SearchEngineConfig' );
1473	}
1474
1475	/**
1476	 * @since 1.27
1477	 * @return SearchEngineFactory
1478	 */
1479	public function getSearchEngineFactory(): SearchEngineFactory {
1480		return $this->getService( 'SearchEngineFactory' );
1481	}
1482
1483	/**
1484	 * @since 1.36
1485	 * @return ShellboxClientFactory
1486	 */
1487	public function getShellboxClientFactory(): ShellboxClientFactory {
1488		return $this->getService( 'ShellboxClientFactory' );
1489	}
1490
1491	/**
1492	 * @since 1.30
1493	 * @return CommandFactory
1494	 */
1495	public function getShellCommandFactory(): CommandFactory {
1496		return $this->getService( 'ShellCommandFactory' );
1497	}
1498
1499	/**
1500	 * @since 1.27
1501	 * @return SiteLookup
1502	 */
1503	public function getSiteLookup(): SiteLookup {
1504		return $this->getService( 'SiteLookup' );
1505	}
1506
1507	/**
1508	 * @since 1.27
1509	 * @return SiteStore
1510	 */
1511	public function getSiteStore(): SiteStore {
1512		return $this->getService( 'SiteStore' );
1513	}
1514
1515	/**
1516	 * @since 1.27
1517	 * @return SkinFactory
1518	 */
1519	public function getSkinFactory(): SkinFactory {
1520		return $this->getService( 'SkinFactory' );
1521	}
1522
1523	/**
1524	 * @since 1.33
1525	 * @return SlotRoleRegistry
1526	 */
1527	public function getSlotRoleRegistry(): SlotRoleRegistry {
1528		return $this->getService( 'SlotRoleRegistry' );
1529	}
1530
1531	/**
1532	 * @since 1.31
1533	 * @return NameTableStore
1534	 */
1535	public function getSlotRoleStore(): NameTableStore {
1536		return $this->getService( 'SlotRoleStore' );
1537	}
1538
1539	/**
1540	 * @since 1.35
1541	 * @return SpamChecker
1542	 */
1543	public function getSpamChecker(): SpamChecker {
1544		return $this->getService( 'SpamChecker' );
1545	}
1546
1547	/**
1548	 * @since 1.32
1549	 * @return SpecialPageFactory
1550	 */
1551	public function getSpecialPageFactory(): SpecialPageFactory {
1552		return $this->getService( 'SpecialPageFactory' );
1553	}
1554
1555	/**
1556	 * @since 1.27
1557	 * @return IBufferingStatsdDataFactory
1558	 */
1559	public function getStatsdDataFactory(): IBufferingStatsdDataFactory {
1560		return $this->getService( 'StatsdDataFactory' );
1561	}
1562
1563	/**
1564	 * @since 1.35
1565	 * @return TalkPageNotificationManager
1566	 */
1567	public function getTalkPageNotificationManager(): TalkPageNotificationManager {
1568		return $this->getService( 'TalkPageNotificationManager' );
1569	}
1570
1571	/**
1572	 * @since 1.34
1573	 * @return TempFSFileFactory
1574	 */
1575	public function getTempFSFileFactory(): TempFSFileFactory {
1576		return $this->getService( 'TempFSFileFactory' );
1577	}
1578
1579	/**
1580	 * @since 1.36
1581	 * @return TidyDriverBase
1582	 */
1583	public function getTidy(): TidyDriverBase {
1584		return $this->getService( 'Tidy' );
1585	}
1586
1587	/**
1588	 * @since 1.35
1589	 * @return TitleFactory
1590	 */
1591	public function getTitleFactory(): TitleFactory {
1592		return $this->getService( 'TitleFactory' );
1593	}
1594
1595	/**
1596	 * @since 1.28
1597	 * @return TitleFormatter
1598	 */
1599	public function getTitleFormatter(): TitleFormatter {
1600		return $this->getService( 'TitleFormatter' );
1601	}
1602
1603	/**
1604	 * @since 1.28
1605	 * @return TitleParser
1606	 */
1607	public function getTitleParser(): TitleParser {
1608		return $this->getService( 'TitleParser' );
1609	}
1610
1611	/**
1612	 * @since 1.36
1613	 * @return UnblockUserFactory
1614	 */
1615	public function getUnblockUserFactory(): UnblockUserFactory {
1616		return $this->getService( 'UnblockUserFactory' );
1617	}
1618
1619	/**
1620	 * @since 1.32
1621	 * @return UploadRevisionImporter
1622	 */
1623	public function getUploadRevisionImporter(): UploadRevisionImporter {
1624		return $this->getService( 'UploadRevisionImporter' );
1625	}
1626
1627	/**
1628	 * @since 1.36
1629	 * @return UserCache
1630	 */
1631	public function getUserCache(): UserCache {
1632		return $this->getService( 'UserCache' );
1633	}
1634
1635	/**
1636	 * @since 1.35
1637	 * @return UserEditTracker
1638	 */
1639	public function getUserEditTracker(): UserEditTracker {
1640		return $this->getService( 'UserEditTracker' );
1641	}
1642
1643	/**
1644	 * @since 1.35
1645	 * @return UserFactory
1646	 */
1647	public function getUserFactory(): UserFactory {
1648		return $this->getService( 'UserFactory' );
1649	}
1650
1651	/**
1652	 * @since 1.35
1653	 * @return UserGroupManager
1654	 */
1655	public function getUserGroupManager(): UserGroupManager {
1656		return $this->getService( 'UserGroupManager' );
1657	}
1658
1659	/**
1660	 * @since 1.35
1661	 * @return UserGroupManagerFactory
1662	 */
1663	public function getUserGroupManagerFactory(): UserGroupManagerFactory {
1664		return $this->getService( 'UserGroupManagerFactory' );
1665	}
1666
1667	/**
1668	 * @since 1.36
1669	 * @return UserIdentityLookup
1670	 */
1671	public function getUserIdentityLookup(): UserIdentityLookup {
1672		return $this->getService( 'UserIdentityLookup' );
1673	}
1674
1675	/**
1676	 * @since 1.36
1677	 * @return UserNamePrefixSearch
1678	 */
1679	public function getUserNamePrefixSearch(): UserNamePrefixSearch {
1680		return $this->getService( 'UserNamePrefixSearch' );
1681	}
1682
1683	/**
1684	 * @since 1.35
1685	 * @return UserNameUtils
1686	 */
1687	public function getUserNameUtils(): UserNameUtils {
1688		return $this->getService( 'UserNameUtils' );
1689	}
1690
1691	/**
1692	 * @since 1.35
1693	 * @return UserOptionsLookup
1694	 */
1695	public function getUserOptionsLookup(): UserOptionsLookup {
1696		return $this->getService( 'UserOptionsLookup' );
1697	}
1698
1699	/**
1700	 * @since 1.35
1701	 * @return UserOptionsManager
1702	 */
1703	public function getUserOptionsManager(): UserOptionsManager {
1704		return $this->getService( 'UserOptionsManager' );
1705	}
1706
1707	/**
1708	 * @since 1.28
1709	 * @return VirtualRESTServiceClient
1710	 */
1711	public function getVirtualRESTServiceClient(): VirtualRESTServiceClient {
1712		return $this->getService( 'VirtualRESTServiceClient' );
1713	}
1714
1715	/**
1716	 * @since 1.28
1717	 * @return WatchedItemQueryService
1718	 */
1719	public function getWatchedItemQueryService(): WatchedItemQueryService {
1720		return $this->getService( 'WatchedItemQueryService' );
1721	}
1722
1723	/**
1724	 * @since 1.28
1725	 * @return WatchedItemStoreInterface
1726	 */
1727	public function getWatchedItemStore(): WatchedItemStoreInterface {
1728		return $this->getService( 'WatchedItemStore' );
1729	}
1730
1731	/**
1732	 * @since 1.35
1733	 * @return WatchlistManager
1734	 * @deprecated since 1.36 use getWatchlistManager() instead
1735	 */
1736	public function getWatchlistNotificationManager(): WatchlistManager {
1737		wfDeprecated( __METHOD__, '1.36' );
1738		return $this->getWatchlistManager();
1739	}
1740
1741	/**
1742	 * @since 1.36
1743	 * @return WatchlistManager
1744	 */
1745	public function getWatchlistManager(): WatchlistManager {
1746		return $this->getService( 'WatchlistManager' );
1747	}
1748
1749	/**
1750	 * @since 1.37
1751	 * @return WikiImporterFactory
1752	 */
1753	public function getWikiImporterFactory(): WikiImporterFactory {
1754		return $this->getService( 'WikiImporterFactory' );
1755	}
1756
1757	/**
1758	 * @since 1.36
1759	 * @return WikiPageFactory
1760	 */
1761	public function getWikiPageFactory(): WikiPageFactory {
1762		return $this->getService( 'WikiPageFactory' );
1763	}
1764
1765	/**
1766	 * @since 1.31
1767	 * @return OldRevisionImporter
1768	 */
1769	public function getWikiRevisionOldRevisionImporter(): OldRevisionImporter {
1770		return $this->getService( 'OldRevisionImporter' );
1771	}
1772
1773	/**
1774	 * @since 1.31
1775	 * @return OldRevisionImporter
1776	 */
1777	public function getWikiRevisionOldRevisionImporterNoUpdates(): OldRevisionImporter {
1778		return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
1779	}
1780
1781	/**
1782	 * @since 1.31
1783	 * @return UploadRevisionImporter
1784	 */
1785	public function getWikiRevisionUploadImporter(): UploadRevisionImporter {
1786		return $this->getService( 'UploadRevisionImporter' );
1787	}
1788
1789}
1790