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