X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=blobdiff_plain;f=includes%2Fcache%2Flocalisation%2FLocalisationCache.php;h=c6d6b8fa5b753821d35160f527b23909253adcd7;hb=7d82ce8bfdda964197a46e5da863c2c59eac8a0c;hp=fb4675eb30215dd0314b92731ff066ea405228f6;hpb=c3ed5103cd469c12d01df6837a57b6f62698fd6e;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/cache/localisation/LocalisationCache.php b/includes/cache/localisation/LocalisationCache.php index fb4675eb30..c6d6b8fa5b 100644 --- a/includes/cache/localisation/LocalisationCache.php +++ b/includes/cache/localisation/LocalisationCache.php @@ -22,15 +22,14 @@ use CLDRPluralRuleParser\Evaluator; use CLDRPluralRuleParser\Error as CLDRPluralRuleError; -use MediaWiki\Config\ServiceOptions; -use MediaWiki\Languages\LanguageNameUtils; -use Psr\Log\LoggerInterface; +use MediaWiki\Logger\LoggerFactory; +use MediaWiki\MediaWikiServices; /** * Class for caching the contents of localisation files, Messages*.php * and *.i18n.php. * - * An instance of this class is available using MediaWikiServices. + * An instance of this class is available using Language::getLocalisationCache(). * * The values retrieved from here are merged, containing items from extension * files, core messages files and the language fallback sequence (e.g. zh-cn -> @@ -41,8 +40,8 @@ use Psr\Log\LoggerInterface; class LocalisationCache { const VERSION = 4; - /** @var ServiceOptions */ - private $options; + /** Configuration associative array */ + private $conf; /** * True if recaching should only be done on an explicit call to recache(). @@ -51,6 +50,11 @@ class LocalisationCache { */ private $manualRecache = false; + /** + * True to treat all files as expired until they are regenerated by this object. + */ + private $forceRecache = false; + /** * The cache data. 3-d array, where the first key is the language code, * the second key is the item key e.g. 'messages', and the third key is @@ -67,16 +71,10 @@ class LocalisationCache { private $store; /** - * @var LoggerInterface + * @var \Psr\Log\LoggerInterface */ private $logger; - /** @var callable[] See comment for parameter in constructor */ - private $clearStoreCallbacks; - - /** @var LanguageNameUtils */ - private $langNameUtils; - /** * A 2-d associative array, code/key, where presence indicates that the item * is loaded. Value arbitrary. @@ -190,52 +188,60 @@ class LocalisationCache { private $mergeableKeys = null; - /** - * @todo Make this a const when HHVM support is dropped (T192166) - * - * @var array - * @since 1.34 - */ - public static $constructorOptions = [ - // True to treat all files as expired until they are regenerated by this object. - 'forceRecache', - 'manualRecache', - 'ExtensionMessagesFiles', - 'MessagesDirs', - ]; - /** * For constructor parameters, see the documentation in DefaultSettings.php * for $wgLocalisationCacheConf. * - * Do not construct this directly. Use MediaWikiServices. - * - * @param ServiceOptions $options - * @param LCStore $store What backend to use for storage - * @param LoggerInterface $logger - * @param callable[] $clearStoreCallbacks To be called whenever the cache is cleared. Can be - * used to clear other caches that depend on this one, such as ResourceLoader's - * MessageBlobStore. - * @param LanguageNameUtils $langNameUtils + * @param array $conf * @throws MWException */ - function __construct( - ServiceOptions $options, - LCStore $store, - LoggerInterface $logger, - array $clearStoreCallbacks, - LanguageNameUtils $langNameUtils - ) { - $options->assertRequiredOptions( self::$constructorOptions ); - - $this->options = $options; - $this->store = $store; - $this->logger = $logger; - $this->clearStoreCallbacks = $clearStoreCallbacks; - $this->langNameUtils = $langNameUtils; - - // Keep this separate from $this->options so it can be mutable - $this->manualRecache = $options->get( 'manualRecache' ); + function __construct( $conf ) { + global $wgCacheDirectory; + + $this->conf = $conf; + $this->logger = LoggerFactory::getInstance( 'localisation' ); + + $directory = !empty( $conf['storeDirectory'] ) ? $conf['storeDirectory'] : $wgCacheDirectory; + $storeArg = []; + $storeArg['directory'] = $directory; + + if ( !empty( $conf['storeClass'] ) ) { + $storeClass = $conf['storeClass']; + } else { + switch ( $conf['store'] ) { + case 'files': + case 'file': + $storeClass = LCStoreCDB::class; + break; + case 'db': + $storeClass = LCStoreDB::class; + $storeArg['server'] = $conf['storeServer'] ?? []; + break; + case 'array': + $storeClass = LCStoreStaticArray::class; + break; + case 'detect': + if ( $directory ) { + $storeClass = LCStoreCDB::class; + } else { + $storeClass = LCStoreDB::class; + $storeArg['server'] = $conf['storeServer'] ?? []; + } + break; + default: + throw new MWException( + 'Please set $wgLocalisationCacheConf[\'store\'] to something sensible.' + ); + } + } + $this->logger->debug( static::class . ": using store $storeClass" ); + + $this->store = new $storeClass( $storeArg ); + foreach ( [ 'manualRecache', 'forceRecache' ] as $var ) { + if ( isset( $conf[$var] ) ) { + $this->$var = $conf[$var]; + } + } } /** @@ -400,7 +406,7 @@ class LocalisationCache { * @return bool */ public function isExpired( $code ) { - if ( $this->options->get( 'forceRecache' ) && !isset( $this->recachedLangs[$code] ) ) { + if ( $this->forceRecache && !isset( $this->recachedLangs[$code] ) ) { $this->logger->debug( __METHOD__ . "($code): forced reload" ); return true; @@ -445,7 +451,7 @@ class LocalisationCache { $this->initialisedLangs[$code] = true; # If the code is of the wrong form for a Messages*.php file, do a shallow fallback - if ( !$this->langNameUtils->isValidBuiltInCode( $code ) ) { + if ( !Language::isValidBuiltInCode( $code ) ) { $this->initShallowFallback( $code, 'en' ); return; @@ -453,7 +459,7 @@ class LocalisationCache { # Recache the data if necessary if ( !$this->manualRecache && $this->isExpired( $code ) ) { - if ( $this->langNameUtils->isSupportedLanguage( $code ) ) { + if ( Language::isSupportedLanguage( $code ) ) { $this->recache( $code ); } elseif ( $code === 'en' ) { throw new MWException( 'MessagesEn.php is missing.' ); @@ -513,17 +519,8 @@ class LocalisationCache { * @return array */ protected function readPHPFile( $_fileName, $_fileType ) { - // Disable APC caching - Wikimedia\suppressWarnings(); - $_apcEnabled = ini_set( 'apc.cache_by_default', '0' ); - Wikimedia\restoreWarnings(); - include $_fileName; - Wikimedia\suppressWarnings(); - ini_set( 'apc.cache_by_default', $_apcEnabled ); - Wikimedia\restoreWarnings(); - $data = []; if ( $_fileType == 'core' || $_fileType == 'extension' ) { foreach ( self::$allKeys as $key ) { @@ -691,7 +688,7 @@ class LocalisationCache { global $IP; // This reads in the PHP i18n file with non-messages l10n data - $fileName = $this->langNameUtils->getMessagesFileName( $code ); + $fileName = Language::getMessagesFileName( $code ); if ( !file_exists( $fileName ) ) { $data = []; } else { @@ -725,6 +722,7 @@ class LocalisationCache { if ( in_array( $key, self::$mergeableMapKeys ) ) { $value = $value + $fallbackValue; } elseif ( in_array( $key, self::$mergeableListKeys ) ) { + // @phan-suppress-next-line PhanTypeMismatchArgumentInternal $value = array_unique( array_merge( $fallbackValue, $value ) ); } elseif ( in_array( $key, self::$mergeableAliasListKeys ) ) { $value = array_merge_recursive( $value, $fallbackValue ); @@ -798,12 +796,14 @@ class LocalisationCache { public function getMessagesDirs() { global $IP; + $config = MediaWikiServices::getInstance()->getMainConfig(); + $messagesDirs = $config->get( 'MessagesDirs' ); return [ 'core' => "$IP/languages/i18n", 'exif' => "$IP/languages/i18n/exif", 'api' => "$IP/includes/api/i18n", 'oojs-ui' => "$IP/resources/lib/ooui/i18n", - ] + $this->options->get( 'MessagesDirs' ); + ] + $messagesDirs; } /** @@ -813,10 +813,12 @@ class LocalisationCache { * @throws MWException */ public function recache( $code ) { + global $wgExtensionMessagesFiles; + if ( !$code ) { throw new MWException( "Invalid language code requested" ); } - $this->recachedLangs[$code] = true; + $this->recachedLangs[ $code ] = true; # Initial values $initialData = array_fill_keys( self::$allKeys, null ); @@ -825,16 +827,11 @@ class LocalisationCache { # Load the primary localisation from the source file $data = $this->readSourceFilesAndRegisterDeps( $code, $deps ); - if ( $data === false ) { - $this->logger->debug( __METHOD__ . ": no localisation file for $code, using fallback to en" ); - $coreData['fallback'] = 'en'; - } else { - $this->logger->debug( __METHOD__ . ": got localisation for $code from source" ); + $this->logger->debug( __METHOD__ . ": got localisation for $code from source" ); - # Merge primary localisation - foreach ( $data as $key => $value ) { - $this->mergeItem( $key, $coreData[$key], $value ); - } + # Merge primary localisation + foreach ( $data as $key => $value ) { + $this->mergeItem( $key, $coreData[ $key ], $value ); } # Fill in the fallback if it's not there already @@ -864,7 +861,7 @@ class LocalisationCache { # Load non-JSON localisation data for extensions $extensionData = array_fill_keys( $codeSequence, $initialData ); - foreach ( $this->options->get( 'ExtensionMessagesFiles' ) as $extension => $fileName ) { + foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) { if ( isset( $messageDirs[$extension] ) ) { # This extension has JSON message data; skip the PHP shim continue; @@ -922,16 +919,14 @@ class LocalisationCache { # Load the secondary localisation from the source file to # avoid infinite cycles on cyclic fallbacks $fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps ); - if ( $fbData !== false ) { - # Only merge the keys that make sense to merge - foreach ( self::$allKeys as $key ) { - if ( !isset( $fbData[$key] ) ) { - continue; - } - - if ( is_null( $coreData[$key] ) || $this->isMergeableKey( $key ) ) { - $this->mergeItem( $key, $csData[$key], $fbData[$key] ); - } + # Only merge the keys that make sense to merge + foreach ( self::$allKeys as $key ) { + if ( !isset( $fbData[ $key ] ) ) { + continue; + } + + if ( is_null( $coreData[ $key ] ) || $this->isMergeableKey( $key ) ) { + $this->mergeItem( $key, $csData[ $key ], $fbData[ $key ] ); } } } @@ -1028,9 +1023,8 @@ class LocalisationCache { # HACK: If using a null (i.e. disabled) storage backend, we # can't write to the MessageBlobStore either if ( !$this->store instanceof LCStoreNull ) { - foreach ( $this->clearStoreCallbacks as $callback ) { - $callback(); - } + $blobStore = MediaWikiServices::getInstance()->getResourceLoader()->getMessageBlobStore(); + $blobStore->clear(); } } @@ -1091,4 +1085,5 @@ class LocalisationCache { $this->store = new LCStoreNull; $this->manualRecache = false; } + }