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