summaryrefslogtreecommitdiff
path: root/www/wiki/includes/MediaWikiServices.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/includes/MediaWikiServices.php')
-rw-r--r--www/wiki/includes/MediaWikiServices.php829
1 files changed, 829 insertions, 0 deletions
diff --git a/www/wiki/includes/MediaWikiServices.php b/www/wiki/includes/MediaWikiServices.php
new file mode 100644
index 00000000..ac986835
--- /dev/null
+++ b/www/wiki/includes/MediaWikiServices.php
@@ -0,0 +1,829 @@
+<?php
+namespace MediaWiki;
+
+use ActorMigration;
+use CommentStore;
+use Config;
+use ConfigFactory;
+use CryptHKDF;
+use CryptRand;
+use EventRelayerGroup;
+use GenderCache;
+use GlobalVarConfig;
+use Hooks;
+use IBufferingStatsdDataFactory;
+use MediaWiki\Http\HttpRequestFactory;
+use MediaWiki\Preferences\PreferencesFactory;
+use MediaWiki\Shell\CommandFactory;
+use MediaWiki\Storage\BlobStore;
+use MediaWiki\Storage\BlobStoreFactory;
+use MediaWiki\Storage\NameTableStore;
+use MediaWiki\Storage\RevisionFactory;
+use MediaWiki\Storage\RevisionLookup;
+use MediaWiki\Storage\RevisionStore;
+use Wikimedia\Rdbms\LBFactory;
+use LinkCache;
+use Wikimedia\Rdbms\LoadBalancer;
+use MediaHandlerFactory;
+use MediaWiki\Linker\LinkRenderer;
+use MediaWiki\Linker\LinkRendererFactory;
+use MediaWiki\Services\SalvageableService;
+use MediaWiki\Services\ServiceContainer;
+use MediaWiki\Services\NoSuchServiceException;
+use MWException;
+use MimeAnalyzer;
+use ObjectCache;
+use Parser;
+use ParserCache;
+use ProxyLookup;
+use SearchEngine;
+use SearchEngineConfig;
+use SearchEngineFactory;
+use SiteLookup;
+use SiteStore;
+use WatchedItemStoreInterface;
+use WatchedItemQueryService;
+use SkinFactory;
+use TitleFormatter;
+use TitleParser;
+use VirtualRESTServiceClient;
+use MediaWiki\Interwiki\InterwikiLookup;
+
+/**
+ * Service locator for MediaWiki core services.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ *
+ * @since 1.27
+ */
+
+/**
+ * MediaWikiServices is the service locator for the application scope of MediaWiki.
+ * Its implemented as a simple configurable DI container.
+ * MediaWikiServices acts as a top level factory/registry for top level services, and builds
+ * the network of service objects that defines MediaWiki's application logic.
+ * It acts as an entry point to MediaWiki's dependency injection mechanism.
+ *
+ * Services are defined in the "wiring" array passed to the constructor,
+ * or by calling defineService().
+ *
+ * @see docs/injection.txt for an overview of using dependency injection in the
+ * MediaWiki code base.
+ */
+class MediaWikiServices extends ServiceContainer {
+
+ /**
+ * @var MediaWikiServices|null
+ */
+ private static $instance = null;
+
+ /**
+ * Returns the global default instance of the top level service locator.
+ *
+ * @since 1.27
+ *
+ * The default instance is initialized using the service instantiator functions
+ * defined in ServiceWiring.php.
+ *
+ * @note This should only be called by static functions! The instance returned here
+ * should not be passed around! Objects that need access to a service should have
+ * that service injected into the constructor, never a service locator!
+ *
+ * @return MediaWikiServices
+ */
+ public static function getInstance() {
+ if ( self::$instance === null ) {
+ // NOTE: constructing GlobalVarConfig here is not particularly pretty,
+ // but some information from the global scope has to be injected here,
+ // even if it's just a file name or database credentials to load
+ // configuration from.
+ $bootstrapConfig = new GlobalVarConfig();
+ self::$instance = self::newInstance( $bootstrapConfig, 'load' );
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Replaces the global MediaWikiServices instance.
+ *
+ * @since 1.28
+ *
+ * @note This is for use in PHPUnit tests only!
+ *
+ * @throws MWException if called outside of PHPUnit tests.
+ *
+ * @param MediaWikiServices $services The new MediaWikiServices object.
+ *
+ * @return MediaWikiServices The old MediaWikiServices object, so it can be restored later.
+ */
+ public static function forceGlobalInstance( MediaWikiServices $services ) {
+ if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+ throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
+ }
+
+ $old = self::getInstance();
+ self::$instance = $services;
+
+ return $old;
+ }
+
+ /**
+ * Creates a new instance of MediaWikiServices and sets it as the global default
+ * instance. getInstance() will return a different MediaWikiServices object
+ * after every call to resetGlobalInstance().
+ *
+ * @since 1.28
+ *
+ * @warning This should not be used during normal operation. It is intended for use
+ * when the configuration has changed significantly since bootstrap time, e.g.
+ * during the installation process or during testing.
+ *
+ * @warning Calling resetGlobalInstance() may leave the application in an inconsistent
+ * state. Calling this is only safe under the ASSUMPTION that NO REFERENCE to
+ * any of the services managed by MediaWikiServices exist. If any service objects
+ * managed by the old MediaWikiServices instance remain in use, they may INTERFERE
+ * with the operation of the services managed by the new MediaWikiServices.
+ * Operating with a mix of services created by the old and the new
+ * MediaWikiServices instance may lead to INCONSISTENCIES and even DATA LOSS!
+ * Any class implementing LAZY LOADING is especially prone to this problem,
+ * since instances would typically retain a reference to a storage layer service.
+ *
+ * @see forceGlobalInstance()
+ * @see resetGlobalInstance()
+ * @see resetBetweenTest()
+ *
+ * @param Config|null $bootstrapConfig The Config object to be registered as the
+ * 'BootstrapConfig' service. This has to contain at least the information
+ * needed to set up the 'ConfigFactory' service. If not given, the bootstrap
+ * config of the old instance of MediaWikiServices will be re-used. If there
+ * was no previous instance, a new GlobalVarConfig object will be used to
+ * bootstrap the services.
+ *
+ * @param string $quick Set this to "quick" to allow expensive resources to be re-used.
+ * See SalvageableService for details.
+ *
+ * @throws MWException If called after MW_SERVICE_BOOTSTRAP_COMPLETE has been defined in
+ * Setup.php (unless MW_PHPUNIT_TEST or MEDIAWIKI_INSTALL or RUN_MAINTENANCE_IF_MAIN
+ * is defined).
+ */
+ public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
+ if ( self::$instance === null ) {
+ // no global instance yet, nothing to reset
+ return;
+ }
+
+ self::failIfResetNotAllowed( __METHOD__ );
+
+ if ( $bootstrapConfig === null ) {
+ $bootstrapConfig = self::$instance->getBootstrapConfig();
+ }
+
+ $oldInstance = self::$instance;
+
+ self::$instance = self::newInstance( $bootstrapConfig, 'load' );
+ self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
+
+ if ( $quick === 'quick' ) {
+ self::$instance->salvage( $oldInstance );
+ } else {
+ $oldInstance->destroy();
+ }
+ }
+
+ /**
+ * Salvages the state of any salvageable service instances in $other.
+ *
+ * @note $other will have been destroyed when salvage() returns.
+ *
+ * @param MediaWikiServices $other
+ */
+ private function salvage( self $other ) {
+ foreach ( $this->getServiceNames() as $name ) {
+ // The service could be new in the new instance and not registered in the
+ // other instance (e.g. an extension that was loaded after the instantiation of
+ // the other instance. Skip this service in this case. See T143974
+ try {
+ $oldService = $other->peekService( $name );
+ } catch ( NoSuchServiceException $e ) {
+ continue;
+ }
+
+ if ( $oldService instanceof SalvageableService ) {
+ /** @var SalvageableService $newService */
+ $newService = $this->getService( $name );
+ $newService->salvage( $oldService );
+ }
+ }
+
+ $other->destroy();
+ }
+
+ /**
+ * Creates a new MediaWikiServices instance and initializes it according to the
+ * given $bootstrapConfig. In particular, all wiring files defined in the
+ * ServiceWiringFiles setting are loaded, and the MediaWikiServices hook is called.
+ *
+ * @param Config|null $bootstrapConfig The Config object to be registered as the
+ * 'BootstrapConfig' service.
+ *
+ * @param string $loadWiring set this to 'load' to load the wiring files specified
+ * in the 'ServiceWiringFiles' setting in $bootstrapConfig.
+ *
+ * @return MediaWikiServices
+ * @throws MWException
+ * @throws \FatalError
+ */
+ private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
+ $instance = new self( $bootstrapConfig );
+
+ // Load the default wiring from the specified files.
+ if ( $loadWiring === 'load' ) {
+ $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
+ $instance->loadWiringFiles( $wiringFiles );
+ }
+
+ // Provide a traditional hook point to allow extensions to configure services.
+ Hooks::run( 'MediaWikiServices', [ $instance ] );
+
+ return $instance;
+ }
+
+ /**
+ * Disables all storage layer services. After calling this, any attempt to access the
+ * storage layer will result in an error. Use resetGlobalInstance() to restore normal
+ * operation.
+ *
+ * @since 1.28
+ *
+ * @warning This is intended for extreme situations only and should never be used
+ * while serving normal web requests. Legitimate use cases for this method include
+ * the installation process. Test fixtures may also use this, if the fixture relies
+ * on globalState.
+ *
+ * @see resetGlobalInstance()
+ * @see resetChildProcessServices()
+ */
+ public static function disableStorageBackend() {
+ // TODO: also disable some Caches, JobQueues, etc
+ $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
+ $services = self::getInstance();
+
+ foreach ( $destroy as $name ) {
+ $services->disableService( $name );
+ }
+
+ ObjectCache::clear();
+ }
+
+ /**
+ * Resets any services that may have become stale after a child process
+ * returns from after pcntl_fork(). It's also safe, but generally unnecessary,
+ * to call this method from the parent process.
+ *
+ * @since 1.28
+ *
+ * @note This is intended for use in the context of process forking only!
+ *
+ * @see resetGlobalInstance()
+ * @see disableStorageBackend()
+ */
+ public static function resetChildProcessServices() {
+ // NOTE: for now, just reset everything. Since we don't know the interdependencies
+ // between services, we can't do this more selectively at this time.
+ self::resetGlobalInstance();
+
+ // Child, reseed because there is no bug in PHP:
+ // https://bugs.php.net/bug.php?id=42465
+ mt_srand( getmypid() );
+ }
+
+ /**
+ * Resets the given service for testing purposes.
+ *
+ * @since 1.28
+ *
+ * @warning This is generally unsafe! Other services may still retain references
+ * to the stale service instance, leading to failures and inconsistencies. Subclasses
+ * may use this method to reset specific services under specific instances, but
+ * it should not be exposed to application logic.
+ *
+ * @note With proper dependency injection used throughout the codebase, this method
+ * should not be needed. It is provided to allow tests that pollute global service
+ * instances to clean up.
+ *
+ * @param string $name
+ * @param bool $destroy Whether the service instance should be destroyed if it exists.
+ * When set to false, any existing service instance will effectively be detached
+ * from the container.
+ *
+ * @throws MWException if called outside of PHPUnit tests.
+ */
+ public function resetServiceForTesting( $name, $destroy = true ) {
+ if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
+ throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
+ }
+
+ $this->resetService( $name, $destroy );
+ }
+
+ /**
+ * Convenience method that throws an exception unless it is called during a phase in which
+ * resetting of global services is allowed. In general, services should not be reset
+ * individually, since that may introduce inconsistencies.
+ *
+ * @since 1.28
+ *
+ * This method will throw an exception if:
+ *
+ * - self::$resetInProgress is false (to allow all services to be reset together
+ * via resetGlobalInstance)
+ * - and MEDIAWIKI_INSTALL is not defined (to allow services to be reset during installation)
+ * - and MW_PHPUNIT_TEST is not defined (to allow services to be reset during testing)
+ *
+ * This method is intended to be used to safeguard against accidentally resetting
+ * global service instances that are not yet managed by MediaWikiServices. It is
+ * defined here in the MediaWikiServices services class to have a central place
+ * for managing service bootstrapping and resetting.
+ *
+ * @param string $method the name of the caller method, as given by __METHOD__.
+ *
+ * @throws MWException if called outside bootstrap mode.
+ *
+ * @see resetGlobalInstance()
+ * @see forceGlobalInstance()
+ * @see disableStorageBackend()
+ */
+ public static function failIfResetNotAllowed( $method ) {
+ if ( !defined( 'MW_PHPUNIT_TEST' )
+ && !defined( 'MW_PARSER_TEST' )
+ && !defined( 'MEDIAWIKI_INSTALL' )
+ && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
+ && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
+ ) {
+ throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
+ }
+ }
+
+ /**
+ * @param Config $config The Config object to be registered as the 'BootstrapConfig' service.
+ * This has to contain at least the information needed to set up the 'ConfigFactory'
+ * service.
+ */
+ public function __construct( Config $config ) {
+ parent::__construct();
+
+ // Register the given Config object as the bootstrap config service.
+ $this->defineService( 'BootstrapConfig', function () use ( $config ) {
+ return $config;
+ } );
+ }
+
+ // CONVENIENCE GETTERS ////////////////////////////////////////////////////
+
+ /**
+ * Returns the Config object containing the bootstrap configuration.
+ * Bootstrap configuration would typically include database credentials
+ * and other information that may be needed before the ConfigFactory
+ * service can be instantiated.
+ *
+ * @note This should only be used during bootstrapping, in particular
+ * when creating the MainConfig service. Application logic should
+ * use getMainConfig() to get a Config instances.
+ *
+ * @since 1.27
+ * @return Config
+ */
+ public function getBootstrapConfig() {
+ return $this->getService( 'BootstrapConfig' );
+ }
+
+ /**
+ * @since 1.27
+ * @return ConfigFactory
+ */
+ public function getConfigFactory() {
+ return $this->getService( 'ConfigFactory' );
+ }
+
+ /**
+ * Returns the Config object that provides configuration for MediaWiki core.
+ * This may or may not be the same object that is returned by getBootstrapConfig().
+ *
+ * @since 1.27
+ * @return Config
+ */
+ public function getMainConfig() {
+ return $this->getService( 'MainConfig' );
+ }
+
+ /**
+ * @since 1.27
+ * @return SiteLookup
+ */
+ public function getSiteLookup() {
+ return $this->getService( 'SiteLookup' );
+ }
+
+ /**
+ * @since 1.27
+ * @return SiteStore
+ */
+ public function getSiteStore() {
+ return $this->getService( 'SiteStore' );
+ }
+
+ /**
+ * @since 1.28
+ * @return InterwikiLookup
+ */
+ public function getInterwikiLookup() {
+ return $this->getService( 'InterwikiLookup' );
+ }
+
+ /**
+ * @since 1.27
+ * @return IBufferingStatsdDataFactory
+ */
+ public function getStatsdDataFactory() {
+ return $this->getService( 'StatsdDataFactory' );
+ }
+
+ /**
+ * @since 1.27
+ * @return EventRelayerGroup
+ */
+ public function getEventRelayerGroup() {
+ return $this->getService( 'EventRelayerGroup' );
+ }
+
+ /**
+ * @since 1.27
+ * @return SearchEngine
+ */
+ public function newSearchEngine() {
+ // New engine object every time, since they keep state
+ return $this->getService( 'SearchEngineFactory' )->create();
+ }
+
+ /**
+ * @since 1.27
+ * @return SearchEngineFactory
+ */
+ public function getSearchEngineFactory() {
+ return $this->getService( 'SearchEngineFactory' );
+ }
+
+ /**
+ * @since 1.27
+ * @return SearchEngineConfig
+ */
+ public function getSearchEngineConfig() {
+ return $this->getService( 'SearchEngineConfig' );
+ }
+
+ /**
+ * @since 1.27
+ * @return SkinFactory
+ */
+ public function getSkinFactory() {
+ return $this->getService( 'SkinFactory' );
+ }
+
+ /**
+ * @since 1.28
+ * @return LBFactory
+ */
+ public function getDBLoadBalancerFactory() {
+ return $this->getService( 'DBLoadBalancerFactory' );
+ }
+
+ /**
+ * @since 1.28
+ * @return LoadBalancer The main DB load balancer for the local wiki.
+ */
+ public function getDBLoadBalancer() {
+ return $this->getService( 'DBLoadBalancer' );
+ }
+
+ /**
+ * @since 1.28
+ * @return WatchedItemStoreInterface
+ */
+ public function getWatchedItemStore() {
+ return $this->getService( 'WatchedItemStore' );
+ }
+
+ /**
+ * @since 1.28
+ * @return WatchedItemQueryService
+ */
+ public function getWatchedItemQueryService() {
+ return $this->getService( 'WatchedItemQueryService' );
+ }
+
+ /**
+ * @since 1.28
+ * @return CryptRand
+ */
+ public function getCryptRand() {
+ return $this->getService( 'CryptRand' );
+ }
+
+ /**
+ * @since 1.28
+ * @return CryptHKDF
+ */
+ public function getCryptHKDF() {
+ return $this->getService( 'CryptHKDF' );
+ }
+
+ /**
+ * @since 1.28
+ * @return MediaHandlerFactory
+ */
+ public function getMediaHandlerFactory() {
+ return $this->getService( 'MediaHandlerFactory' );
+ }
+
+ /**
+ * @since 1.28
+ * @return MimeAnalyzer
+ */
+ public function getMimeAnalyzer() {
+ return $this->getService( 'MimeAnalyzer' );
+ }
+
+ /**
+ * @since 1.28
+ * @return ProxyLookup
+ */
+ public function getProxyLookup() {
+ return $this->getService( 'ProxyLookup' );
+ }
+
+ /**
+ * @since 1.29
+ * @return Parser
+ */
+ public function getParser() {
+ return $this->getService( 'Parser' );
+ }
+
+ /**
+ * @since 1.30
+ * @return ParserCache
+ */
+ public function getParserCache() {
+ return $this->getService( 'ParserCache' );
+ }
+
+ /**
+ * @since 1.28
+ * @return GenderCache
+ */
+ public function getGenderCache() {
+ return $this->getService( 'GenderCache' );
+ }
+
+ /**
+ * @since 1.28
+ * @return LinkCache
+ */
+ public function getLinkCache() {
+ return $this->getService( 'LinkCache' );
+ }
+
+ /**
+ * @since 1.28
+ * @return LinkRendererFactory
+ */
+ public function getLinkRendererFactory() {
+ return $this->getService( 'LinkRendererFactory' );
+ }
+
+ /**
+ * LinkRenderer instance that can be used
+ * if no custom options are needed
+ *
+ * @since 1.28
+ * @return LinkRenderer
+ */
+ public function getLinkRenderer() {
+ return $this->getService( 'LinkRenderer' );
+ }
+
+ /**
+ * @since 1.28
+ * @return TitleFormatter
+ */
+ public function getTitleFormatter() {
+ return $this->getService( 'TitleFormatter' );
+ }
+
+ /**
+ * @since 1.28
+ * @return TitleParser
+ */
+ public function getTitleParser() {
+ return $this->getService( 'TitleParser' );
+ }
+
+ /**
+ * @since 1.28
+ * @return \BagOStuff
+ */
+ public function getMainObjectStash() {
+ return $this->getService( 'MainObjectStash' );
+ }
+
+ /**
+ * @since 1.28
+ * @return \WANObjectCache
+ */
+ public function getMainWANObjectCache() {
+ return $this->getService( 'MainWANObjectCache' );
+ }
+
+ /**
+ * @since 1.28
+ * @return \BagOStuff
+ */
+ public function getLocalServerObjectCache() {
+ return $this->getService( 'LocalServerObjectCache' );
+ }
+
+ /**
+ * @since 1.28
+ * @return VirtualRESTServiceClient
+ */
+ public function getVirtualRESTServiceClient() {
+ return $this->getService( 'VirtualRESTServiceClient' );
+ }
+
+ /**
+ * @since 1.29
+ * @return \ConfiguredReadOnlyMode
+ */
+ public function getConfiguredReadOnlyMode() {
+ return $this->getService( 'ConfiguredReadOnlyMode' );
+ }
+
+ /**
+ * @since 1.29
+ * @return \ReadOnlyMode
+ */
+ public function getReadOnlyMode() {
+ return $this->getService( 'ReadOnlyMode' );
+ }
+
+ /**
+ * @since 1.31
+ * @return \UploadRevisionImporter
+ */
+ public function getWikiRevisionUploadImporter() {
+ return $this->getService( 'UploadRevisionImporter' );
+ }
+
+ /**
+ * @since 1.31
+ * @return \OldRevisionImporter
+ */
+ public function getWikiRevisionOldRevisionImporter() {
+ return $this->getService( 'OldRevisionImporter' );
+ }
+
+ /**
+ * @since 1.31
+ * @return \OldRevisionImporter
+ */
+ public function getWikiRevisionOldRevisionImporterNoUpdates() {
+ return $this->getService( 'WikiRevisionOldRevisionImporterNoUpdates' );
+ }
+
+ /**
+ * @since 1.30
+ * @return CommandFactory
+ */
+ public function getShellCommandFactory() {
+ return $this->getService( 'ShellCommandFactory' );
+ }
+
+ /**
+ * @since 1.31
+ * @return \ExternalStoreFactory
+ */
+ public function getExternalStoreFactory() {
+ return $this->getService( 'ExternalStoreFactory' );
+ }
+
+ /**
+ * @since 1.31
+ * @return BlobStoreFactory
+ */
+ public function getBlobStoreFactory() {
+ return $this->getService( 'BlobStoreFactory' );
+ }
+
+ /**
+ * @since 1.31
+ * @return BlobStore
+ */
+ public function getBlobStore() {
+ return $this->getService( '_SqlBlobStore' );
+ }
+
+ /**
+ * @since 1.31
+ * @return RevisionStore
+ */
+ public function getRevisionStore() {
+ return $this->getService( 'RevisionStore' );
+ }
+
+ /**
+ * @since 1.31
+ * @return RevisionLookup
+ */
+ public function getRevisionLookup() {
+ return $this->getService( 'RevisionLookup' );
+ }
+
+ /**
+ * @since 1.31
+ * @return RevisionFactory
+ */
+ public function getRevisionFactory() {
+ return $this->getService( 'RevisionFactory' );
+ }
+
+ /**
+ * @since 1.31
+ * @return NameTableStore
+ */
+ public function getContentModelStore() {
+ return $this->getService( 'ContentModelStore' );
+ }
+
+ /**
+ * @since 1.31
+ * @return NameTableStore
+ */
+ public function getSlotRoleStore() {
+ return $this->getService( 'SlotRoleStore' );
+ }
+
+ /**
+ * @since 1.31
+ * @return PreferencesFactory
+ */
+ public function getPreferencesFactory() {
+ return $this->getService( 'PreferencesFactory' );
+ }
+
+ /**
+ * @since 1.31
+ * @return HttpRequestFactory
+ */
+ public function getHttpRequestFactory() {
+ return $this->getService( 'HttpRequestFactory' );
+ }
+
+ /**
+ * @since 1.31
+ * @return CommentStore
+ */
+ public function getCommentStore() {
+ return $this->getService( 'CommentStore' );
+ }
+
+ /**
+ * @since 1.31
+ * @return ActorMigration
+ */
+ public function getActorMigration() {
+ return $this->getService( 'ActorMigration' );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // NOTE: When adding a service getter here, don't forget to add a test
+ // case for it in MediaWikiServicesTest::provideGetters() and in
+ // MediaWikiServicesTest::provideGetService()!
+ ///////////////////////////////////////////////////////////////////////////
+
+}