Convert MessageCache to service
[lhc/web/wiklou.git] / includes / MediaWikiServices.php
1 <?php
2
3 namespace MediaWiki;
4
5 use ActorMigration;
6 use CommentStore;
7 use Config;
8 use ConfigFactory;
9 use CryptHKDF;
10 use DateFormatterFactory;
11 use EventRelayerGroup;
12 use GenderCache;
13 use GlobalVarConfig;
14 use Hooks;
15 use IBufferingStatsdDataFactory;
16 use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
17 use MediaWiki\Block\BlockManager;
18 use MediaWiki\Block\BlockRestrictionStore;
19 use MediaWiki\Http\HttpRequestFactory;
20 use MediaWiki\Permissions\PermissionManager;
21 use MediaWiki\Preferences\PreferencesFactory;
22 use MediaWiki\Shell\CommandFactory;
23 use MediaWiki\Revision\RevisionRenderer;
24 use MediaWiki\Revision\SlotRoleRegistry;
25 use MediaWiki\Special\SpecialPageFactory;
26 use MediaWiki\Storage\BlobStore;
27 use MediaWiki\Storage\BlobStoreFactory;
28 use MediaWiki\Storage\NameTableStore;
29 use MediaWiki\Storage\NameTableStoreFactory;
30 use MediaWiki\Revision\RevisionFactory;
31 use MediaWiki\Revision\RevisionLookup;
32 use MediaWiki\Revision\RevisionStore;
33 use OldRevisionImporter;
34 use MediaWiki\Revision\RevisionStoreFactory;
35 use UploadRevisionImporter;
36 use Wikimedia\Rdbms\ILoadBalancer;
37 use LinkCache;
38 use MediaHandlerFactory;
39 use MediaWiki\Config\ConfigRepository;
40 use MediaWiki\Linker\LinkRenderer;
41 use MediaWiki\Linker\LinkRendererFactory;
42 use MWException;
43 use MessageCache;
44 use MimeAnalyzer;
45 use NamespaceInfo;
46 use ObjectCache;
47 use Parser;
48 use ParserCache;
49 use ParserFactory;
50 use PasswordFactory;
51 use ProxyLookup;
52 use RepoGroup;
53 use ResourceLoader;
54 use SearchEngine;
55 use SearchEngineConfig;
56 use SearchEngineFactory;
57 use SiteLookup;
58 use SiteStore;
59 use WatchedItemStoreInterface;
60 use WatchedItemQueryService;
61 use SkinFactory;
62 use TitleFormatter;
63 use TitleParser;
64 use VirtualRESTServiceClient;
65 use Wikimedia\Rdbms\LBFactory;
66 use Wikimedia\Services\SalvageableService;
67 use Wikimedia\Services\ServiceContainer;
68 use Wikimedia\Services\NoSuchServiceException;
69 use MediaWiki\Interwiki\InterwikiLookup;
70 use MagicWordFactory;
71 use MediaWiki\Storage\PageEditStash;
72
73 /**
74 * Service locator for MediaWiki core services.
75 *
76 * This program is free software; you can redistribute it and/or modify
77 * it under the terms of the GNU General Public License as published by
78 * the Free Software Foundation; either version 2 of the License, or
79 * (at your option) any later version.
80 *
81 * This program is distributed in the hope that it will be useful,
82 * but WITHOUT ANY WARRANTY; without even the implied warranty of
83 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84 * GNU General Public License for more details.
85 *
86 * You should have received a copy of the GNU General Public License along
87 * with this program; if not, write to the Free Software Foundation, Inc.,
88 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
89 * http://www.gnu.org/copyleft/gpl.html
90 *
91 * @file
92 *
93 * @since 1.27
94 */
95
96 /**
97 * MediaWikiServices is the service locator for the application scope of MediaWiki.
98 * Its implemented as a simple configurable DI container.
99 * MediaWikiServices acts as a top level factory/registry for top level services, and builds
100 * the network of service objects that defines MediaWiki's application logic.
101 * It acts as an entry point to MediaWiki's dependency injection mechanism.
102 *
103 * Services are defined in the "wiring" array passed to the constructor,
104 * or by calling defineService().
105 *
106 * @see docs/injection.txt for an overview of using dependency injection in the
107 * MediaWiki code base.
108 */
109 class MediaWikiServices extends ServiceContainer {
110
111 /**
112 * @var MediaWikiServices|null
113 */
114 private static $instance = null;
115
116 /**
117 * Returns the global default instance of the top level service locator.
118 *
119 * @since 1.27
120 *
121 * The default instance is initialized using the service instantiator functions
122 * defined in ServiceWiring.php.
123 *
124 * @note This should only be called by static functions! The instance returned here
125 * should not be passed around! Objects that need access to a service should have
126 * that service injected into the constructor, never a service locator!
127 *
128 * @return MediaWikiServices
129 */
130 public static function getInstance() {
131 if ( self::$instance === null ) {
132 // NOTE: constructing GlobalVarConfig here is not particularly pretty,
133 // but some information from the global scope has to be injected here,
134 // even if it's just a file name or database credentials to load
135 // configuration from.
136 $bootstrapConfig = new GlobalVarConfig();
137 self::$instance = self::newInstance( $bootstrapConfig, 'load' );
138 }
139
140 return self::$instance;
141 }
142
143 /**
144 * Replaces the global MediaWikiServices instance.
145 *
146 * @since 1.28
147 *
148 * @note This is for use in PHPUnit tests only!
149 *
150 * @throws MWException if called outside of PHPUnit tests.
151 *
152 * @param MediaWikiServices $services The new MediaWikiServices object.
153 *
154 * @return MediaWikiServices The old MediaWikiServices object, so it can be restored later.
155 */
156 public static function forceGlobalInstance( MediaWikiServices $services ) {
157 if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
158 throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
159 }
160
161 $old = self::getInstance();
162 self::$instance = $services;
163
164 return $old;
165 }
166
167 /**
168 * Creates a new instance of MediaWikiServices and sets it as the global default
169 * instance. getInstance() will return a different MediaWikiServices object
170 * after every call to resetGlobalInstance().
171 *
172 * @since 1.28
173 *
174 * @warning This should not be used during normal operation. It is intended for use
175 * when the configuration has changed significantly since bootstrap time, e.g.
176 * during the installation process or during testing.
177 *
178 * @warning Calling resetGlobalInstance() may leave the application in an inconsistent
179 * state. Calling this is only safe under the ASSUMPTION that NO REFERENCE to
180 * any of the services managed by MediaWikiServices exist. If any service objects
181 * managed by the old MediaWikiServices instance remain in use, they may INTERFERE
182 * with the operation of the services managed by the new MediaWikiServices.
183 * Operating with a mix of services created by the old and the new
184 * MediaWikiServices instance may lead to INCONSISTENCIES and even DATA LOSS!
185 * Any class implementing LAZY LOADING is especially prone to this problem,
186 * since instances would typically retain a reference to a storage layer service.
187 *
188 * @see forceGlobalInstance()
189 * @see resetGlobalInstance()
190 * @see resetBetweenTest()
191 *
192 * @param Config|null $bootstrapConfig The Config object to be registered as the
193 * 'BootstrapConfig' service. This has to contain at least the information
194 * needed to set up the 'ConfigFactory' service. If not given, the bootstrap
195 * config of the old instance of MediaWikiServices will be re-used. If there
196 * was no previous instance, a new GlobalVarConfig object will be used to
197 * bootstrap the services.
198 *
199 * @param string $quick Set this to "quick" to allow expensive resources to be re-used.
200 * See SalvageableService for details.
201 *
202 * @throws MWException If called after MW_SERVICE_BOOTSTRAP_COMPLETE has been defined in
203 * Setup.php (unless MW_PHPUNIT_TEST or MEDIAWIKI_INSTALL or RUN_MAINTENANCE_IF_MAIN
204 * is defined).
205 */
206 public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
207 if ( self::$instance === null ) {
208 // no global instance yet, nothing to reset
209 return;
210 }
211
212 self::failIfResetNotAllowed( __METHOD__ );
213
214 if ( $bootstrapConfig === null ) {
215 $bootstrapConfig = self::$instance->getBootstrapConfig();
216 }
217
218 $oldInstance = self::$instance;
219
220 self::$instance = self::newInstance( $bootstrapConfig, 'load' );
221 self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
222
223 if ( $quick === 'quick' ) {
224 self::$instance->salvage( $oldInstance );
225 } else {
226 $oldInstance->destroy();
227 }
228 }
229
230 /** @noinspection PhpDocSignatureInspection */
231
232 /**
233 * Salvages the state of any salvageable service instances in $other.
234 *
235 * @note $other will have been destroyed when salvage() returns.
236 *
237 * @param MediaWikiServices $other
238 */
239 private function salvage( self $other ) {
240 foreach ( $this->getServiceNames() as $name ) {
241 // The service could be new in the new instance and not registered in the
242 // other instance (e.g. an extension that was loaded after the instantiation of
243 // the other instance. Skip this service in this case. See T143974
244 try {
245 $oldService = $other->peekService( $name );
246 } catch ( NoSuchServiceException $e ) {
247 continue;
248 }
249
250 if ( $oldService instanceof SalvageableService ) {
251 /** @var SalvageableService $newService */
252 $newService = $this->getService( $name );
253 $newService->salvage( $oldService );
254 }
255 }
256
257 $other->destroy();
258 }
259
260 /**
261 * Creates a new MediaWikiServices instance and initializes it according to the
262 * given $bootstrapConfig. In particular, all wiring files defined in the
263 * ServiceWiringFiles setting are loaded, and the MediaWikiServices hook is called.
264 *
265 * @param Config|null $bootstrapConfig The Config object to be registered as the
266 * 'BootstrapConfig' service.
267 *
268 * @param string $loadWiring set this to 'load' to load the wiring files specified
269 * in the 'ServiceWiringFiles' setting in $bootstrapConfig.
270 *
271 * @return MediaWikiServices
272 * @throws MWException
273 * @throws \FatalError
274 */
275 private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
276 $instance = new self( $bootstrapConfig );
277
278 // Load the default wiring from the specified files.
279 if ( $loadWiring === 'load' ) {
280 $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
281 $instance->loadWiringFiles( $wiringFiles );
282 }
283
284 // Provide a traditional hook point to allow extensions to configure services.
285 Hooks::run( 'MediaWikiServices', [ $instance ] );
286
287 return $instance;
288 }
289
290 /**
291 * Disables all storage layer services. After calling this, any attempt to access the
292 * storage layer will result in an error. Use resetGlobalInstance() to restore normal
293 * operation.
294 *
295 * @since 1.28
296 *
297 * @warning This is intended for extreme situations only and should never be used
298 * while serving normal web requests. Legitimate use cases for this method include
299 * the installation process. Test fixtures may also use this, if the fixture relies
300 * on globalState.
301 *
302 * @see resetGlobalInstance()
303 * @see resetChildProcessServices()
304 */
305 public static function disableStorageBackend() {
306 // TODO: also disable some Caches, JobQueues, etc
307 $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
308 $services = self::getInstance();
309
310 foreach ( $destroy as $name ) {
311 $services->disableService( $name );
312 }
313
314 ObjectCache::clear();
315 }
316
317 /**
318 * Resets any services that may have become stale after a child process
319 * returns from after pcntl_fork(). It's also safe, but generally unnecessary,
320 * to call this method from the parent process.
321 *
322 * @since 1.28
323 *
324 * @note This is intended for use in the context of process forking only!
325 *
326 * @see resetGlobalInstance()
327 * @see disableStorageBackend()
328 */
329 public static function resetChildProcessServices() {
330 // NOTE: for now, just reset everything. Since we don't know the interdependencies
331 // between services, we can't do this more selectively at this time.
332 self::resetGlobalInstance();
333
334 // Child, reseed because there is no bug in PHP:
335 // https://bugs.php.net/bug.php?id=42465
336 mt_srand( getmypid() );
337 }
338
339 /**
340 * Resets the given service for testing purposes.
341 *
342 * @since 1.28
343 *
344 * @warning This is generally unsafe! Other services may still retain references
345 * to the stale service instance, leading to failures and inconsistencies. Subclasses
346 * may use this method to reset specific services under specific instances, but
347 * it should not be exposed to application logic.
348 *
349 * @note With proper dependency injection used throughout the codebase, this method
350 * should not be needed. It is provided to allow tests that pollute global service
351 * instances to clean up.
352 *
353 * @param string $name
354 * @param bool $destroy Whether the service instance should be destroyed if it exists.
355 * When set to false, any existing service instance will effectively be detached
356 * from the container.
357 *
358 * @throws MWException if called outside of PHPUnit tests.
359 */
360 public function resetServiceForTesting( $name, $destroy = true ) {
361 if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
362 throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
363 }
364
365 $this->resetService( $name, $destroy );
366 }
367
368 /**
369 * Convenience method that throws an exception unless it is called during a phase in which
370 * resetting of global services is allowed. In general, services should not be reset
371 * individually, since that may introduce inconsistencies.
372 *
373 * @since 1.28
374 *
375 * This method will throw an exception if:
376 *
377 * - self::$resetInProgress is false (to allow all services to be reset together
378 * via resetGlobalInstance)
379 * - and MEDIAWIKI_INSTALL is not defined (to allow services to be reset during installation)
380 * - and MW_PHPUNIT_TEST is not defined (to allow services to be reset during testing)
381 *
382 * This method is intended to be used to safeguard against accidentally resetting
383 * global service instances that are not yet managed by MediaWikiServices. It is
384 * defined here in the MediaWikiServices services class to have a central place
385 * for managing service bootstrapping and resetting.
386 *
387 * @param string $method the name of the caller method, as given by __METHOD__.
388 *
389 * @throws MWException if called outside bootstrap mode.
390 *
391 * @see resetGlobalInstance()
392 * @see forceGlobalInstance()
393 * @see disableStorageBackend()
394 */
395 public static function failIfResetNotAllowed( $method ) {
396 if ( !defined( 'MW_PHPUNIT_TEST' )
397 && !defined( 'MW_PARSER_TEST' )
398 && !defined( 'MEDIAWIKI_INSTALL' )
399 && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
400 && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
401 ) {
402 throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
403 }
404 }
405
406 /**
407 * @param Config $config The Config object to be registered as the 'BootstrapConfig' service.
408 * This has to contain at least the information needed to set up the 'ConfigFactory'
409 * service.
410 */
411 public function __construct( Config $config ) {
412 parent::__construct();
413
414 // Register the given Config object as the bootstrap config service.
415 $this->defineService( 'BootstrapConfig', function () use ( $config ) {
416 return $config;
417 } );
418 }
419
420 // CONVENIENCE GETTERS ////////////////////////////////////////////////////
421
422 /**
423 * @since 1.31
424 * @return ActorMigration
425 */
426 public function getActorMigration() {
427 return $this->getService( 'ActorMigration' );
428 }
429
430 /**
431 * @since 1.31
432 * @return BlobStore
433 */
434 public function getBlobStore() {
435 return $this->getService( '_SqlBlobStore' );
436 }
437
438 /**
439 * @since 1.31
440 * @return BlobStoreFactory
441 */
442 public function getBlobStoreFactory() {
443 return $this->getService( 'BlobStoreFactory' );
444 }
445
446 /**
447 * @since 1.34
448 * @return BlockManager
449 */
450 public function getBlockManager() : BlockManager {
451 return $this->getService( 'BlockManager' );
452 }
453
454 /**
455 * @since 1.33
456 * @return BlockRestrictionStore
457 */
458 public function getBlockRestrictionStore() : BlockRestrictionStore {
459 return $this->getService( 'BlockRestrictionStore' );
460 }
461
462 /**
463 * Returns the Config object containing the bootstrap configuration.
464 * Bootstrap configuration would typically include database credentials
465 * and other information that may be needed before the ConfigFactory
466 * service can be instantiated.
467 *
468 * @note This should only be used during bootstrapping, in particular
469 * when creating the MainConfig service. Application logic should
470 * use getMainConfig() to get a Config instances.
471 *
472 * @since 1.27
473 * @return Config
474 */
475 public function getBootstrapConfig() {
476 return $this->getService( 'BootstrapConfig' );
477 }
478
479 /**
480 * @since 1.32
481 * @return NameTableStore
482 */
483 public function getChangeTagDefStore() {
484 return $this->getService( 'NameTableStoreFactory' )->getChangeTagDef();
485 }
486
487 /**
488 * @since 1.31
489 * @return CommentStore
490 */
491 public function getCommentStore() {
492 return $this->getService( 'CommentStore' );
493 }
494
495 /**
496 * @since 1.27
497 * @return ConfigFactory
498 */
499 public function getConfigFactory() {
500 return $this->getService( 'ConfigFactory' );
501 }
502
503 /**
504 * @since 1.32
505 * @return ConfigRepository
506 */
507 public function getConfigRepository() {
508 return $this->getService( 'ConfigRepository' );
509 }
510
511 /**
512 * @since 1.29
513 * @return \ConfiguredReadOnlyMode
514 */
515 public function getConfiguredReadOnlyMode() {
516 return $this->getService( 'ConfiguredReadOnlyMode' );
517 }
518
519 /**
520 * @since 1.32
521 * @return \Language
522 */
523 public function getContentLanguage() {
524 return $this->getService( 'ContentLanguage' );
525 }
526
527 /**
528 * @since 1.31
529 * @return NameTableStore
530 */
531 public function getContentModelStore() {
532 return $this->getService( 'NameTableStoreFactory' )->getContentModels();
533 }
534
535 /**
536 * @since 1.28
537 * @return CryptHKDF
538 */
539 public function getCryptHKDF() {
540 return $this->getService( 'CryptHKDF' );
541 }
542
543 /**
544 * @since 1.33
545 * @return DateFormatterFactory
546 */
547 public function getDateFormatterFactory() {
548 return $this->getService( 'DateFormatterFactory' );
549 }
550
551 /**
552 * @since 1.28
553 * @return ILoadBalancer The main DB load balancer for the local wiki.
554 */
555 public function getDBLoadBalancer() {
556 return $this->getService( 'DBLoadBalancer' );
557 }
558
559 /**
560 * @since 1.28
561 * @return LBFactory
562 */
563 public function getDBLoadBalancerFactory() {
564 return $this->getService( 'DBLoadBalancerFactory' );
565 }
566
567 /**
568 * @since 1.27
569 * @return EventRelayerGroup
570 */
571 public function getEventRelayerGroup() {
572 return $this->getService( 'EventRelayerGroup' );
573 }
574
575 /**
576 * @since 1.34
577 * @return \ExternalStoreAccess
578 */
579 public function getExternalStoreAccess() {
580 return $this->getService( 'ExternalStoreAccess' );
581 }
582
583 /**
584 * @since 1.31
585 * @return \ExternalStoreFactory
586 */
587 public function getExternalStoreFactory() {
588 return $this->getService( 'ExternalStoreFactory' );
589 }
590
591 /**
592 * @since 1.28
593 * @return GenderCache
594 */
595 public function getGenderCache() {
596 return $this->getService( 'GenderCache' );
597 }
598
599 /**
600 * @since 1.31
601 * @return HttpRequestFactory
602 */
603 public function getHttpRequestFactory() {
604 return $this->getService( 'HttpRequestFactory' );
605 }
606
607 /**
608 * @since 1.28
609 * @return InterwikiLookup
610 */
611 public function getInterwikiLookup() {
612 return $this->getService( 'InterwikiLookup' );
613 }
614
615 /**
616 * @since 1.28
617 * @return LinkCache
618 */
619 public function getLinkCache() {
620 return $this->getService( 'LinkCache' );
621 }
622
623 /**
624 * LinkRenderer instance that can be used
625 * if no custom options are needed
626 *
627 * @since 1.28
628 * @return LinkRenderer
629 */
630 public function getLinkRenderer() {
631 return $this->getService( 'LinkRenderer' );
632 }
633
634 /**
635 * @since 1.28
636 * @return LinkRendererFactory
637 */
638 public function getLinkRendererFactory() {
639 return $this->getService( 'LinkRendererFactory' );
640 }
641
642 /**
643 * @since 1.28
644 * @return \BagOStuff
645 */
646 public function getLocalServerObjectCache() {
647 return $this->getService( 'LocalServerObjectCache' );
648 }
649
650 /**
651 * @since 1.32
652 * @return MagicWordFactory
653 */
654 public function getMagicWordFactory() {
655 return $this->getService( 'MagicWordFactory' );
656 }
657
658 /**
659 * Returns the Config object that provides configuration for MediaWiki core.
660 * This may or may not be the same object that is returned by getBootstrapConfig().
661 *
662 * @since 1.27
663 * @return Config
664 */
665 public function getMainConfig() {
666 return $this->getService( 'MainConfig' );
667 }
668
669 /**
670 * @since 1.28
671 * @return \BagOStuff
672 */
673 public function getMainObjectStash() {
674 return $this->getService( 'MainObjectStash' );
675 }
676
677 /**
678 * @since 1.28
679 * @return \WANObjectCache
680 */
681 public function getMainWANObjectCache() {
682 return $this->getService( 'MainWANObjectCache' );
683 }
684
685 /**
686 * @since 1.28
687 * @return MediaHandlerFactory
688 */
689 public function getMediaHandlerFactory() {
690 return $this->getService( 'MediaHandlerFactory' );
691 }
692
693 /**
694 * @since 1.34
695 * @return MessageCache
696 */
697 public function getMessageCache() : MessageCache {
698 return $this->getService( 'MessageCache' );
699 }
700
701 /**
702 * @since 1.28
703 * @return MimeAnalyzer
704 */
705 public function getMimeAnalyzer() {
706 return $this->getService( 'MimeAnalyzer' );
707 }
708
709 /**
710 * @since 1.34
711 * @return NamespaceInfo
712 */
713 public function getNamespaceInfo() : NamespaceInfo {
714 return $this->getService( 'NamespaceInfo' );
715 }
716
717 /**
718 * @since 1.32
719 * @return NameTableStoreFactory
720 */
721 public function getNameTableStoreFactory() {
722 return $this->getService( 'NameTableStoreFactory' );
723 }
724
725 /**
726 * @since 1.32
727 * @return OldRevisionImporter
728 */
729 public function getOldRevisionImporter() {
730 return $this->getService( 'OldRevisionImporter' );
731 }
732
733 /**
734 * @return PageEditStash
735 * @since 1.34
736 */
737 public function getPageEditStash() {
738 return $this->getService( 'PageEditStash' );
739 }
740
741 /**
742 * @since 1.29
743 * @return Parser
744 */
745 public function getParser() {
746 return $this->getService( 'Parser' );
747 }
748
749 /**
750 * @since 1.30
751 * @return ParserCache
752 */
753 public function getParserCache() {
754 return $this->getService( 'ParserCache' );
755 }
756
757 /**
758 * @since 1.32
759 * @return ParserFactory
760 */
761 public function getParserFactory() {
762 return $this->getService( 'ParserFactory' );
763 }
764
765 /**
766 * @since 1.32
767 * @return PasswordFactory
768 */
769 public function getPasswordFactory() {
770 return $this->getService( 'PasswordFactory' );
771 }
772
773 /**
774 * @since 1.32
775 * @return StatsdDataFactoryInterface
776 */
777 public function getPerDbNameStatsdDataFactory() {
778 return $this->getService( 'PerDbNameStatsdDataFactory' );
779 }
780
781 /**
782 * @since 1.33
783 * @return PermissionManager
784 */
785 public function getPermissionManager() {
786 return $this->getService( 'PermissionManager' );
787 }
788
789 /**
790 * @since 1.31
791 * @return PreferencesFactory
792 */
793 public function getPreferencesFactory() {
794 return $this->getService( 'PreferencesFactory' );
795 }
796
797 /**
798 * @since 1.28
799 * @return ProxyLookup
800 */
801 public function getProxyLookup() {
802 return $this->getService( 'ProxyLookup' );
803 }
804
805 /**
806 * @since 1.29
807 * @return \ReadOnlyMode
808 */
809 public function getReadOnlyMode() {
810 return $this->getService( 'ReadOnlyMode' );
811 }
812
813 /**
814 * @since 1.34
815 * @return RepoGroup
816 */
817 public function getRepoGroup() : RepoGroup {
818 return $this->getService( 'RepoGroup' );
819 }
820
821 /**
822 * @since 1.33
823 * @return ResourceLoader
824 */
825 public function getResourceLoader() {
826 return $this->getService( 'ResourceLoader' );
827 }
828
829 /**
830 * @since 1.31
831 * @return RevisionFactory
832 */
833 public function getRevisionFactory() {
834 return $this->getService( 'RevisionFactory' );
835 }
836
837 /**
838 * @since 1.31
839 * @return RevisionLookup
840 */
841 public function getRevisionLookup() {
842 return $this->getService( 'RevisionLookup' );
843 }
844
845 /**
846 * @since 1.32
847 * @return RevisionRenderer
848 */
849 public function getRevisionRenderer() {
850 return $this->getService( 'RevisionRenderer' );
851 }
852
853 /**
854 * @since 1.31
855 * @return RevisionStore
856 */
857 public function getRevisionStore() {
858 return $this->getService( 'RevisionStore' );
859 }
860
861 /**
862 * @since 1.32
863 * @return RevisionStoreFactory
864 */
865 public function getRevisionStoreFactory() {
866 return $this->getService( 'RevisionStoreFactory' );
867 }
868
869 /**
870 * @since 1.27
871 * @return SearchEngine
872 */
873 public function newSearchEngine() {
874 // New engine object every time, since they keep state
875 return $this->getService( 'SearchEngineFactory' )->create();
876 }
877
878 /**
879 * @since 1.27
880 * @return SearchEngineConfig
881 */
882 public function getSearchEngineConfig() {
883 return $this->getService( 'SearchEngineConfig' );
884 }
885
886 /**
887 * @since 1.27
888 * @return SearchEngineFactory
889 */
890 public function getSearchEngineFactory() {
891 return $this->getService( 'SearchEngineFactory' );
892 }
893
894 /**
895 * @since 1.30
896 * @return CommandFactory
897 */
898 public function getShellCommandFactory() {
899 return $this->getService( 'ShellCommandFactory' );
900 }
901
902 /**
903 * @since 1.27
904 * @return SiteLookup
905 */
906 public function getSiteLookup() {
907 return $this->getService( 'SiteLookup' );
908 }
909
910 /**
911 * @since 1.27
912 * @return SiteStore
913 */
914 public function getSiteStore() {
915 return $this->getService( 'SiteStore' );
916 }
917
918 /**
919 * @since 1.27
920 * @return SkinFactory
921 */
922 public function getSkinFactory() {
923 return $this->getService( 'SkinFactory' );
924 }
925
926 /**
927 * @since 1.33
928 * @return SlotRoleRegistry
929 */
930 public function getSlotRoleRegistry() {
931 return $this->getService( 'SlotRoleRegistry' );
932 }
933
934 /**
935 * @since 1.31
936 * @return NameTableStore
937 */
938 public function getSlotRoleStore() {
939 return $this->getService( 'NameTableStoreFactory' )->getSlotRoles();
940 }
941
942 /**
943 * @since 1.32
944 * @return SpecialPageFactory
945 */
946 public function getSpecialPageFactory() : SpecialPageFactory {
947 return $this->getService( 'SpecialPageFactory' );
948 }
949
950 /**
951 * @since 1.27
952 * @return IBufferingStatsdDataFactory
953 */
954 public function getStatsdDataFactory() {
955 return $this->getService( 'StatsdDataFactory' );
956 }
957
958 /**
959 * @since 1.28
960 * @return TitleFormatter
961 */
962 public function getTitleFormatter() {
963 return $this->getService( 'TitleFormatter' );
964 }
965
966 /**
967 * @since 1.28
968 * @return TitleParser
969 */
970 public function getTitleParser() {
971 return $this->getService( 'TitleParser' );
972 }
973
974 /**
975 * @since 1.32
976 * @return UploadRevisionImporter
977 */
978 public function getUploadRevisionImporter() {
979 return $this->getService( 'UploadRevisionImporter' );
980 }
981
982 /**
983 * @since 1.28
984 * @return VirtualRESTServiceClient
985 */
986 public function getVirtualRESTServiceClient() {
987 return $this->getService( 'VirtualRESTServiceClient' );
988 }
989
990 /**
991 * @since 1.28
992 * @return WatchedItemQueryService
993 */
994 public function getWatchedItemQueryService() {
995 return $this->getService( 'WatchedItemQueryService' );
996 }
997
998 /**
999 * @since 1.28
1000 * @return WatchedItemStoreInterface
1001 */
1002 public function getWatchedItemStore() {
1003 return $this->getService( 'WatchedItemStore' );
1004 }
1005
1006 /**
1007 * @since 1.31
1008 * @return \OldRevisionImporter
1009 */
1010 public function getWikiRevisionOldRevisionImporter() {
1011 return $this->getService( 'OldRevisionImporter' );
1012 }
1013
1014 /**
1015 * @since 1.31
1016 * @return \OldRevisionImporter
1017 */
1018 public function getWikiRevisionOldRevisionImporterNoUpdates() {
1019 return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
1020 }
1021
1022 /**
1023 * @since 1.31
1024 * @return \UploadRevisionImporter
1025 */
1026 public function getWikiRevisionUploadImporter() {
1027 return $this->getService( 'UploadRevisionImporter' );
1028 }
1029
1030 }