<?php
namespace MediaWiki;
-use ApiQueryInfo;
-use CentralIdLookup;
use Config;
use ConfigFactory;
-use DeferredUpdates;
-use FileBackendGroup;
+use EventRelayerGroup;
use GlobalVarConfig;
use Hooks;
-use IP;
-use JobQueueAggregator;
-use Language;
use LBFactory;
-use LinkCache;
+use Liuggio\StatsdClient\Factory\StatsdDataFactory;
use LoadBalancer;
-use LockManagerGroup;
-use MagicWord;
-use MediaHandler;
use MediaWiki\Services\ServiceContainer;
-use MediaWiki\Session\SessionManager;
-use MessageCache;
use MWException;
-use MWNamespace;
-use MWTidy;
-use ObjectCache;
-use RedisConnectionPool;
-use RepoGroup;
-use RequestContext;
use ResourceLoader;
+use SearchEngine;
+use SearchEngineConfig;
+use SearchEngineFactory;
use SiteLookup;
use SiteStore;
-use SpecialPageFactory;
-use Title;
-use User;
-use WatchedItemStore;
-use Wikimedia\Assert\Assert;
+use SkinFactory;
/**
* Service locator for MediaWiki core services.
$old = self::getInstance();
self::$instance = $services;
- self::resetLegacyServices();
-
return $old;
}
* was no previous instance, a new GlobalVarConfig object will be used to
* bootstrap the services.
*
- * @throws MWException
+ * @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 ) {
if ( self::$instance === null ) {
return;
}
+ self::failIfResetNotAllowed( __METHOD__ );
+
if ( $bootstrapConfig === null ) {
$bootstrapConfig = self::$instance->getBootstrapConfig();
}
self::$instance->destroy();
self::$instance = self::newInstance( $bootstrapConfig );
-
- self::resetLegacyServices();
}
/**
return $instance;
}
- /**
- * Resets global instances of services that have not yet been ported to using
- * MediaWikiServices to manage their default instance.
- *
- * @note eventually, all global service instances are to be managed by MediaWikiServices.
- * To emulate the effect of resetting the global service locator, we reset the individual
- * static singletons for now.
- *
- * @note As long as we don't know the interdependencies between the services, the only way
- * to reset services consistently is to reset all services at once. This should be ok since
- * there should rarely be a need to reset all processes.
- */
- private static function resetLegacyServices() {
- global $wgContLang, $wgUser, $wgMemc, $wgRequest;
-
- $services = self::getInstance();
- $config = $services->getMainConfig();
-
- // NOTE: all the services instance that get reset below should be migrated
- // to be managed by MediaWikiServices. Eventually, this method can then be
- // removed.
-
- User::resetIdByNameCache();
- LinkCache::singleton()->clear();
- Title::clearCaches();
-
- MWTidy::destroySingleton();
- MagicWord::clearCache();
- SpecialPageFactory::resetList();
- JobQueueAggregator::destroySingleton();
- DeferredUpdates::clearPendingUpdates();
- CentralIdLookup::resetCache();
- MediaHandler::resetCache();
- IP::clearCaches();
- ResourceLoader::clearCache();
-
- ApiQueryInfo::resetTokenCache();
-
- RepoGroup::destroySingleton();
-
- MessageCache::destroyInstance();
-
- MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
- Language::$mLangObjCache = [];
- Language::getLocalisationCache()->unloadAll();
-
- ObjectCache::clear();
- RedisConnectionPool::destroySingletons();
- FileBackendGroup::destroySingleton();
- LockManagerGroup::destroySingletons();
-
- RequestContext::resetMain();
- $wgRequest = RequestContext::getMain()->getRequest(); // BackCompat
-
- $wgContLang = Language::factory( $config->get( 'LanguageCode' ) );
- $wgContLang->resetNamespaces(); # reset namespace cache
-
- $wgMemc = ObjectCache::getLocalClusterInstance();
- $wgUser = RequestContext::getMain()->getUser();
-
- SessionManager::resetCache();
-
- // Provide a hook point for extensions that need to reset global service instances.
- Hooks::run( 'MediaWikiServices::resetLegacyServices', [ $services ] );
- }
-
/**
* 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
* @throws MWException if called outside of PHPUnit tests.
*/
public function resetServiceForTesting( $name, $destroy = true ) {
- if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+ if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
}
}
/**
- * Convenience method that throws an exception if called outside the service bootstrapping
- * phase as indicated by the MW_SERVICE_BOOTSTRAP_COMPLETE constant - that is, after
- * Setup.php has called resetGlobalInstance(). Additionally, no exception is thrown if
- * this method is called during unit testing (as indicated by MW_PHPUNIT_TEST) or
- * during installation (as indicated by MEDIAWIKI_INSTALL).
+ * 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.
+ *
+ * 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 keep the knowledge about
- * how the bootstrapping phase is managed central.
+ * 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__.
*
* @see forceGlobalInstance()
* @see disableStorageBackend()
*/
- public static function failUnlessBootstrapping( $method ) {
+ 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 unit tests!' );
+ throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
}
-
- ObjectCache::clear();
}
/**
return $this->getService( 'SiteStore' );
}
+ /**
+ * @return StatsdDataFactory
+ */
+ public function getStatsdDataFactory() {
+ return $this->getService( 'StatsdDataFactory' );
+ }
+
+ /**
+ * @return EventRelayerGroup
+ */
+ public function getEventRelayerGroup() {
+ return $this->getService( 'EventRelayerGroup' );
+ }
+
+ /**
+ * @return SearchEngine
+ */
+ public function newSearchEngine() {
+ // New engine object every time, since they keep state
+ return $this->getService( 'SearchEngineFactory' )->create();
+ }
+
+ /**
+ * @return SearchEngineFactory
+ */
+ public function getSearchEngineFactory() {
+ return $this->getService( 'SearchEngineFactory' );
+ }
+
+ /**
+ * @return SearchEngineConfig
+ */
+ public function getSearchEngineConfig() {
+ return $this->getService( 'SearchEngineConfig' );
+ }
+
+ /**
+ * @return SkinFactory
+ */
+ public function getSkinFactory() {
+ return $this->getService( 'SkinFactory' );
+ }
+
/**
* @return LBFactory
*/
return $this->getService( 'DBLoadBalancer' );
}
- /**
- * @return WatchedItemStore
- */
- public function getWatchedItemStore() {
- return $this->getService( 'WatchedItemStore' );
- }
-
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service getter here, don't forget to add a test
// case for it in MediaWikiServicesTest::provideGetters() and in