Revert "LocalisationCache: Load only core data if possible"

This reverts commit cf8e22e1e4.

Bug: T342418
Bug: T343375
Change-Id: I6490ffba96b4f2d65d9206a4942f29d24d8bbecb
This commit is contained in:
Ahmon Dancy 2023-08-02 19:10:01 +00:00 committed by Jforrester
parent cf8e22e1e4
commit e4e613b0d1
2 changed files with 22 additions and 140 deletions

View file

@ -130,18 +130,6 @@ class LocalisationCache {
*/
private $recachedLangs = [];
/**
* An array indicating whether core data for a language has been loaded.
* If the entry for a language code $code is true,
* then {@link self::$data} is guaranteed to contain an array for $code,
* with at least an entry (possibly null) for each of the {@link self::CORE_ONLY_KEYS},
* and all the core-only keys will be marked as loaded in {@link self::$loadedItems} too.
* Additionally, there will be a 'deps' entry for $code with the dependencies tracked so far.
*
* @var array<string,bool>
*/
private $coreDataLoaded = [];
/**
* All item keys
*/
@ -450,29 +438,13 @@ class LocalisationCache {
* @param string $key
*/
private function loadItem( $code, $key ) {
if ( isset( $this->loadedItems[$code][$key] ) ) {
return;
}
if (
in_array( $key, self::CORE_ONLY_KEYS, true ) ||
// "synthetic" keys added by loadCoreData based on "fallback"
$key === 'fallbackSequence' ||
$key === 'originalFallbackSequence'
) {
if ( $this->langNameUtils->isValidBuiltInCode( $code ) ) {
$this->loadCoreData( $code );
return;
}
}
if ( !isset( $this->initialisedLangs[$code] ) ) {
$this->initLanguage( $code );
}
// Check to see if initLanguage() loaded it for us
if ( isset( $this->loadedItems[$code][$key] ) ) {
return;
}
// Check to see if initLanguage() loaded it for us
if ( isset( $this->loadedItems[$code][$key] ) ) {
return;
}
if ( isset( $this->shallowFallbacks[$code] ) ) {
@ -668,7 +640,6 @@ class LocalisationCache {
$this->loadedItems[$primaryCode] =& $this->loadedItems[$fallbackCode];
$this->loadedSubitems[$primaryCode] =& $this->loadedSubitems[$fallbackCode];
$this->shallowFallbacks[$primaryCode] = $fallbackCode;
$this->coreDataLoaded[$primaryCode] =& $this->coreDataLoaded[$fallbackCode];
}
/**
@ -837,7 +808,8 @@ class LocalisationCache {
/**
* Read the data from the source files for a given language, and register
* the relevant dependencies in the $deps array.
* the relevant dependencies in the $deps array. If the localisation
* exists, the data array is returned, otherwise false is returned.
*
* @param string $code
* @param array &$deps
@ -853,26 +825,12 @@ class LocalisationCache {
$data = $this->readPHPFile( $fileName, 'core' );
}
return $data;
}
/**
* Read and compile the plural data for a given language,
* and register the relevant dependencies in the $deps array.
*
* @param string $code
* @param array &$deps
* @return array
*/
private function readPluralFilesAndRegisterDeps( $code, &$deps ) {
$data = [
// Load CLDR plural rules for JavaScript
'pluralRules' => $this->getPluralRules( $code ),
// And for PHP
'compiledPluralRules' => $this->getCompiledPluralRules( $code ),
// Load plural rule types
'pluralRuleTypes' => $this->getPluralRuleTypes( $code ),
];
// Load CLDR plural rules for JavaScript
$data['pluralRules'] = $this->getPluralRules( $code );
// And for PHP
$data['compiledPluralRules'] = $this->getCompiledPluralRules( $code );
// Load plural rule types
$data['pluralRuleTypes'] = $this->getPluralRuleTypes( $code );
foreach ( self::PLURAL_FILES as $fileName ) {
$deps[] = new FileDependency( $fileName );
@ -952,24 +910,20 @@ class LocalisationCache {
}
/**
* Load the core localisation data for a given language code,
* without extensions, using only the process cache.
* See {@link self::$coreDataLoaded} for what this guarantees.
*
* In addition to the core-only keys,
* {@link self::$data} may contain additional entries for $code,
* but those must not be used outside of {@link self::recache()}
* (and accordingly, they are not marked as loaded yet).
* Load localisation data for a given language for both core and extensions
* and save it to the persistent cache store and the process cache
* @param string $code
* @throws MWException
*/
private function loadCoreData( string $code ) {
public function recache( $code ) {
if ( !$code ) {
throw new MWException( "Invalid language code requested" );
}
if ( $this->coreDataLoaded[$code] ?? false ) {
return;
}
$this->recachedLangs[ $code ] = true;
$coreData = array_fill_keys( self::CORE_ONLY_KEYS, null );
# Initial values
$initialData = array_fill_keys( self::ALL_KEYS, null );
$coreData = $initialData;
$deps = [];
# Load the primary localisation from the source file
@ -1004,63 +958,6 @@ class LocalisationCache {
}
}
foreach ( $coreData['fallbackSequence'] as $fbCode ) {
// load core fallback data
$fbData = $this->readSourceFilesAndRegisterDeps( $fbCode, $deps );
foreach ( self::CORE_ONLY_KEYS as $key ) {
// core-only keys are not mergeable, only set if not present in core data yet
if ( isset( $fbData[$key] ) && !isset( $coreData[$key] ) ) {
$coreData[$key] = $fbData[$key];
}
}
}
$coreData['deps'] = $deps;
foreach ( $coreData as $key => $item ) {
$this->data[$code][$key] ??= null;
// @phan-suppress-next-line PhanTypeArraySuspiciousNullable -- we just set a default null
$this->mergeItem( $key, $this->data[$code][$key], $item );
if (
in_array( $key, self::CORE_ONLY_KEYS, true ) ||
// "synthetic" keys based on "fallback" (see above)
$key === 'fallbackSequence' ||
$key === 'originalFallbackSequence'
) {
// only mark core-only keys as loaded;
// we may have loaded additional ones from the source file,
// but they are not fully loaded yet, since recache()
// may have to merge in additional values from fallback languages
$this->loadedItems[$code][$key] = true;
}
}
$this->coreDataLoaded[$code] = true;
}
/**
* Load localisation data for a given language for both core and extensions
* and save it to the persistent cache store and the process cache
* @param string $code
* @throws MWException
*/
public function recache( $code ) {
if ( !$code ) {
throw new MWException( "Invalid language code requested" );
}
$this->recachedLangs[ $code ] = true;
# Initial values
$initialData = array_fill_keys( self::ALL_KEYS, null );
$this->data[$code] = [];
$this->loadedItems[$code] = [];
$this->loadedSubitems[$code] = [];
$this->coreDataLoaded[$code] = false;
$this->loadCoreData( $code );
$coreData = $this->data[$code];
// @phan-suppress-next-line PhanTypeArraySuspiciousNullable -- guaranteed by loadCoreData()
$deps = $coreData['deps'];
$coreData += $this->readPluralFilesAndRegisterDeps( $code, $deps );
$codeSequence = array_merge( [ $code ], $coreData['fallbackSequence'] );
$messageDirs = $this->getMessagesDirs();
@ -1132,14 +1029,13 @@ class LocalisationCache {
# Load the secondary localisation from the source file to
# avoid infinite cycles on cyclic fallbacks
$fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps );
$fbData += $this->readPluralFilesAndRegisterDeps( $csCode, $deps );
# Only merge the keys that make sense to merge
foreach ( self::ALL_KEYS as $key ) {
if ( !isset( $fbData[ $key ] ) ) {
continue;
}
if ( !isset( $coreData[ $key ] ) || self::isMergeableKey( $key ) ) {
if ( ( $coreData[ $key ] ) === null || self::isMergeableKey( $key ) ) {
$this->mergeItem( $key, $csData[ $key ], $fbData[ $key ] );
}
}
@ -1284,7 +1180,6 @@ class LocalisationCache {
unset( $this->initialisedLangs[$code] );
unset( $this->shallowFallbacks[$code] );
unset( $this->sourceLanguage[$code] );
unset( $this->coreDataLoaded[$code] );
foreach ( $this->shallowFallbacks as $shallowCode => $fbCode ) {
if ( $fbCode === $code ) {

View file

@ -3,7 +3,6 @@
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Tests\Unit\DummyServicesTrait;
use Psr\Log\NullLogger;
use Wikimedia\TestingAccessWrapper;
/**
* @group Database
@ -151,18 +150,6 @@ class LocalisationCacheTest extends MediaWikiIntegrationTestCase {
);
}
public function testLoadCoreDataAvoidsInitLanguage(): void {
$lc = $this->getMockLocalisationCache();
$lc->getItem( 'de', 'fallback' );
$lc->getItem( 'de', 'rtl' );
$lc->getItem( 'de', 'fallbackSequence' );
$lc->getItem( 'de', 'originalFallbackSequence' );
$this->assertArrayNotHasKey( 'de',
TestingAccessWrapper::newFromObject( $lc )->initialisedLangs );
}
public function testShallowFallbackForInvalidCode(): void {
$lc = $this->getMockLocalisationCache();
$invalidCode = '!invalid!';