ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
MigratedLanguageFileSyncEntryRulesTest Class Reference

Entry rules of MigratedLanguageFileSync: delta/reset decisions, database sanitising, overlay presence, msgctxt handling. More...

+ Inheritance diagram for MigratedLanguageFileSyncEntryRulesTest:
+ Collaboration diagram for MigratedLanguageFileSyncEntryRulesTest:

Public Member Functions

 testBelongsInDelta (?string $shipped_value, string $value, bool $expected)
 belongsInDelta() alone decides what enters the overlay; tested without sync()'s file I/O. More...
 
 testResolveLocalValue (?string $shipped_value, string $value, string $expected)
 Shared by belongsInDelta() and ilObjLanguageExt::_saveValues(): an empty value resets to the shipped one, but only for a key the shipped .po carries. More...
 
 testDatabaseValuesSanitizesOnlyAnUnmodifiedValueEqualToTheShippedOne ()
 databaseValues() sanitises only an unmodified value equal to the shipped one (for the database mirror); a locally changed value stays untouched, its markup is checked by the caller. More...
 
 testDatabaseValuesLeavesAnAlreadyAllowedUnmodifiedValueByteIdentical ()
 
 testDatabaseValuesOfSanitizesAgainstTheRealShippedPo ()
 
 testDatabaseValuesOfLeavesEntriesUnchangedWhenTheModuleIsNotMigratedForTheLanguage ()
 A module not migrated for the language (no shipped .po): $entries come back unchanged. More...
 
 testDatabaseValuesOfLeavesEntriesUnchangedWhenTheShippedPoCannotBeRead ()
 An unreadable shipped .po must not abort the database write: $entries come back unchanged (the overlay write reports the file). More...
 
 testHasOverlayIsTrueWhenEitherOverlayFileExists ()
 
 testHasOverlayIsFalseWithoutAnyOverlayFile ()
 
 testHasOverlayIsFalseForAnUnknownModuleOrWithoutClientDataDir ()
 
 testHasOverlayIsTrueEvenForAnIrregularFileAtTheOverlayPosition ()
 hasOverlay() reports a non-regular file (e.g. More...
 
 testModuleEntriesIncludesAnEntryWithoutAnyContext ()
 An entry without msgctxt (null) belongs to whichever module reads the catalog. More...
 
 testModuleEntriesIgnoresAnEntryOfAForeignContext (string $context)
 An entry with an empty msgctxt is a foreign context, not "no context". More...
 
 testModuleEntriesPrefersTheModuleContextEntryOverTheContextlessOne (bool $module_first)
 A key with and without context: the module-context entry wins regardless of catalog order. More...
 
 testFindModuleEntryFallsBackToTheContextlessEntry ()
 
 testFindModuleEntryPrefersTheModuleContextEntry ()
 
 testFindModuleEntryReturnsNullForAForeignContext ()
 
 testFindModuleEntryIgnoresAnEmptyStringContextInsteadOfTreatingItAsContextless ()
 BUG (documented, not fixed): unlike moduleEntries(), findModuleEntry()'s fallback $catalog->find(null, $identifier) also matches an entry with msgctxt "" - gettext/gettext builds the key as "{$context}\004{$original}", so null and '' collide. More...
 
 testLoadShippedModuleEntriesIncludesAContextlessEntry ()
 End-to-end: a contextless shipped entry is served for the module via loadShippedModuleEntries(). More...
 
 testSyncTreatsAContextlessShippedEntryAsThisModulesShippedValue ()
 End-to-end: sync() reads a contextless shipped entry as the module's shipped value, so resyncing it creates no overlay. More...
 

Static Public Member Functions

static belongsInDeltaCases ()
 
static resolveLocalValueCases ()
 
static foreignContexts ()
 
static contextOrders ()
 
- Static Public Member Functions inherited from MigratedLanguageFileSyncTestCase
static refreshFlags ()
 

Additional Inherited Members

- Protected Member Functions inherited from MigratedLanguageFileSyncTestCase
 setUp ()
 
 tearDown ()
 
 seedShipped (array $entries, string $lang_key='de', string $module=self::MODULE)
 
 seedOverlay (array $entries, string $lang_key='de')
 
 shippedPo (string $lang_key='de', string $module=self::MODULE)
 
 overlayBase (string $lang_key='de')
 
 overlayPo ()
 
 sync (array $entries, bool $refresh=false, ?string $client_data_dir='default')
 
 overlayIdentifiers ()
 
 overlayDirectory ()
 
 findUnwritable (array $lang_keys=['de'], ?string $client_data_dir='default', ?LanguageFileDirectoryManager $manager=null)
 
- Protected Attributes inherited from MigratedLanguageFileSyncTestCase
const string MODULE = 'stest'
 
string $fixture_directory
 
string $client_data_dir
 
string $ilias_root
 
LanguageFileDirectory $directory
 
LanguageFileDirectoryManager $manager
 

Detailed Description

Entry rules of MigratedLanguageFileSync: delta/reset decisions, database sanitising, overlay presence, msgctxt handling.

Definition at line 34 of file MigratedLanguageFileSyncEntryRulesTest.php.

Member Function Documentation

◆ belongsInDeltaCases()

static MigratedLanguageFileSyncEntryRulesTest::belongsInDeltaCases ( )
static
Returns
array<string, array{0: ?string, 1: string, 2: bool}>

Definition at line 46 of file MigratedLanguageFileSyncEntryRulesTest.php.

46 : array
47 {
48 return [
49 'differs from shipped' => ['Hallo', 'Servus', true],
50 'same as shipped' => ['Hallo', 'Hallo', false],
51 'key not shipped at all - any non-empty value belongs' => [null, 'Eigener Wert', true],
52 'empty value resets to shipped, even without a shipped key' => [null, '', false],
53 'empty value resets to shipped, even when shipped differs' => ['Hallo', '', false],
54 'shipped value itself is empty, value matches' => ['', '', false],
55 'shipped value itself is empty, value differs' => ['', 'x', true],
56 'the literal string "0" belongs when shipped differs' => ['1', '0', true],
57 'the literal string "0" is not "empty" and does not reset' => [null, '0', true],
58 ];
59 }

◆ contextOrders()

static MigratedLanguageFileSyncEntryRulesTest::contextOrders ( )
static
Returns
array<string, array{0: bool}>

Definition at line 253 of file MigratedLanguageFileSyncEntryRulesTest.php.

253 : array
254 {
255 return ['module context first' => [true], 'contextless first' => [false]];
256 }

◆ foreignContexts()

static MigratedLanguageFileSyncEntryRulesTest::foreignContexts ( )
static
Returns
array<string, array{0: string}>

Definition at line 229 of file MigratedLanguageFileSyncEntryRulesTest.php.

229 : array
230 {
231 return ['empty-string msgctxt' => [''], 'context of another module' => ['other_module']];
232 }

◆ resolveLocalValueCases()

static MigratedLanguageFileSyncEntryRulesTest::resolveLocalValueCases ( )
static
Returns
array<string, array{0: ?string, 1: string, 2: string}>

Definition at line 74 of file MigratedLanguageFileSyncEntryRulesTest.php.

74 : array
75 {
76 return [
77 'empty value of a shipped key resolves to the shipped value' => ['Hallo', '', 'Hallo'],
78 'empty value of a key that is not shipped stays empty' => [null, '', ''],
79 'a non-empty value is returned unchanged, shipped key' => ['Hallo', 'Servus', 'Servus'],
80 'a non-empty value is returned unchanged, not a shipped key' => [null, 'Eigener Wert', 'Eigener Wert'],
81 'the shipped value itself is empty - stays empty (nothing to reset to in practice)' => ['', '', ''],
82 ];
83 }

◆ testBelongsInDelta()

MigratedLanguageFileSyncEntryRulesTest::testBelongsInDelta ( ?string  $shipped_value,
string  $value,
bool  $expected 
)

belongsInDelta() alone decides what enters the overlay; tested without sync()'s file I/O.

Definition at line 38 of file MigratedLanguageFileSyncEntryRulesTest.php.

38 : void
39 {
40 $this->assertSame($expected, MigratedLanguageFileSync::belongsInDelta($shipped_value, $value));
41 }

◆ testDatabaseValuesLeavesAnAlreadyAllowedUnmodifiedValueByteIdentical()

MigratedLanguageFileSyncEntryRulesTest::testDatabaseValuesLeavesAnAlreadyAllowedUnmodifiedValueByteIdentical ( )

Definition at line 106 of file MigratedLanguageFileSyncEntryRulesTest.php.

106 : void
107 {
108 $result = MigratedLanguageFileSync::databaseValues(['greeting' => 'Hallo'], ['greeting' => 'Hallo']);
109
110 $this->assertSame('Hallo', $result['greeting']);
111 }

◆ testDatabaseValuesOfLeavesEntriesUnchangedWhenTheModuleIsNotMigratedForTheLanguage()

MigratedLanguageFileSyncEntryRulesTest::testDatabaseValuesOfLeavesEntriesUnchangedWhenTheModuleIsNotMigratedForTheLanguage ( )

A module not migrated for the language (no shipped .po): $entries come back unchanged.

Definition at line 131 of file MigratedLanguageFileSyncEntryRulesTest.php.

131 : void
132 {
133 $bad = '<script>alert(1)</script>Hallo';
134
135 $result = MigratedLanguageFileSync::databaseValuesOf(
136 $this->manager,
137 $this->ilias_root,
138 'de',
139 'not_a_contributed_module',
140 ['greeting' => $bad]
141 );
142
143 $this->assertSame($bad, $result['greeting']);
144 }

◆ testDatabaseValuesOfLeavesEntriesUnchangedWhenTheShippedPoCannotBeRead()

MigratedLanguageFileSyncEntryRulesTest::testDatabaseValuesOfLeavesEntriesUnchangedWhenTheShippedPoCannotBeRead ( )

An unreadable shipped .po must not abort the database write: $entries come back unchanged (the overlay write reports the file).

Definition at line 150 of file MigratedLanguageFileSyncEntryRulesTest.php.

150 : void
151 {
152 file_put_contents($this->shippedPo(), "msgid \"kaputt\n");
153 $bad = '<script>alert(1)</script>Hallo';
154
155 $result = MigratedLanguageFileSync::databaseValuesOf(
156 $this->manager,
157 $this->ilias_root,
158 'de',
159 self::MODULE,
160 ['greeting' => $bad]
161 );
162
163 $this->assertSame($bad, $result['greeting']);
164 }
shippedPo(string $lang_key='de', string $module=self::MODULE)

References MigratedLanguageFileSyncTestCase\shippedPo().

+ Here is the call graph for this function:

◆ testDatabaseValuesOfSanitizesAgainstTheRealShippedPo()

MigratedLanguageFileSyncEntryRulesTest::testDatabaseValuesOfSanitizesAgainstTheRealShippedPo ( )

Definition at line 113 of file MigratedLanguageFileSyncEntryRulesTest.php.

113 : void
114 {
115 $bad = '<script>alert(1)</script>Hallo';
116 $this->seedShipped(['greeting' => $bad]);
117
118 $result = MigratedLanguageFileSync::databaseValuesOf(
119 $this->manager,
120 $this->ilias_root,
121 'de',
122 self::MODULE,
123 ['greeting' => $bad]
124 );
125
126 $this->assertStringNotContainsString('<script', $result['greeting']);
127 $this->assertStringContainsString('Hallo', $result['greeting']);
128 }
seedShipped(array $entries, string $lang_key='de', string $module=self::MODULE)

References MigratedLanguageFileSyncTestCase\seedShipped().

+ Here is the call graph for this function:

◆ testDatabaseValuesSanitizesOnlyAnUnmodifiedValueEqualToTheShippedOne()

MigratedLanguageFileSyncEntryRulesTest::testDatabaseValuesSanitizesOnlyAnUnmodifiedValueEqualToTheShippedOne ( )

databaseValues() sanitises only an unmodified value equal to the shipped one (for the database mirror); a locally changed value stays untouched, its markup is checked by the caller.

Definition at line 89 of file MigratedLanguageFileSyncEntryRulesTest.php.

89 : void
90 {
91 $bad = '<script>alert(1)</script>Hallo';
92
93 $result = MigratedLanguageFileSync::databaseValues(
94 ['unmodified' => $bad, 'changed' => $bad, 'not_shipped_at_all' => $bad],
95 ['unmodified' => $bad, 'changed' => 'Anderer Shipped-Wert']
96 );
97
98 $this->assertStringNotContainsString('<script', $result['unmodified']);
99 $this->assertStringContainsString('Hallo', $result['unmodified']);
100 // "changed" differs from its shipped value - databaseValues() does not touch it at all
101 $this->assertSame($bad, $result['changed']);
102 // no shipped counterpart at all - left untouched, too
103 $this->assertSame($bad, $result['not_shipped_at_all']);
104 }

◆ testFindModuleEntryFallsBackToTheContextlessEntry()

MigratedLanguageFileSyncEntryRulesTest::testFindModuleEntryFallsBackToTheContextlessEntry ( )

Definition at line 259 of file MigratedLanguageFileSyncEntryRulesTest.php.

259 : void
260 {
261 $catalog = new TranslationCatalog();
262 $catalog->add(MigratedPoFixture::entry(null, 'greeting', 'Hallo'));
263
264 $entry = MigratedLanguageFileSync::findModuleEntry($catalog, 'itest', 'greeting');
265
266 $this->assertNotNull($entry);
267 $this->assertSame('Hallo', $entry->getTranslation());
268 }
An in-memory gettext catalog (header block plus messages) and the only place of the component that re...
static entry(?string $context, string $id, string $value)

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testFindModuleEntryIgnoresAnEmptyStringContextInsteadOfTreatingItAsContextless()

MigratedLanguageFileSyncEntryRulesTest::testFindModuleEntryIgnoresAnEmptyStringContextInsteadOfTreatingItAsContextless ( )

BUG (documented, not fixed): unlike moduleEntries(), findModuleEntry()'s fallback $catalog->find(null, $identifier) also matches an entry with msgctxt "" - gettext/gettext builds the key as "{$context}\004{$original}", so null and '' collide.

Definition at line 294 of file MigratedLanguageFileSyncEntryRulesTest.php.

294 : void
295 {
296 $catalog = new TranslationCatalog();
297 $catalog->add(MigratedPoFixture::entry('', 'farewell', 'Leer'));
298
299 $this->assertNull(MigratedLanguageFileSync::findModuleEntry($catalog, 'itest', 'farewell'));
300 }

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testFindModuleEntryPrefersTheModuleContextEntry()

MigratedLanguageFileSyncEntryRulesTest::testFindModuleEntryPrefersTheModuleContextEntry ( )

Definition at line 270 of file MigratedLanguageFileSyncEntryRulesTest.php.

270 : void
271 {
272 $catalog = new TranslationCatalog();
273 $catalog->add(MigratedPoFixture::entry(null, 'greeting', 'Ohne Kontext'));
274 $catalog->add(MigratedPoFixture::entry('itest', 'greeting', 'Mit Modulkontext'));
275
276 $entry = MigratedLanguageFileSync::findModuleEntry($catalog, 'itest', 'greeting');
277
278 $this->assertSame('Mit Modulkontext', $entry?->getTranslation());
279 }

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testFindModuleEntryReturnsNullForAForeignContext()

MigratedLanguageFileSyncEntryRulesTest::testFindModuleEntryReturnsNullForAForeignContext ( )

Definition at line 281 of file MigratedLanguageFileSyncEntryRulesTest.php.

281 : void
282 {
283 $catalog = new TranslationCatalog();
284 $catalog->add(MigratedPoFixture::entry('other_module', 'greeting', 'Fremd'));
285
286 $this->assertNull(MigratedLanguageFileSync::findModuleEntry($catalog, 'itest', 'greeting'));
287 }

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testHasOverlayIsFalseForAnUnknownModuleOrWithoutClientDataDir()

MigratedLanguageFileSyncEntryRulesTest::testHasOverlayIsFalseForAnUnknownModuleOrWithoutClientDataDir ( )

Definition at line 181 of file MigratedLanguageFileSyncEntryRulesTest.php.

181 : void
182 {
183 $this->seedShipped(['greeting' => 'Hallo']);
184 $this->seedOverlay(['greeting' => 'Servus']);
185
186 $this->assertFalse(MigratedLanguageFileSync::hasOverlay($this->manager, 'de', 'other_module', $this->client_data_dir));
187 $this->assertFalse(MigratedLanguageFileSync::hasOverlay($this->manager, 'de', self::MODULE, null));
188 }
seedOverlay(array $entries, string $lang_key='de')

References MigratedLanguageFileSyncTestCase\seedOverlay(), and MigratedLanguageFileSyncTestCase\seedShipped().

+ Here is the call graph for this function:

◆ testHasOverlayIsFalseWithoutAnyOverlayFile()

MigratedLanguageFileSyncEntryRulesTest::testHasOverlayIsFalseWithoutAnyOverlayFile ( )

Definition at line 174 of file MigratedLanguageFileSyncEntryRulesTest.php.

174 : void
175 {
176 $this->seedShipped(['greeting' => 'Hallo']);
177
178 $this->assertFalse(MigratedLanguageFileSync::hasOverlay($this->manager, 'de', self::MODULE, $this->client_data_dir));
179 }

References MigratedLanguageFileSyncTestCase\seedShipped().

+ Here is the call graph for this function:

◆ testHasOverlayIsTrueEvenForAnIrregularFileAtTheOverlayPosition()

MigratedLanguageFileSyncEntryRulesTest::testHasOverlayIsTrueEvenForAnIrregularFileAtTheOverlayPosition ( )

hasOverlay() reports a non-regular file (e.g.

a directory) as present, unlike is_file(); reading it is covered by assertReadableOverlay().

Definition at line 194 of file MigratedLanguageFileSyncEntryRulesTest.php.

194 : void
195 {
196 $this->seedShipped(['greeting' => 'Hallo']);
197 mkdir($this->overlayBase() . '.po', 0775, true);
198
199 $this->assertTrue(MigratedLanguageFileSync::hasOverlay($this->manager, 'de', self::MODULE, $this->client_data_dir));
200 }

References MigratedLanguageFileSyncTestCase\overlayBase(), and MigratedLanguageFileSyncTestCase\seedShipped().

+ Here is the call graph for this function:

◆ testHasOverlayIsTrueWhenEitherOverlayFileExists()

MigratedLanguageFileSyncEntryRulesTest::testHasOverlayIsTrueWhenEitherOverlayFileExists ( )

Definition at line 166 of file MigratedLanguageFileSyncEntryRulesTest.php.

166 : void
167 {
168 $this->seedShipped(['greeting' => 'Hallo']);
169 $this->seedOverlay(['greeting' => 'Servus']);
170
171 $this->assertTrue(MigratedLanguageFileSync::hasOverlay($this->manager, 'de', self::MODULE, $this->client_data_dir));
172 }

References MigratedLanguageFileSyncTestCase\seedOverlay(), and MigratedLanguageFileSyncTestCase\seedShipped().

+ Here is the call graph for this function:

◆ testLoadShippedModuleEntriesIncludesAContextlessEntry()

MigratedLanguageFileSyncEntryRulesTest::testLoadShippedModuleEntriesIncludesAContextlessEntry ( )

End-to-end: a contextless shipped entry is served for the module via loadShippedModuleEntries().

Definition at line 303 of file MigratedLanguageFileSyncEntryRulesTest.php.

303 : void
304 {
305 $catalog = new TranslationCatalog();
306 $catalog->add(MigratedPoFixture::entry(null, 'greeting', 'Hallo'));
307 MigratedPoFixture::writePo($this->shippedPo(), $catalog);
308
309 $entries = MigratedLanguageFileSync::loadShippedModuleEntries($this->shippedPo(), self::MODULE);
310
311 $this->assertSame('Hallo', $entries['greeting']['value']);
312 }
static writePo(string $file, TranslationCatalog $catalog)

References MigratedPoFixture\entry(), MigratedLanguageFileSyncTestCase\shippedPo(), and MigratedPoFixture\writePo().

+ Here is the call graph for this function:

◆ testModuleEntriesIgnoresAnEntryOfAForeignContext()

MigratedLanguageFileSyncEntryRulesTest::testModuleEntriesIgnoresAnEntryOfAForeignContext ( string  $context)

An entry with an empty msgctxt is a foreign context, not "no context".

Definition at line 216 of file MigratedLanguageFileSyncEntryRulesTest.php.

216 : void
217 {
218 $catalog = new TranslationCatalog();
219 $catalog->add(MigratedPoFixture::entry($context, 'greeting', 'Fremd'));
220
221 $entries = MigratedLanguageFileSync::moduleEntries($catalog, 'itest');
222
223 $this->assertArrayNotHasKey('greeting', $entries);
224 }

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testModuleEntriesIncludesAnEntryWithoutAnyContext()

MigratedLanguageFileSyncEntryRulesTest::testModuleEntriesIncludesAnEntryWithoutAnyContext ( )

An entry without msgctxt (null) belongs to whichever module reads the catalog.

Definition at line 203 of file MigratedLanguageFileSyncEntryRulesTest.php.

203 : void
204 {
205 $catalog = new TranslationCatalog();
206 $catalog->add(MigratedPoFixture::entry(null, 'greeting', 'Hallo'));
207
208 $entries = MigratedLanguageFileSync::moduleEntries($catalog, 'itest');
209
210 $this->assertArrayHasKey('greeting', $entries);
211 $this->assertSame('Hallo', $entries['greeting']->getTranslation());
212 }

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testModuleEntriesPrefersTheModuleContextEntryOverTheContextlessOne()

MigratedLanguageFileSyncEntryRulesTest::testModuleEntriesPrefersTheModuleContextEntryOverTheContextlessOne ( bool  $module_first)

A key with and without context: the module-context entry wins regardless of catalog order.

Definition at line 236 of file MigratedLanguageFileSyncEntryRulesTest.php.

236 : void
237 {
238 $catalog = new TranslationCatalog();
239 $module_entry = MigratedPoFixture::entry('itest', 'greeting', 'Mit Modulkontext');
240 $contextless = MigratedPoFixture::entry(null, 'greeting', 'Ohne Kontext');
241 foreach ($module_first ? [$module_entry, $contextless] : [$contextless, $module_entry] as $entry) {
242 $catalog->add($entry);
243 }
244
245 $entries = MigratedLanguageFileSync::moduleEntries($catalog, 'itest');
246
247 $this->assertSame('Mit Modulkontext', $entries['greeting']->getTranslation());
248 }

References MigratedPoFixture\entry().

+ Here is the call graph for this function:

◆ testResolveLocalValue()

MigratedLanguageFileSyncEntryRulesTest::testResolveLocalValue ( ?string  $shipped_value,
string  $value,
string  $expected 
)

Shared by belongsInDelta() and ilObjLanguageExt::_saveValues(): an empty value resets to the shipped one, but only for a key the shipped .po carries.

Definition at line 66 of file MigratedLanguageFileSyncEntryRulesTest.php.

66 : void
67 {
68 $this->assertSame($expected, MigratedLanguageFileSync::resolveLocalValue($shipped_value, $value));
69 }

◆ testSyncTreatsAContextlessShippedEntryAsThisModulesShippedValue()

MigratedLanguageFileSyncEntryRulesTest::testSyncTreatsAContextlessShippedEntryAsThisModulesShippedValue ( )

End-to-end: sync() reads a contextless shipped entry as the module's shipped value, so resyncing it creates no overlay.

Definition at line 318 of file MigratedLanguageFileSyncEntryRulesTest.php.

318 : void
319 {
320 $catalog = new TranslationCatalog();
321 $catalog->add(MigratedPoFixture::entry(null, 'greeting', 'Hallo'));
322 MigratedPoFixture::writePo($this->shippedPo(), $catalog);
323
324 $this->sync(['greeting' => 'Hallo']);
325
326 $this->assertFileDoesNotExist($this->overlayBase() . '.po', 'unchanged from the contextless shipped value - no delta at all');
327 }
sync(array $entries, bool $refresh=false, ?string $client_data_dir='default')

References MigratedPoFixture\entry(), MigratedLanguageFileSyncTestCase\overlayBase(), MigratedLanguageFileSyncTestCase\shippedPo(), MigratedLanguageFileSyncTestCase\sync(), and MigratedPoFixture\writePo().

+ Here is the call graph for this function:

The documentation for this class was generated from the following file: