19declare(strict_types=1);
31use PHPUnit\Framework\Attributes\DataProvider;
32use PHPUnit\Framework\TestCase;
42 $this->
shipPo([
'greeting' =>
'Hallo',
'farewell' =>
'Tschüss']);
43 $this->
writeLang(
'lang/ilias_de.lang', [
'common#:#yes#:#Ja']);
45 $this->
manager()->insertLanguageForInstallation(
'de');
49 'common|yes' => [
'value' =>
'Ja',
'local_change' =>
null],
50 'pilot|greeting' => [
'value' =>
'Hallo',
'local_change' =>
null],
51 'pilot|farewell' => [
'value' =>
'Tschüss',
'local_change' =>
null],
55 $this->assertSame([
'greeting' =>
'Hallo',
'farewell' =>
'Tschüss'], $this->
lngModules()[self::MODULE]);
60 $this->
shipPo([
'greeting' =>
'Hallo']);
61 $this->
writeLang(
'lang/ilias_de.lang', [
'pilot#:#greeting#:#Alt aus lang/',
'pilot#:#stale#:#Veraltet']);
62 $this->
writeLang(
'components/pilot/lang/ilias_de.lang', [
'greeting#:#Alt aus Komponente']);
64 $this->
manager()->insertLanguageForInstallation(
'de');
66 $this->assertSame([
'greeting' =>
'Hallo'], $this->
lngModules()[self::MODULE]);
67 $this->assertArrayNotHasKey(
'pilot|stale', $this->
lngData());
75 $this->
shipPo([
'greeting' =>
'Hallo'],
'de');
76 $this->
writeLang(
'components/pilot/lang/ilias_en.lang', [
'greeting#:#Hello']);
78 $this->
manager()->insertLanguageForInstallation(
'en');
80 $this->assertSame([
'greeting' =>
'Hello'], $this->
lngModules()[self::MODULE]);
81 $this->assertDirectoryDoesNotExist($this->root .
'/client-data/lang');
89 $this->
shipPo([
'greeting' => [
'value' =>
'Hello',
'fuzzy' =>
true]]);
91 $this->
manager()->insertLanguageForInstallation(
'de');
94 $this->assertSame([
'.locks',
'taken-over.de.json'], array_values(array_diff(scandir($this->root .
'/client-data/lang'), [
'.',
'..'])));
96 [
'greeting' => [
'value' =>
'Hello',
'local_change' =>
false,
'local_change_date' =>
null,
'original' =>
'Hello']],
108 $this->
shipPo([
'greeting' =>
'Hallo']);
109 $this->
seedOverlay([
'greeting' => [
'value' =>
'Servus',
'original' =>
'Hallo',
'local_change' =>
'2020-01-01T00:00:00Z']]);
111 $held_locks =
new ReflectionProperty(MigratedLanguageFileSync::class,
'held_locks');
114 $manager = $this->
manager(
null,
function () use (&$observed, $held_locks, $lock_file):
void {
115 $observed = array_key_exists($lock_file, $held_locks->getValue());
118 $manager->insertLanguageForInstallation(
'de');
120 $this->assertTrue($observed,
'the module\'s overlay lock must already be held at this point in the run');
122 $this->assertSame([], $held_locks->getValue());
134 $this->root .
'/components/pilot/lang/zmod_de.po',
138 $this->root .
'/components/pilot/lang/amod_de.po',
142 $this->root .
'/client-data/lang/zmod/de/zmod_de',
146 $this->root .
'/client-data/lang/amod/de/amod_de',
149 $held_locks =
new ReflectionProperty(MigratedLanguageFileSync::class,
'held_locks');
150 $observed_order =
null;
158 static fn(): \DateTimeImmutable =>
new \DateTimeImmutable(self::NOW,
new \DateTimeZone(
'UTC')),
160 $observed_order = array_map(
161 static fn(
string $lock_file):
string => basename(dirname($lock_file, 2)) .
'/' . basename($lock_file),
162 array_keys($held_locks->getValue())
165 fn():
string => $this->root .
'/client-data'
170 $this->assertSame([
'amod/lock',
'zmod/lock'], $observed_order);
179 $this->
shipPo([
'greeting' =>
'Hallo']);
181 'greeting' => [
'value' =>
'Von einem parallelen Admin-Edit',
'original' =>
'Hallo',
'local_change' =>
'2020-01-01T00:00:00Z'],
184 $manager = $this->
manager(
null,
function () use ($concurrent_edit):
void {
188 $unwritten = $manager->insertLanguageForInstallation(
'de');
190 $this->assertSame([self::MODULE], $unwritten);
192 'Von einem parallelen Admin-Edit',
194 $this->
overlayPo()->find(self::MODULE,
'greeting')->getTranslation(),
195 'the concurrently-written overlay must survive untouched'
Lets a test observe or influence the invalidation.
An in-memory gettext catalog (header block plus messages) and the only place of the component that re...
Reads the shipped .po of a migrated module and maintains its per-installation overlay: the ....
The module array just written to lng_modules could not be read back - almost always a wrong collation...
Write access to the language installation: installing, flushing and registering languages in the data...
insertLanguageForInstallation(string $lang_key)
Installs or refreshes a language from every directory the LanguageFileDirectoryManager knows (includi...
Fixtures of the LanguageInstallationManager tests for modules migrated to PO/MO ("pilot").
shipPo(array $entries, string $lang_key='de')
seedOverlay(array $entries)
effective()
Shipped .po plus overlay delta, as served (MigratedLanguageFileSync::loadModuleTranslations()) - the ...
manager(?\Closure $client_data_dir_resolver=null, ?\Closure $language_cache_invalidator=null, bool $with_resolver=true, bool $with_logger=true, ?LoggerInterface $logger=null)
writeLang(string $relative_file, array $lines)
testAModuleWithAnExistingOverlayIsLockedForTheWholeRunNotJustItsOwnSync()
A module that already has an overlay when insertLanguage() decides what to lock is locked (MigratedLa...
testAModuleIsOnlyMigratedForLanguagesWithAShippedPo()
Only languages that ship a .po are migrated: for another language the .lang lines are used.
testAModuleWithoutAnOverlayThatGetsOneCreatedDuringTheRunIsReportedAndTheOverlaySurvives()
A module without an overlay at that point is never locked (no lock file is created).
testLocksAreAcquiredInSortedOrderRegardlessOfTheContributedDirectoryOrder()
Deadlock protection: modules with an overlay are locked in one global order (module name,...
testLangLinesOfAMigratedModuleInNonLocalFilesAreIgnored()
testInstallWithoutLocalChangesWritesNoOverlayOnlyTheTakenOverRecord()
An installation without local changes writes no overlay file: the shipped state is served as is.
testValuesOfAMigratedModuleComeFromThePoEvenWithoutAnyLangLine()
The tos lines could be removed from lang/ilias_xx.lang: the database is filled from the shipped ....
static writePair(string $base_path, TranslationCatalog $catalog)
Writes "<base>.po" and, like MigratedLanguageFileSync::sync(), its compiled revision named by current...
static directory(string $prefix, string $path, bool $local=false)
static catalog(string $module, array $entries)
static writePo(string $file, TranslationCatalog $catalog)
static overlayLock(string $base_path)
A directory of language files with a path and a prefix for them.
Read-only access to the installed languages (database) and the available or valid language files (fil...