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

Guards the database handling of ilLanguagesInstalledAndUpdatedObjective: ilSetupLanguage resolves its database lazily, so setDbHandler() must stay authoritative; a regression would be silent because the global fallback takes over again. More...

+ Inheritance diagram for ilLanguagesInstalledAndUpdatedObjectiveTest:
+ Collaboration diagram for ilLanguagesInstalledAndUpdatedObjectiveTest:

Public Member Functions

 testInjectedDatabaseTakesPrecedenceOverTheGlobal ()
 
 testAchieveNeedsNoGlobalDatabaseAtAll ()
 
 testGetLabelNeedsNoDatabase ()
 
 testIsApplicableReadsTheLanguagesForTheLabelFromTheSetupDatabase ()
 
 testAchieveReusesTheLanguagesDeterminedInIsApplicable ()
 
 testInstallLanguagesActuallyFlushesBothTheNewlyInstalledAndTheAlreadyInstalledLanguage ()
 A mixed list of installed and not installed keys must flush and reinstall each: the new one via InstallLanguage, the installed one via UpdateLanguage (both built via forSetup() around the same mocked ilSetupLanguage). More...
 
 testFreshlyInstalledLanguageIsImmediatelyRefreshedAgainByUpdateLanguage ()
 The documented "harmless double cycle": a language just installed by InstallLanguage is flushed again by UpdateLanguage, because getInstalledLanguages() now reports it as installed. More...
 
 testAchieveSkipsInvalidLanguagesAndInformsTheAdministrator ()
 An invalid language file only skips that language (reported); valid ones are still refreshed. More...
 
 testAchieveReportsSkippedLanguagesViaErrorLogWithoutAdminInteraction ()
 
 testAchieveWithOnlyInvalidLanguagesDoesNotThrowAndWritesNothing ()
 
 testAchieveDoesNotInformWhenEveryLanguageIsValid ()
 
 testWarnsAboutAMissingClientDataDirectoryWhenMigratedModulesExist ()
 Without a resolvable client data directory no PO/MO overlay can be written: worth a warning instead of silently serving the modules from the database, but only if such a module exists. More...
 
 testNoWarningAboutAMissingClientDataDirectoryWithoutAnyMigratedModule ()
 Without any migrated module a missing client data directory is no warning. More...
 
 testNoWarningAboutAMissingClientDataDirectoryWithNoValidLanguageKeys ()
 With every requested language invalid, $language_keys is empty before informAboutMissingClientDataDirectory() is reached: no warning, whatever hasMigratedModules() says. More...
 
 testAchieveWarnsAboutUnwritableOverlayDirectoriesBeforeWritingAndStillUpdates ()
 Checked before anything is written: unwritable overlay directories of the languages about to be installed or updated are reported by name; the update still runs. More...
 
 testTheWritabilityCheckOnlyCoversTheLanguagesThatAreActuallyWritten ()
 Invalid languages are skipped before the check. More...
 
 testAchieveInformsAboutTheLanguagesWhoseOverlayCouldNotBeWritten ()
 Overlays that could not be written although the check passed (race, single unwritable file) are reported from the Activity results, every language once, from InstallLanguage and UpdateLanguage together. More...
 
 testAchieveWarnsAboutSkippedInvalidMarkupEntriesPerLanguage ()
 Customizing entries left out for disallowed markup (LanguageInstallationManager::getSkippedInvalidMarkupEntries()) are reported as a WARNING per language; the install/update is not aborted. More...
 
 testAchieveWarnsAboutSkippedDuplicateEntriesPerLanguage ()
 
 testAchieveWarnsAboutModulesWithAnUnreadableOverlayPerLanguage ()
 Modules left out because their overlay cannot be read are named per language; without any there is no such warning. More...
 
 testAchieveWarnsAboutOverlaysOfUnshippedModulesPerLanguage ()
 
 testAchieveWarnsAboutUnrecordedTakenOverModulesPerLanguage ()
 
 testAchieveWarnsAboutInvalidMarkupInPreExistingLocalChanges ()
 Legacy local changes written before the markup check are never modified or removed, only reported once per run as a WARNING naming the entry. More...
 
 testTheMarkupCheckOfLocalChangesReadsLngDataOnlyWhereItIsStillTheSource (string $lng_data_module, string $source, string $overlay_value, bool $expect_warning)
 Disallowed markup in lng_data only counts for modules before the takeover and for plugins; otherwise the overlay is checked. More...
 
 testAchieveDoesNotWarnAboutAnAllowedPreExistingLocalChange ()
 A legacy local change that is still allowed is not reported. More...
 
 testAchieveDoesNotWarnAboutInvalidMarkupWithoutAnySkippedEntry ()
 No skipped entries, no such warning. More...
 
 testInstallLanguagesReturnsTheDeduplicatedLanguagesWithAnUnwrittenOverlay ()
 installLanguages() returns the languages with an unwritten overlay; a missing result key counts as none, duplicates are removed. More...
 
 testInstallLanguagesWithDefaultDirectoriesOnlyReportsTheInstallResult ()
 With only the default directories no UpdateLanguage runs, so only InstallLanguage's result contributes. More...
 
 testAchieveWarnsWhenSetupDoesNotRunAsTheOwnerOfTheClientDataDirectory ()
 Writable is not enough: a Setup run as another user than the client data directory's owner is warned about. More...
 
 testAchieveDoesNotWarnWhenSetupRunsAsTheOwnerOfTheClientDataDirectory ()
 
 testTheOwnerWarningIsGivenInAdditionToTheUnwritableDirectoriesWarning ()
 The owner warning comes in addition to the unwritable-directories warning: that one concerns this run, the owner mismatch every later write by the web server. More...
 
 testNoOwnerWarningWithoutAnyMigratedModule ()
 The owner-mismatch warning only protects a migrated module's overlay: without a migrated module it is not given. More...
 
 testAnInstanceWithDefaultDirectoriesInstallsMissingLanguagesButNeverRefreshes ()
 An instance with only the default directories (plugin Setup Objectives) must never refresh an installed language: that would drop every component-contributed module from lng_data. More...
 
 testInstallLanguagesWithoutKeysDoesNothing ()
 
 testAchieveTakesTheClientDataDirFromTheSetupEnvironment ()
 
 testAchieveKeepsTheDefaultResolutionWithoutAUsableClientDataDir (\Closure $resources)
 
 testTheHashIsStableForTheSameDirectoryConfiguration ()
 
 testTheDefaultDirectoriesHashDiffersFromAnExplicitlyEqualConfiguration ()
 The default-directories instance never refreshes, so it must not collide with one built with an equal explicit configuration. More...
 
 testTheHashDiffersForDifferentDirectoryConfigurations (\Closure $a, \Closure $b)
 Each part of a directory's configuration (class, prefix, path, suffix) and a contributed directory must change the hash, otherwise the Setup keeps only one of two differently configured objectives. More...
 
 testTheBuildIsAPreconditionOnlyWithDirectoriesOfTheComponentGraph ()
 

Static Public Member Functions

static markupCheckSources ()
 
static incompleteClientEnvironments ()
 
static differingConfigurations ()
 

Protected Member Functions

 setUp ()
 
 tearDown ()
 

Private Member Functions

 createDatabaseMock (string $tag, array &$log)
 
 createSetupLanguageMock (array $installed_language_keys, array &$log)
 
 invokeInstallLanguages (ilLanguagesInstalledAndUpdatedObjective $objective, array $language_keys)
 installLanguages() is protected, so it is invoked via reflection, like ilSetupLanguageTest::callCheckLanguage(). More...
 
 createAchievableSetupLanguage (array $installed, array $invalid, array &$flushed, bool $default_directories=false)
 
 databaseStub ()
 
 informCollectingEnvironment (array &$messages)
 
 directoryOfAnotherUser (string $own_directory)
 
 iniStub (string $datadir)
 
 achieveCapturingClientDataDir (array $resources)
 
 hashFor (?LanguageFileDirectoryManager $manager)
 

Static Private Member Functions

static directory (string $prefix, string $path, bool $local=false)
 
static manager (LanguageFileDirectory ... $directories)
 

Private Attributes

bool $had_global_db
 
mixed $previous_global_db = null
 

Detailed Description

Guards the database handling of ilLanguagesInstalledAndUpdatedObjective: ilSetupLanguage resolves its database lazily, so setDbHandler() must stay authoritative; a regression would be silent because the global fallback takes over again.

Definition at line 36 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

Member Function Documentation

◆ achieveCapturingClientDataDir()

ilLanguagesInstalledAndUpdatedObjectiveTest::achieveCapturingClientDataDir ( array  $resources)
private
Parameters
array<string,mixed>$resources
Returns
list<?string> every value setClientDataDir() was called with

Definition at line 938 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

938 : array
939 {
940 $flushed = [];
941 $calls = [];
942 $setup_language = $this->createAchievableSetupLanguage([], [], $flushed);
943 $setup_language->method('setClientDataDir')->willReturnCallback(
944 static function (?string $dir) use (&$calls): void {
945 $calls[] = $dir;
946 }
947 );
948
949 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment(
950 [Setup\Environment::RESOURCE_DATABASE => $this->databaseStub()] + $resources
951 ));
952
953 return $calls;
954 }
createAchievableSetupLanguage(array $installed, array $invalid, array &$flushed, bool $default_directories=false)

◆ createAchievableSetupLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::createAchievableSetupLanguage ( array  $installed,
array  $invalid,
array &  $flushed,
bool  $default_directories = false 
)
private
Parameters
list<string>$flushed collects every flushed language key

Definition at line 262 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

262 : Stub&ilSetupLanguage
263 {
264 $setup_language = $this->createStub(ilSetupLanguage::class);
265 $setup_language->method('getInstalledLanguages')->willReturn($installed);
266 $setup_language->method('getAvailableLanguagesForInstallation')->willReturn([]);
267 $setup_language->method('getLocalLanguages')->willReturn([]);
268 $setup_language->method('getInvalidLocalLanguageFiles')->willReturn([]);
269 $setup_language->method('checkLanguageForInstallation')->willReturnCallback(
270 static fn(string $lang_key): bool => !in_array($lang_key, $invalid, true)
271 );
272 $setup_language->method('usesDefaultLanguageFileDirectories')->willReturn($default_directories);
273 $setup_language->method('flushLanguageForInstallation')->willReturnCallback(
274 static function (string $lang_key) use (&$flushed): void {
275 $flushed[] = $lang_key;
276 }
277 );
278
279 return $setup_language;
280 }
language handling for setup

Referenced by testAchieveDoesNotInformWhenEveryLanguageIsValid(), testAchieveInformsAboutTheLanguagesWhoseOverlayCouldNotBeWritten(), testAchieveReportsSkippedLanguagesViaErrorLogWithoutAdminInteraction(), testAchieveSkipsInvalidLanguagesAndInformsTheAdministrator(), testAchieveWarnsAboutInvalidMarkupInPreExistingLocalChanges(), testAchieveWarnsAboutModulesWithAnUnreadableOverlayPerLanguage(), testAchieveWarnsAboutOverlaysOfUnshippedModulesPerLanguage(), testAchieveWarnsAboutSkippedDuplicateEntriesPerLanguage(), testAchieveWarnsAboutSkippedInvalidMarkupEntriesPerLanguage(), testAchieveWarnsAboutUnrecordedTakenOverModulesPerLanguage(), testAchieveWarnsAboutUnwritableOverlayDirectoriesBeforeWritingAndStillUpdates(), testAchieveWithOnlyInvalidLanguagesDoesNotThrowAndWritesNothing(), testNoWarningAboutAMissingClientDataDirectoryWithNoValidLanguageKeys(), testNoWarningAboutAMissingClientDataDirectoryWithoutAnyMigratedModule(), testTheWritabilityCheckOnlyCoversTheLanguagesThatAreActuallyWritten(), and testWarnsAboutAMissingClientDataDirectoryWhenMigratedModulesExist().

+ Here is the caller graph for this function:

◆ createDatabaseMock()

ilLanguagesInstalledAndUpdatedObjectiveTest::createDatabaseMock ( string  $tag,
array &  $log 
)
private
Parameters
list<string>$log collects the tag of every database actually queried

Definition at line 64 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

65 {
66 $db = $this->createStub(ilDBInterface::class);
67 $db->method('quote')->willReturnCallback(static fn(mixed $value): string => "'" . (string) $value . "'");
68 $db->method('like')->willReturn('1=1');
69 $db->method('now')->willReturn('NOW()');
70 $db->method('nextId')->willReturn(1);
71 $db->method('manipulate')->willReturnCallback(static function () use ($tag, &$log): int {
72 $log[] = $tag;
73 return 1;
74 });
75 $db->method('query')->willReturnCallback(function () use ($tag, &$log) {
76 $log[] = $tag;
77 return $this->createStub(ilDBStatement::class);
78 });
79
80 // a single installed language, then exhausted; $rows must be captured by reference, or the
81 // "while ($row = fetchObject())" loops never end
82 $rows = [(object) ['title' => 'de', 'obj_id' => 7, 'description' => 'installed']];
83 $db->method('fetchObject')->willReturnCallback(static function () use (&$rows) {
84 return array_shift($rows);
85 });
86
87 return $db;
88 }
Interface ilDBInterface.
$log
Definition: ltiauth.php:50

References $log, ILIAS\Scripts\PHPStan\$rows, and ILIAS\Repository\object().

Referenced by testAchieveNeedsNoGlobalDatabaseAtAll(), testInjectedDatabaseTakesPrecedenceOverTheGlobal(), and testIsApplicableReadsTheLanguagesForTheLabelFromTheSetupDatabase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ createSetupLanguageMock()

ilLanguagesInstalledAndUpdatedObjectiveTest::createSetupLanguageMock ( array  $installed_language_keys,
array &  $log 
)
private
Parameters
list<string>$log collects the language key every write method was called with, in call order

Definition at line 177 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

177 : Stub&ilSetupLanguage
178 {
179 $setup_language = $this->createStub(ilSetupLanguage::class);
180 $setup_language->method('getInstalledLanguages')->willReturn($installed_language_keys);
181 $setup_language->method('getAvailableLanguagesForInstallation')->willReturn([]);
182 $setup_language->method('getLocalLanguages')->willReturn([]);
183 $setup_language->method('getInvalidLocalLanguageFiles')->willReturn([]);
184 $setup_language->method('checkLanguageForInstallation')->willReturn(true);
185 $setup_language->method('flushLanguageForInstallation')->willReturnCallback(
186 static function (string $lang_key) use (&$log): void {
187 $log[] = $lang_key;
188 }
189 );
190
191 return $setup_language;
192 }

References $log.

Referenced by testInstallLanguagesActuallyFlushesBothTheNewlyInstalledAndTheAlreadyInstalledLanguage().

+ Here is the caller graph for this function:

◆ databaseStub()

◆ differingConfigurations()

static ilLanguagesInstalledAndUpdatedObjectiveTest::differingConfigurations ( )
static

Definition at line 1066 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1066 : array
1067 {
1068 return [
1069 'default vs. with contributed directory' => [
1070 static fn() => null,
1071 static fn() => self::manager(self::directory('tos', 'components/ILIAS/TermsOfService/lang/')),
1072 ],
1073 'prefix differs' => [
1074 static fn() => self::manager(self::directory('tos', 'components/x/lang/')),
1075 static fn() => self::manager(self::directory('file', 'components/x/lang/')),
1076 ],
1077 'path differs' => [
1078 static fn() => self::manager(self::directory('tos', 'components/x/lang/')),
1079 static fn() => self::manager(self::directory('tos', 'components/y/lang/')),
1080 ],
1081 'suffix differs' => [
1082 static fn() => self::manager(self::directory('tos', 'components/x/lang/')),
1083 static fn() => self::manager(self::directory('tos', 'components/x/lang/', true)),
1084 ],
1085 'only the class differs' => [
1086 static fn() => self::manager(new \ILIAS\Language\ComponentTranslation\ComponentLanguageFileDirectory(new \ILIAS\Language(), 'tos')),
1087 static function (): LanguageFileDirectoryManager {
1088 $component = new \ILIAS\Language\ComponentTranslation\ComponentLanguageFileDirectory(new \ILIAS\Language(), 'tos');
1089 return self::manager(self::directory('tos', $component->getPath()));
1090 },
1091 ],
1092 ];
1093 }
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.

◆ directory()

static ilLanguagesInstalledAndUpdatedObjectiveTest::directory ( string  $prefix,
string  $path,
bool  $local = false 
)
staticprivate

Definition at line 1008 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1009 {
1010 return MigratedPoFixture::directory($prefix, $path, $local);
1011 }
static directory(string $prefix, string $path, bool $local=false)
A directory of language files with a path and a prefix for them.

References MigratedPoFixture\directory().

+ Here is the call graph for this function:

◆ directoryOfAnotherUser()

ilLanguagesInstalledAndUpdatedObjectiveTest::directoryOfAnotherUser ( string  $own_directory)
private

Definition at line 816 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

816 : string
817 {
818 if (posix_geteuid() === 0) {
819 if (!@chown($own_directory, 65534)) {
820 $this->markTestSkipped('Cannot hand a directory to another user.');
821 }
822 clearstatcache();
823 return $own_directory;
824 }
825 if (fileowner('/') === posix_geteuid()) {
826 $this->markTestSkipped('No directory of another user available.');
827 }
828
829 return '/';
830 }

◆ hashFor()

ilLanguagesInstalledAndUpdatedObjectiveTest::hashFor ( ?LanguageFileDirectoryManager  $manager)
private

Definition at line 1022 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1022 : string
1023 {
1024 $setup_language = new ilSetupLanguage('en', $manager);
1026 $setup_language,
1027 $this->createStub(\ILIAS\Language\Activities\InstallLanguage::class),
1028 $this->createStub(\ILIAS\Language\Activities\UpdateLanguage::class)
1029 ))->getHash();
1030 }

◆ incompleteClientEnvironments()

static ilLanguagesInstalledAndUpdatedObjectiveTest::incompleteClientEnvironments ( )
static

Definition at line 991 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

991 : array
992 {
993 return [
994 'no ini, no client id' => [static fn(ilIniFile $ini): array => []],
995 'no client id' => [static fn(ilIniFile $ini): array => [Setup\Environment::RESOURCE_ILIAS_INI => $ini]],
996 'no ini' => [static fn(ilIniFile $ini): array => [Setup\Environment::RESOURCE_CLIENT_ID => 'myclient']],
997 'client directory does not exist' => [static fn(ilIniFile $ini): array => [
998 Setup\Environment::RESOURCE_ILIAS_INI => $ini,
999 Setup\Environment::RESOURCE_CLIENT_ID => 'other',
1000 ]],
1001 'unsafe client id' => [static fn(ilIniFile $ini): array => [
1002 Setup\Environment::RESOURCE_ILIAS_INI => $ini,
1003 Setup\Environment::RESOURCE_CLIENT_ID => '../myclient',
1004 ]],
1005 ];
1006 }
INI file parser — compatibility wrapper.
An environment holds resources to be used in the setup process.
Definition: Environment.php:28

◆ informCollectingEnvironment()

ilLanguagesInstalledAndUpdatedObjectiveTest::informCollectingEnvironment ( array &  $messages)
private
Parameters
list<string>$messages collects every message passed to AdminInteraction::inform()

Definition at line 358 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

358 : Setup\Environment
359 {
360 $io = $this->createStub(Setup\AdminInteraction::class);
361 $io->method('inform')->willReturnCallback(static function (string $message) use (&$messages): void {
362 $messages[] = $message;
363 });
364
365 return new Setup\ArrayEnvironment([
366 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
367 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
368 ]);
369 }

References $message, and databaseStub().

Referenced by testAchieveInformsAboutTheLanguagesWhoseOverlayCouldNotBeWritten(), testAchieveWarnsAboutInvalidMarkupInPreExistingLocalChanges(), testAchieveWarnsAboutModulesWithAnUnreadableOverlayPerLanguage(), testAchieveWarnsAboutOverlaysOfUnshippedModulesPerLanguage(), testAchieveWarnsAboutSkippedDuplicateEntriesPerLanguage(), testAchieveWarnsAboutSkippedInvalidMarkupEntriesPerLanguage(), testAchieveWarnsAboutUnrecordedTakenOverModulesPerLanguage(), testAchieveWarnsAboutUnwritableOverlayDirectoriesBeforeWritingAndStillUpdates(), testNoWarningAboutAMissingClientDataDirectoryWithNoValidLanguageKeys(), testTheWritabilityCheckOnlyCoversTheLanguagesThatAreActuallyWritten(), and testWarnsAboutAMissingClientDataDirectoryWhenMigratedModulesExist().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ iniStub()

ilLanguagesInstalledAndUpdatedObjectiveTest::iniStub ( string  $datadir)
private

Definition at line 925 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

925 : ilIniFile
926 {
927 $ini = $this->createStub(ilIniFile::class);
928 $ini->method('readVariable')->willReturnCallback(
929 static fn(string $group, string $name): string => $group === 'clients' && $name === 'datadir' ? $datadir : ''
930 );
931 return $ini;
932 }

◆ invokeInstallLanguages()

ilLanguagesInstalledAndUpdatedObjectiveTest::invokeInstallLanguages ( ilLanguagesInstalledAndUpdatedObjective  $objective,
array  $language_keys 
)
private

installLanguages() is protected, so it is invoked via reflection, like ilSetupLanguageTest::callCheckLanguage().

Parameters
list<string>$language_keys

Definition at line 199 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

199 : void
200 {
201 (new ReflectionMethod($objective, 'installLanguages'))->invoke($objective, $language_keys);
202 }

Referenced by testFreshlyInstalledLanguageIsImmediatelyRefreshedAgainByUpdateLanguage(), and testInstallLanguagesActuallyFlushesBothTheNewlyInstalledAndTheAlreadyInstalledLanguage().

+ Here is the caller graph for this function:

◆ manager()

◆ markupCheckSources()

static ilLanguagesInstalledAndUpdatedObjectiveTest::markupCheckSources ( )
static
Returns
array<string, array{0: string, 1: string, 2: string, 3: bool}> module of the lng_data change, source ("overlay": readable overlay, "record": taken over, none), value of the overlay entry, whether it is reported

Definition at line 625 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

625 : array
626 {
627 return [
628 'module with a readable overlay: lng_data is not read' => ['pilot', 'overlay', 'Hallo', false],
629 'module taken over: lng_data is not read' => ['pilot', 'record', 'Hallo', false],
630 'the overlay itself holds disallowed markup' => ['pilot', 'overlay', '<script>x</script>', true],
631 'module before the takeover: lng_data counts' => ['pilot', 'none', 'Hallo', true],
632 'module of no component: lng_data counts' => ['rep_robj_xtst', 'none', 'Hallo', true],
633 ];
634 }

◆ setUp()

ilLanguagesInstalledAndUpdatedObjectiveTest::setUp ( )
protected

Definition at line 43 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

43 : void
44 {
45 // never the build of the installation, see MigratedPoFixture::resetRuntime()
47 // these tests replace/remove $GLOBALS['ilDB'], which other tests in random order rely on
48 $this->had_global_db = isset($GLOBALS['ilDB']);
49 $this->previous_global_db = $GLOBALS['ilDB'] ?? null;
50 }
static resetRuntime(?string $artifact_directory=null)
Forgets the static state of the runtime read path and points build and runtime at $artifact_directory...
$GLOBALS["DIC"]
Definition: wac.php:66

References $GLOBALS, and MigratedPoFixture\resetRuntime().

+ Here is the call graph for this function:

◆ tearDown()

ilLanguagesInstalledAndUpdatedObjectiveTest::tearDown ( )
protected

Definition at line 52 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

52 : void
53 {
54 if ($this->had_global_db) {
56 } else {
57 unset($GLOBALS['ilDB']);
58 }
59 }

References $GLOBALS, and $previous_global_db.

◆ testAchieveDoesNotInformWhenEveryLanguageIsValid()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveDoesNotInformWhenEveryLanguageIsValid ( )

Definition at line 340 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

340 : void
341 {
342 $flushed = [];
343 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
344 $io = $this->createMock(Setup\AdminInteraction::class);
345 $io->expects($this->never())->method('inform');
346
347 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
348 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
349 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
350 ]));
351
352 $this->assertSame(['de'], $flushed);
353 }

References createAchievableSetupLanguage(), and databaseStub().

+ Here is the call graph for this function:

◆ testAchieveDoesNotWarnAboutAnAllowedPreExistingLocalChange()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveDoesNotWarnAboutAnAllowedPreExistingLocalChange ( )

A legacy local change that is still allowed is not reported.

Definition at line 689 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

689 : void
690 {
691 $flushed = [];
692 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
693 $setup_language->method('getSkippedInvalidMarkupEntries')->willReturn([]);
694 $setup_language->method('getClientDataDir')->willReturn(null);
695 $setup_language->method('getLocalChanges')->willReturn(['common' => ['greeting' => 'Hallo, geändert']]);
696 $messages = [];
697
698 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
699
700 $this->assertSame(
701 [],
702 array_values(array_filter($messages, static fn(string $m): bool => str_contains($m, 'Local changes')))
703 );
704 }

◆ testAchieveDoesNotWarnAboutInvalidMarkupWithoutAnySkippedEntry()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveDoesNotWarnAboutInvalidMarkupWithoutAnySkippedEntry ( )

No skipped entries, no such warning.

Definition at line 709 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

709 : void
710 {
711 $flushed = [];
712 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
713 $setup_language->method('getSkippedInvalidMarkupEntries')->willReturn([]);
714 $messages = [];
715
716 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
717
718 $this->assertSame(
719 [],
720 array_values(array_filter($messages, static fn(string $m): bool => str_contains($m, 'markup that is not allowed')))
721 );
722 }

◆ testAchieveDoesNotWarnWhenSetupRunsAsTheOwnerOfTheClientDataDirectory()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveDoesNotWarnWhenSetupRunsAsTheOwnerOfTheClientDataDirectory ( )

Definition at line 832 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

832 : void
833 {
834 if (function_exists('posix_geteuid') && posix_geteuid() === 0) {
835 $this->markTestSkipped('A Setup run as root is always warned about (running Setup as root is not supported).');
836 }
837 $datadir = sys_get_temp_dir() . '/ilias_obj_owner_' . bin2hex(random_bytes(4));
838 mkdir($datadir);
839 $flushed = [];
840 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
841 $setup_language->method('getClientDataDir')->willReturn($datadir);
842 $io = $this->createMock(Setup\AdminInteraction::class);
843 $io->expects($this->never())->method('inform');
844
845 try {
846 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
847 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
848 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
849 ]));
850 } finally {
852 }
853 }
static removeDirectory(string $directory)

References MigratedPoFixture\removeDirectory().

+ Here is the call graph for this function:

◆ testAchieveInformsAboutTheLanguagesWhoseOverlayCouldNotBeWritten()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveInformsAboutTheLanguagesWhoseOverlayCouldNotBeWritten ( )

Overlays that could not be written although the check passed (race, single unwritable file) are reported from the Activity results, every language once, from InstallLanguage and UpdateLanguage together.

Definition at line 478 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

478 : void
479 {
480 $install_language = $this->createMock(\ILIAS\Language\Activities\InstallLanguage::class);
481 $install_language->expects($this->once())->method('perform')->willReturn([
482 'overlay_write_failed_language_keys' => ['fr'],
483 ]);
484 $update_language = $this->createMock(\ILIAS\Language\Activities\UpdateLanguage::class);
485 $update_language->expects($this->once())->method('perform')->willReturn([
486 'overlay_write_failed_language_keys' => ['de', 'fr'],
487 ]);
488 $flushed = [];
489 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
490 $messages = [];
491
492 (new ilLanguagesInstalledAndUpdatedObjective($setup_language, $install_language, $update_language))
493 ->achieve($this->informCollectingEnvironment($messages));
494
495 $this->assertCount(1, $messages);
496 $this->assertStringStartsWith('WARNING:', $messages[0]);
497 $this->assertStringContainsString('the languages fr, de ', $messages[0]);
498 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveKeepsTheDefaultResolutionWithoutAUsableClientDataDir()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveKeepsTheDefaultResolutionWithoutAUsableClientDataDir ( \Closure  $resources)
Parameters
array<string,mixed>$resources

Definition at line 977 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

977 : void
978 {
979 $datadir = sys_get_temp_dir() . '/ilias_obj_cdd_' . bin2hex(random_bytes(4));
980 mkdir($datadir . '/myclient', 0775, true);
981
982 try {
983 $calls = $this->achieveCapturingClientDataDir($resources($this->iniStub($datadir)));
984 } finally {
986 }
987
988 $this->assertSame([], $calls, 'setClientDataDir() must not be called (not even with null)');
989 }

References MigratedPoFixture\removeDirectory().

+ Here is the call graph for this function:

◆ testAchieveNeedsNoGlobalDatabaseAtAll()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveNeedsNoGlobalDatabaseAtAll ( )

Definition at line 109 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

109 : void
110 {
111 $log = [];
112 unset($GLOBALS['ilDB']);
113
115 $environment = new Setup\ArrayEnvironment([
116 Setup\Environment::RESOURCE_DATABASE => $this->createDatabaseMock('INJECTED', $log),
117 // the real ilSetupLanguage resolves the client data directory of the running installation; its owner check may
118 // warn (e.g. as root), which is unrelated here
119 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $this->createStub(Setup\AdminInteraction::class),
120 ]);
121
122 $objective->achieve($environment);
123
124 $this->assertFalse(isset($GLOBALS['ilDB']), 'the global database must not be (re)created');
125 $this->assertSame(['INJECTED'], array_values(array_unique($log)));
126 }

References $GLOBALS, $log, and createDatabaseMock().

+ Here is the call graph for this function:

◆ testAchieveReportsSkippedLanguagesViaErrorLogWithoutAdminInteraction()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveReportsSkippedLanguagesViaErrorLogWithoutAdminInteraction ( )

Definition at line 311 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

311 : void
312 {
313 $this->expectErrorLog();
314 $flushed = [];
315 $setup_language = $this->createAchievableSetupLanguage(['de', 'xx'], ['xx'], $flushed);
316
317 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
318 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
319 ]));
320
321 $this->assertSame(['de'], $flushed);
322 $this->assertStringContainsString('xx', (string) file_get_contents((string) ini_get('error_log')));
323 }

References createAchievableSetupLanguage(), and databaseStub().

+ Here is the call graph for this function:

◆ testAchieveReusesTheLanguagesDeterminedInIsApplicable()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveReusesTheLanguagesDeterminedInIsApplicable ( )

Definition at line 153 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

153 : void
154 {
155 $setup_language = $this->createMock(ilSetupLanguage::class);
156 $setup_language->expects($this->once())->method('getInstalledLanguages')->willReturn(['de', 'fr']);
157 $setup_language->method('checkLanguageForInstallation')->willReturn(true);
158 $install_language = $this->createMock(\ILIAS\Language\Activities\InstallLanguage::class);
159 $install_language->expects($this->once())->method('perform')
160 ->with(['language_keys' => ['de', 'fr'], 'mode' => \ILIAS\Language\Activities\InstallLanguage::MODE_INSTALL]);
161 $update_language = $this->createMock(\ILIAS\Language\Activities\UpdateLanguage::class);
162 $update_language->expects($this->once())->method('perform')->with(['language_keys' => ['de', 'fr']]);
163 $objective = new ilLanguagesInstalledAndUpdatedObjective($setup_language, $install_language, $update_language);
164 $environment = new Setup\ArrayEnvironment([
165 Setup\Environment::RESOURCE_DATABASE => $this->createStub(ilDBInterface::class),
166 ]);
167
168 $objective->isApplicable($environment);
169 $objective->achieve($environment);
170
171 $this->assertSame('Install/Update languages de, fr', $objective->getLabel());
172 }

◆ testAchieveSkipsInvalidLanguagesAndInformsTheAdministrator()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveSkipsInvalidLanguagesAndInformsTheAdministrator ( )

An invalid language file only skips that language (reported); valid ones are still refreshed.

Definition at line 290 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

290 : void
291 {
292 $flushed = [];
293 $setup_language = $this->createAchievableSetupLanguage(['de', 'xx', 'fr'], ['xx'], $flushed);
294 $messages = [];
295 $io = $this->createStub(Setup\AdminInteraction::class);
296 $io->method('inform')->willReturnCallback(static function (string $message) use (&$messages): void {
297 $messages[] = $message;
298 });
299
300 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
301 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
302 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
303 ]));
304
305 $this->assertSame(['de', 'fr'], $flushed, 'valid languages are refreshed, the invalid one is untouched');
306 $this->assertCount(1, $messages);
307 $this->assertStringContainsString('xx', $messages[0]);
308 $this->assertStringNotContainsString('de', str_replace('Skipped languages', '', $messages[0]));
309 }

References $message, createAchievableSetupLanguage(), and databaseStub().

+ Here is the call graph for this function:

◆ testAchieveTakesTheClientDataDirFromTheSetupEnvironment()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveTakesTheClientDataDirFromTheSetupEnvironment ( )

Definition at line 956 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

956 : void
957 {
958 $datadir = sys_get_temp_dir() . '/ilias_obj_cdd_' . bin2hex(random_bytes(4));
959 mkdir($datadir . '/myclient', 0775, true);
960
961 try {
962 $calls = $this->achieveCapturingClientDataDir([
963 Setup\Environment::RESOURCE_ILIAS_INI => $this->iniStub($datadir . '/'),
964 Setup\Environment::RESOURCE_CLIENT_ID => 'myclient',
965 ]);
966 } finally {
968 }
969
970 $this->assertSame([$datadir . '/myclient'], $calls);
971 }

References MigratedPoFixture\removeDirectory().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutInvalidMarkupInPreExistingLocalChanges()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutInvalidMarkupInPreExistingLocalChanges ( )

Legacy local changes written before the markup check are never modified or removed, only reported once per run as a WARNING naming the entry.

Definition at line 598 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

598 : void
599 {
600 $this->expectErrorLog();
601 $flushed = [];
602 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
603 $setup_language->method('getSkippedInvalidMarkupEntries')->willReturn([]);
604 $setup_language->method('getClientDataDir')->willReturn(null);
605 $setup_language->method('getLocalChanges')->willReturn([
606 'common' => ['greeting' => '<script>alert(1)</script>'],
607 ]);
608 $messages = [];
609
610 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
611
612 $warnings = array_values(array_filter(
613 $messages,
614 static fn(string $m): bool => str_contains($m, 'Local changes') && str_contains($m, 'contain HTML')
615 ));
616 $this->assertCount(1, $warnings);
617 $this->assertStringContainsString('common#:#greeting', $warnings[0]);
618 $this->assertStringContainsString('de', $warnings[0]);
619 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutModulesWithAnUnreadableOverlayPerLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutModulesWithAnUnreadableOverlayPerLanguage ( )

Modules left out because their overlay cannot be read are named per language; without any there is no such warning.

Definition at line 545 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

545 : void
546 {
547 $flushed = [];
548 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
549 $setup_language->method('getSkippedUnreadableOverlays')->willReturn(['de' => ['common', 'tos']]);
550 $messages = [];
551
552 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
553
554 $warnings = array_values(array_filter($messages, static fn(string $m): bool => str_contains($m, 'cannot be read for the modules')));
555 $this->assertCount(1, $warnings);
556 $this->assertStringStartsWith('WARNING:', $warnings[0]);
557 $this->assertStringContainsString('language de', $warnings[0]);
558 $this->assertStringContainsString('common, tos', $warnings[0]);
559 $this->assertStringContainsString('rollback copy in lng_data/lng_modules is incomplete', $warnings[0]);
560 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutOverlaysOfUnshippedModulesPerLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutOverlaysOfUnshippedModulesPerLanguage ( )

Definition at line 562 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

562 : void
563 {
564 $flushed = [];
565 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
566 $setup_language->method('getOverlaysOfUnshippedModules')->willReturn(['de' => ['common', 'tos']]);
567 $messages = [];
568
569 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
570
571 $this->assertCount(1, $messages);
572 $this->assertStringStartsWith('WARNING:', $messages[0]);
573 $this->assertStringContainsString('common, tos', $messages[0]);
574 $this->assertStringContainsString('language de', $messages[0]);
575 $this->assertStringContainsString('taken-over.de.json', $messages[0]);
576 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutSkippedDuplicateEntriesPerLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutSkippedDuplicateEntriesPerLanguage ( )

Definition at line 526 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

526 : void
527 {
528 $flushed = [];
529 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
530 $setup_language->method('getSkippedDuplicateEntries')->willReturn([
531 'de' => ['common#:#greeting' => ['mme: greeting'], 'tos#:#x' => ['mme: x']],
532 ]);
533 $messages = [];
534
535 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
536
537 $warnings = array_values(array_filter($messages, static fn(string $m): bool => str_contains($m, 'were not applied')));
538 $this->assertCount(1, $warnings);
539 $this->assertStringStartsWith('WARNING: Customizing entries of language de ', $warnings[0]);
540 $this->assertStringContainsString('common#:#greeting, tos#:#x', $warnings[0]);
541 $this->assertStringContainsString('another module', $warnings[0]);
542 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutSkippedInvalidMarkupEntriesPerLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutSkippedInvalidMarkupEntriesPerLanguage ( )

Customizing entries left out for disallowed markup (LanguageInstallationManager::getSkippedInvalidMarkupEntries()) are reported as a WARNING per language; the install/update is not aborted.

Definition at line 504 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

504 : void
505 {
506 $flushed = [];
507 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
508 $setup_language->method('getSkippedInvalidMarkupEntries')->willReturn([
509 'de' => ['common#:#greeting' => ['tag <script>']],
510 'fr' => ['common#:#farewell' => ['comment " i"']],
511 ]);
512 $messages = [];
513
514 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
515
516 $warnings = array_values(array_filter($messages, static fn(string $m): bool => str_starts_with($m, 'WARNING:')));
517 $this->assertCount(2, $warnings);
518 $this->assertTrue(
519 (bool) array_filter($warnings, static fn(string $m): bool => str_contains($m, 'de') && str_contains($m, 'common#:#greeting'))
520 );
521 $this->assertTrue(
522 (bool) array_filter($warnings, static fn(string $m): bool => str_contains($m, 'fr') && str_contains($m, 'common#:#farewell'))
523 );
524 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutUnrecordedTakenOverModulesPerLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutUnrecordedTakenOverModulesPerLanguage ( )

Definition at line 578 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

578 : void
579 {
580 $flushed = [];
581 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
582 $setup_language->method('getUnrecordedTakenOverModules')->willReturn(['fr' => ['common']]);
583 $messages = [];
584
585 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
586
587 $this->assertCount(1, $messages);
588 $this->assertStringStartsWith('WARNING:', $messages[0]);
589 $this->assertStringContainsString('language fr', $messages[0]);
590 $this->assertStringContainsString('modules common', $messages[0]);
591 $this->assertStringContainsString('taken-over.fr.json', $messages[0]);
592 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsAboutUnwritableOverlayDirectoriesBeforeWritingAndStillUpdates()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsAboutUnwritableOverlayDirectoriesBeforeWritingAndStillUpdates ( )

Checked before anything is written: unwritable overlay directories of the languages about to be installed or updated are reported by name; the update still runs.

Definition at line 430 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

430 : void
431 {
432 $flushed = [];
433 $events = [];
434 $setup_language = $this->createAchievableSetupLanguage(['de', 'fr'], [], $flushed);
435 $setup_language->method('findUnwritableOverlayDirectories')->willReturnCallback(
436 static function (array $lang_keys) use (&$events, &$flushed): array {
437 $events[] = ['check', $lang_keys, count($flushed)];
438 return ['/data/client/lang/components/pilot/lang', '/data/client/lang/components/other/lang'];
439 }
440 );
441 $messages = [];
442
443 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
444
445 $this->assertSame([['check', ['de', 'fr'], 0]], $events, 'checked once, for all languages, before any write');
446 $this->assertSame(['de', 'fr'], $flushed, 'the update is not aborted');
447 $this->assertCount(1, $messages);
448 $this->assertStringStartsWith('WARNING:', $messages[0]);
449 $this->assertStringContainsString('/data/client/lang/components/pilot/lang, /data/client/lang/components/other/lang', $messages[0]);
450 $this->assertStringContainsString('web server user', $messages[0]);
451 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testAchieveWarnsWhenSetupDoesNotRunAsTheOwnerOfTheClientDataDirectory()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWarnsWhenSetupDoesNotRunAsTheOwnerOfTheClientDataDirectory ( )

Writable is not enough: a Setup run as another user than the client data directory's owner is warned about.

As root the directory is handed to a non-root user, otherwise "/" (root-owned) serves as another user's directory, which fires the root-specific branch ("$owner === 0", "belongs to root") instead; the assertions therefore branch on the observed owner.

Definition at line 783 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

783 : void
784 {
785 if (!function_exists('posix_geteuid')) {
786 $this->markTestSkipped('The owner check needs the POSIX extension.');
787 }
788 $datadir = sys_get_temp_dir() . '/ilias_obj_owner_' . bin2hex(random_bytes(4));
789 mkdir($datadir);
790 try {
791 $foreign_dir = $this->directoryOfAnotherUser($datadir);
792 $flushed = [];
793 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
794 $setup_language->method('getClientDataDir')->willReturn($foreign_dir);
795 // the owner-mismatch warning is only given when there is a migrated module's overlay to protect
796 $setup_language->method('hasMigratedModules')->willReturn(true);
797 $foreign_owner = fileowner($foreign_dir);
798 $messages = [];
799
800 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
801 } finally {
803 }
804
805 $this->assertNotSame(posix_geteuid(), $foreign_owner);
806 $this->assertCount(1, $messages);
807 $this->assertStringStartsWith('WARNING: Setup runs as user id ' . posix_geteuid() . ',', $messages[0]);
808 if ($foreign_owner === 0) {
809 $this->assertStringContainsString('belongs to root', $messages[0]);
810 } else {
811 $this->assertStringContainsString($foreign_dir . ' belongs to user id ' . $foreign_owner . '.', $messages[0]);
812 }
813 $this->assertSame(['de'], $flushed);
814 }

References MigratedPoFixture\removeDirectory().

+ Here is the call graph for this function:

◆ testAchieveWithOnlyInvalidLanguagesDoesNotThrowAndWritesNothing()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAchieveWithOnlyInvalidLanguagesDoesNotThrowAndWritesNothing ( )

Definition at line 325 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

325 : void
326 {
327 $flushed = [];
328 $setup_language = $this->createAchievableSetupLanguage(['xx'], ['xx'], $flushed);
329 $io = $this->createMock(Setup\AdminInteraction::class);
330 $io->expects($this->once())->method('inform');
331
332 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
333 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
334 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
335 ]));
336
337 $this->assertSame([], $flushed);
338 }

References createAchievableSetupLanguage(), and databaseStub().

+ Here is the call graph for this function:

◆ testAnInstanceWithDefaultDirectoriesInstallsMissingLanguagesButNeverRefreshes()

ilLanguagesInstalledAndUpdatedObjectiveTest::testAnInstanceWithDefaultDirectoriesInstallsMissingLanguagesButNeverRefreshes ( )

An instance with only the default directories (plugin Setup Objectives) must never refresh an installed language: that would drop every component-contributed module from lng_data.

Definition at line 905 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

905 : void
906 {
907 $flushed = [];
908 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed, true);
909
910 $this->invokeInstallLanguages(new ilLanguagesInstalledAndUpdatedObjective($setup_language), ['de', 'fr']);
911
912 $this->assertSame(['fr'], $flushed);
913 }
invokeInstallLanguages(ilLanguagesInstalledAndUpdatedObjective $objective, array $language_keys)
installLanguages() is protected, so it is invoked via reflection, like ilSetupLanguageTest::callCheck...

◆ testFreshlyInstalledLanguageIsImmediatelyRefreshedAgainByUpdateLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testFreshlyInstalledLanguageIsImmediatelyRefreshedAgainByUpdateLanguage ( )

The documented "harmless double cycle": a language just installed by InstallLanguage is flushed again by UpdateLanguage, because getInstalledLanguages() now reports it as installed.

Intentional, see ilLanguagesInstalledAndUpdatedObjective::installLanguages().

Definition at line 225 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

225 : void
226 {
227 $log = [];
228 $newly_installed = [];
229
230 $setup_language = $this->createStub(ilSetupLanguage::class);
231 $setup_language->method('getInstalledLanguages')->willReturnCallback(
232 static function () use (&$newly_installed): array {
233 return array_merge(['de'], $newly_installed);
234 }
235 );
236 $setup_language->method('getAvailableLanguagesForInstallation')->willReturn([]);
237 $setup_language->method('getLocalLanguages')->willReturn([]);
238 $setup_language->method('getInvalidLocalLanguageFiles')->willReturn([]);
239 $setup_language->method('checkLanguageForInstallation')->willReturn(true);
240 $setup_language->method('flushLanguageForInstallation')->willReturnCallback(
241 static function (string $lang_key) use (&$log): void {
242 $log[] = $lang_key;
243 }
244 );
245 // the write that makes 'fr' visible as installed to later getInstalledLanguages() calls, like a real INSERT
246 $setup_language->method('registerInstalledLanguage')->willReturnCallback(
247 static function (string $lang_key) use (&$newly_installed): void {
248 $newly_installed[] = $lang_key;
249 }
250 );
251
252 $objective = new ilLanguagesInstalledAndUpdatedObjective($setup_language);
253 $this->invokeInstallLanguages($objective, ['de', 'fr']);
254
255 // 'fr' is flushed by InstallLanguage; UpdateLanguage then sees ['de', 'fr'] and flushes both again
256 $this->assertSame(['fr', 'de', 'fr'], $log);
257 }

References $log, and invokeInstallLanguages().

+ Here is the call graph for this function:

◆ testGetLabelNeedsNoDatabase()

ilLanguagesInstalledAndUpdatedObjectiveTest::testGetLabelNeedsNoDatabase ( )

Definition at line 128 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

128 : void
129 {
130 unset($GLOBALS['ilDB']);
131 $setup_language = $this->createMock(ilSetupLanguage::class);
132 $setup_language->expects($this->never())->method('getInstalledLanguages');
133
134 $objective = new ilLanguagesInstalledAndUpdatedObjective($setup_language);
135
136 $this->assertSame('Install/Update languages', $objective->getLabel());
137 }

References $GLOBALS.

◆ testInjectedDatabaseTakesPrecedenceOverTheGlobal()

ilLanguagesInstalledAndUpdatedObjectiveTest::testInjectedDatabaseTakesPrecedenceOverTheGlobal ( )

Definition at line 90 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

90 : void
91 {
92 $log = [];
93 $GLOBALS['ilDB'] = $this->createDatabaseMock('GLOBAL', $log);
94
95 $setup_language = new ilSetupLanguage('de');
96 $setup_language->setDbHandler($this->createDatabaseMock('INJECTED', $log));
97
98 $setup_language->getInstalledLanguages();
99 $setup_language->registerInstalledLanguage('de', [], []);
100
101 $this->assertNotEmpty($log, 'no database was queried at all');
102 $this->assertSame(
103 ['INJECTED'],
104 array_values(array_unique($log)),
105 'the global was used even though a database had been injected'
106 );
107 }

References $GLOBALS, $log, and createDatabaseMock().

+ Here is the call graph for this function:

◆ testInstallLanguagesActuallyFlushesBothTheNewlyInstalledAndTheAlreadyInstalledLanguage()

ilLanguagesInstalledAndUpdatedObjectiveTest::testInstallLanguagesActuallyFlushesBothTheNewlyInstalledAndTheAlreadyInstalledLanguage ( )

A mixed list of installed and not installed keys must flush and reinstall each: the new one via InstallLanguage, the installed one via UpdateLanguage (both built via forSetup() around the same mocked ilSetupLanguage).

Definition at line 208 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

208 : void
209 {
210 $log = [];
211 $setup_language = $this->createSetupLanguageMock(['de'], $log);
212
213 $objective = new ilLanguagesInstalledAndUpdatedObjective($setup_language);
214 $this->invokeInstallLanguages($objective, ['de', 'fr']);
215
216 // 'fr' is flushed by InstallLanguage, then 'de' by UpdateLanguage: installLanguages() runs InstallLanguage first
217 $this->assertSame(['fr', 'de'], $log);
218 }
createSetupLanguageMock(array $installed_language_keys, array &$log)

References $log, createSetupLanguageMock(), and invokeInstallLanguages().

+ Here is the call graph for this function:

◆ testInstallLanguagesReturnsTheDeduplicatedLanguagesWithAnUnwrittenOverlay()

ilLanguagesInstalledAndUpdatedObjectiveTest::testInstallLanguagesReturnsTheDeduplicatedLanguagesWithAnUnwrittenOverlay ( )

installLanguages() returns the languages with an unwritten overlay; a missing result key counts as none, duplicates are removed.

Definition at line 728 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

728 : void
729 {
730 $install_language = $this->createStub(\ILIAS\Language\Activities\InstallLanguage::class);
731 $install_language->method('perform')->willReturn(['overlay_write_failed_language_keys' => ['fr', 'de']]);
732 $update_language = $this->createStub(\ILIAS\Language\Activities\UpdateLanguage::class);
733 $update_language->method('perform')->willReturn(['overlay_write_failed_language_keys' => ['de', 'it']]);
734 $flushed = [];
736 $this->createAchievableSetupLanguage([], [], $flushed),
737 $install_language,
738 $update_language
739 );
740
741 $this->assertSame(
742 ['fr', 'de', 'it'],
743 (new ReflectionMethod($objective, 'installLanguages'))->invoke($objective, ['de', 'fr', 'it'])
744 );
745
746 $install_without_field = $this->createStub(\ILIAS\Language\Activities\InstallLanguage::class);
747 $install_without_field->method('perform')->willReturn([]);
748 $update_without_field = $this->createStub(\ILIAS\Language\Activities\UpdateLanguage::class);
749 $update_without_field->method('perform')->willReturn([]);
751 $this->createAchievableSetupLanguage([], [], $flushed),
752 $install_without_field,
753 $update_without_field
754 );
755 $this->assertSame([], (new ReflectionMethod($objective, 'installLanguages'))->invoke($objective, ['de']));
756 }

◆ testInstallLanguagesWithDefaultDirectoriesOnlyReportsTheInstallResult()

ilLanguagesInstalledAndUpdatedObjectiveTest::testInstallLanguagesWithDefaultDirectoriesOnlyReportsTheInstallResult ( )

With only the default directories no UpdateLanguage runs, so only InstallLanguage's result contributes.

Definition at line 761 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

761 : void
762 {
763 $install_language = $this->createStub(\ILIAS\Language\Activities\InstallLanguage::class);
764 $install_language->method('perform')->willReturn(['overlay_write_failed_language_keys' => ['fr']]);
765 $update_language = $this->createMock(\ILIAS\Language\Activities\UpdateLanguage::class);
766 $update_language->expects($this->never())->method('perform');
767 $flushed = [];
769 $this->createAchievableSetupLanguage([], [], $flushed, true),
770 $install_language,
771 $update_language
772 );
773
774 $this->assertSame(['fr'], (new ReflectionMethod($objective, 'installLanguages'))->invoke($objective, ['fr']));
775 }

◆ testInstallLanguagesWithoutKeysDoesNothing()

ilLanguagesInstalledAndUpdatedObjectiveTest::testInstallLanguagesWithoutKeysDoesNothing ( )

Definition at line 915 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

915 : void
916 {
917 $flushed = [];
918 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
919
921
922 $this->assertSame([], $flushed);
923 }

◆ testIsApplicableReadsTheLanguagesForTheLabelFromTheSetupDatabase()

ilLanguagesInstalledAndUpdatedObjectiveTest::testIsApplicableReadsTheLanguagesForTheLabelFromTheSetupDatabase ( )

Definition at line 139 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

139 : void
140 {
141 $log = [];
142 unset($GLOBALS['ilDB']);
144 $environment = new Setup\ArrayEnvironment([
145 Setup\Environment::RESOURCE_DATABASE => $this->createDatabaseMock('INJECTED', $log),
146 ]);
147
148 $this->assertTrue($objective->isApplicable($environment));
149 $this->assertSame('Install/Update languages de', $objective->getLabel());
150 $this->assertSame(['INJECTED'], array_values(array_unique($log)));
151 }

References $GLOBALS, $log, and createDatabaseMock().

+ Here is the call graph for this function:

◆ testNoOwnerWarningWithoutAnyMigratedModule()

ilLanguagesInstalledAndUpdatedObjectiveTest::testNoOwnerWarningWithoutAnyMigratedModule ( )

The owner-mismatch warning only protects a migrated module's overlay: without a migrated module it is not given.

Definition at line 883 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

883 : void
884 {
885 if (!function_exists('posix_geteuid')) {
886 $this->markTestSkipped('The owner check needs the POSIX extension.');
887 }
888 $flushed = [];
889 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
890 $setup_language->method('getClientDataDir')->willReturn('/');
891 $setup_language->method('hasMigratedModules')->willReturn(false);
892 $io = $this->createMock(Setup\AdminInteraction::class);
893 $io->expects($this->never())->method('inform');
894
895 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
896 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
897 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
898 ]));
899 }

◆ testNoWarningAboutAMissingClientDataDirectoryWithNoValidLanguageKeys()

ilLanguagesInstalledAndUpdatedObjectiveTest::testNoWarningAboutAMissingClientDataDirectoryWithNoValidLanguageKeys ( )

With every requested language invalid, $language_keys is empty before informAboutMissingClientDataDirectory() is reached: no warning, whatever hasMigratedModules() says.

Definition at line 411 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

411 : void
412 {
413 $flushed = [];
414 $setup_language = $this->createAchievableSetupLanguage(['xx'], ['xx'], $flushed);
415 $setup_language->method('getClientDataDir')->willReturn(null);
416 $setup_language->method('hasMigratedModules')->willReturn(true);
417 $messages = [];
418
419 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
420
421 // the "invalid language" notice is expected, the missing-client-data-dir warning is not
422 $this->assertCount(1, $messages);
423 $this->assertStringStartsWith('Skipped languages', $messages[0]);
424 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testNoWarningAboutAMissingClientDataDirectoryWithoutAnyMigratedModule()

ilLanguagesInstalledAndUpdatedObjectiveTest::testNoWarningAboutAMissingClientDataDirectoryWithoutAnyMigratedModule ( )

Without any migrated module a missing client data directory is no warning.

Definition at line 392 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

392 : void
393 {
394 $flushed = [];
395 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
396 $setup_language->method('getClientDataDir')->willReturn(null);
397 $setup_language->method('hasMigratedModules')->willReturn(false);
398 $io = $this->createMock(Setup\AdminInteraction::class);
399 $io->expects($this->never())->method('inform');
400
401 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve(new Setup\ArrayEnvironment([
402 Setup\Environment::RESOURCE_DATABASE => $this->databaseStub(),
403 Setup\Environment::RESOURCE_ADMIN_INTERACTION => $io,
404 ]));
405 }

References createAchievableSetupLanguage(), and databaseStub().

+ Here is the call graph for this function:

◆ testTheBuildIsAPreconditionOnlyWithDirectoriesOfTheComponentGraph()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheBuildIsAPreconditionOnlyWithDirectoriesOfTheComponentGraph ( )

Definition at line 1095 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1095 : void
1096 {
1097 $environment = $this->createStub(Setup\Environment::class);
1098
1100 $this->assertCount(1, $default->getPreconditions($environment));
1101 $this->assertInstanceOf(ilDatabaseInitializedObjective::class, $default->getPreconditions($environment)[0]);
1102
1104 $setup_language = new ilSetupLanguage('en', $manager);
1105 $preconditions = (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->getPreconditions($environment);
1106
1107 $this->assertCount(2, $preconditions);
1108 $this->assertInstanceOf(ilDatabaseInitializedObjective::class, $preconditions[0]);
1109 $this->assertSame(
1111 $this->createStub(\ILIAS\Refinery\Factory::class),
1112 $setup_language,
1113 $this->createStub(\ILIAS\Language\Activities\InstallLanguage::class),
1114 $this->createStub(\ILIAS\Language\Activities\UpdateLanguage::class)
1115 ))->getBuildObjective()->getHash(),
1116 $preconditions[1]->getHash(),
1117 'the same objective as the build of the agent, so Setup achieves it once'
1118 );
1119 }

◆ testTheDefaultDirectoriesHashDiffersFromAnExplicitlyEqualConfiguration()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheDefaultDirectoriesHashDiffersFromAnExplicitlyEqualConfiguration ( )

The default-directories instance never refreshes, so it must not collide with one built with an equal explicit configuration.

Definition at line 1048 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1048 : void
1049 {
1050 $this->assertNotSame(
1051 $this->hashFor(null),
1053 );
1054 }

◆ testTheHashDiffersForDifferentDirectoryConfigurations()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheHashDiffersForDifferentDirectoryConfigurations ( \Closure  $a,
\Closure  $b 
)

Each part of a directory's configuration (class, prefix, path, suffix) and a contributed directory must change the hash, otherwise the Setup keeps only one of two differently configured objectives.

Definition at line 1061 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1061 : void
1062 {
1063 $this->assertNotSame($this->hashFor($a()), $this->hashFor($b()));
1064 }
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples

References Vendor\Package\$a, and Vendor\Package\$b.

◆ testTheHashIsStableForTheSameDirectoryConfiguration()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheHashIsStableForTheSameDirectoryConfiguration ( )

Definition at line 1032 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

1032 : void
1033 {
1037 self::directory('tos', 'components/ILIAS/TermsOfService/lang/')
1038 );
1039
1040 $this->assertSame($this->hashFor($build()), $this->hashFor($build()));
1041 $this->assertMatchesRegularExpression('/^[0-9a-f]{64}$/', $this->hashFor($build()));
1042 }
static directory(string $prefix, string $path, bool $local=false)

◆ testTheMarkupCheckOfLocalChangesReadsLngDataOnlyWhereItIsStillTheSource()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheMarkupCheckOfLocalChangesReadsLngDataOnlyWhereItIsStillTheSource ( string  $lng_data_module,
string  $source,
string  $overlay_value,
bool  $expect_warning 
)

Disallowed markup in lng_data only counts for modules before the takeover and for plugins; otherwise the overlay is checked.

Definition at line 638 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

643 : void {
644 if ($expect_warning) {
645 $this->expectErrorLog();
646 }
647 $root = (string) realpath(__DIR__ . '/../../../../../');
648 $relative = 'components/ILIAS/Language/tests/Setup/tmp-markup-' . bin2hex(random_bytes(4)) . '/';
649 $client_data_dir = sys_get_temp_dir() . '/ilias_markup_check_' . bin2hex(random_bytes(4));
650 mkdir($client_data_dir, 0775, true);
651 $directory = MigratedPoFixture::directory('pilot', $relative);
652 $manager = new LanguageFileDirectoryManager(new CustomizingLanguageFileDirectory(), $directory);
653 try {
654 MigratedPoFixture::writePo($root . '/' . $relative . 'pilot_de.po', MigratedPoFixture::catalog('pilot', ['greeting' => 'Hallo']));
655 if ($source === 'overlay') {
657 MigratedPoFixture::overlayBase($client_data_dir, $directory, 'de'),
658 MigratedPoFixture::catalog('pilot', ['greeting' => ['value' => $overlay_value, 'original' => 'Hallo', 'local_change' => '2025-05-05T05:05:05Z']])
659 );
660 } elseif ($source === 'record') {
661 MigratedLanguageFileSync::markLocalChangesTakenOver($client_data_dir, 'de', ['pilot']);
662 }
663 $flushed = [];
664 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
665 $setup_language->method('getSkippedInvalidMarkupEntries')->willReturn([]);
666 $setup_language->method('getClientDataDir')->willReturn($client_data_dir);
667 $setup_language->method('getLanguageFileDirectoryManager')->willReturn($manager);
668 $setup_language->method('getLocalChanges')->willReturn([$lng_data_module => ['farewell' => '<script>alert(1)</script>']]);
669 $messages = [];
670
671 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
672
673 $warnings = array_values(array_filter($messages, static fn(string $m): bool => str_contains($m, 'Local changes')));
674 $this->assertCount($expect_warning ? 1 : 0, $warnings);
675 if ($expect_warning) {
676 // the overlay's own entry, or the lng_data row of a module without overlay and record
677 $this->assertStringContainsString($source === 'overlay' ? 'pilot#:#greeting' : $lng_data_module . '#:#farewell', $warnings[0]);
678 $this->assertSame($source !== 'overlay', str_contains($warnings[0], '#:#farewell'));
679 }
680 } finally {
681 MigratedPoFixture::removeDirectory($root . '/' . $relative);
682 MigratedPoFixture::removeDirectory($client_data_dir);
683 }
684 }
static writePair(string $base_path, TranslationCatalog $catalog)
Writes "<base>.po" and, like MigratedLanguageFileSync::sync(), its compiled revision named by current...
static catalog(string $module, array $entries)
static writePo(string $file, TranslationCatalog $catalog)
static overlayBase(string $client_data_dir, LanguageFileDirectory $directory, string $lang_key)
The overlay of $directory's module for $lang_key without the .po extension.

◆ testTheOwnerWarningIsGivenInAdditionToTheUnwritableDirectoriesWarning()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheOwnerWarningIsGivenInAdditionToTheUnwritableDirectoriesWarning ( )

The owner warning comes in addition to the unwritable-directories warning: that one concerns this run, the owner mismatch every later write by the web server.

Definition at line 859 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

859 : void
860 {
861 if (!function_exists('posix_geteuid')) {
862 $this->markTestSkipped('The owner check needs the POSIX extension.');
863 }
864 $flushed = [];
865 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
866 $setup_language->method('findUnwritableOverlayDirectories')->willReturn(['/x/lang/components/pilot/lang']);
867 $setup_language->method('getClientDataDir')->willReturn('/');
868 // the owner-mismatch warning is only given when there is a migrated module's overlay to protect
869 $setup_language->method('hasMigratedModules')->willReturn(true);
870 $messages = [];
871
872 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
873
874 $this->assertCount(2, $messages);
875 $this->assertStringContainsString('/x/lang/components/pilot/lang', $messages[0]);
876 $this->assertStringStartsWith('WARNING: Setup runs as user id ' . posix_geteuid() . ',', $messages[1]);
877 $this->assertStringContainsString('chown -R ', $messages[1]);
878 }

◆ testTheWritabilityCheckOnlyCoversTheLanguagesThatAreActuallyWritten()

ilLanguagesInstalledAndUpdatedObjectiveTest::testTheWritabilityCheckOnlyCoversTheLanguagesThatAreActuallyWritten ( )

Invalid languages are skipped before the check.

Definition at line 456 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

456 : void
457 {
458 $flushed = [];
459 $checked = [];
460 $setup_language = $this->createAchievableSetupLanguage(['de', 'xx'], ['xx'], $flushed);
461 $setup_language->method('findUnwritableOverlayDirectories')->willReturnCallback(
462 static function (array $lang_keys) use (&$checked): array {
463 $checked[] = $lang_keys;
464 return [];
465 }
466 );
467 $messages = [];
468
469 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
470
471 $this->assertSame([['de']], $checked);
472 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

◆ testWarnsAboutAMissingClientDataDirectoryWhenMigratedModulesExist()

ilLanguagesInstalledAndUpdatedObjectiveTest::testWarnsAboutAMissingClientDataDirectoryWhenMigratedModulesExist ( )

Without a resolvable client data directory no PO/MO overlay can be written: worth a warning instead of silently serving the modules from the database, but only if such a module exists.

Definition at line 375 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

375 : void
376 {
377 $flushed = [];
378 $setup_language = $this->createAchievableSetupLanguage(['de'], [], $flushed);
379 $setup_language->method('getClientDataDir')->willReturn(null);
380 $setup_language->method('hasMigratedModules')->willReturn(true);
381 $messages = [];
382
383 (new ilLanguagesInstalledAndUpdatedObjective($setup_language))->achieve($this->informCollectingEnvironment($messages));
384
385 $this->assertCount(1, $messages);
386 $this->assertStringStartsWith('WARNING: The client data directory is not known', $messages[0]);
387 }

References createAchievableSetupLanguage(), and informCollectingEnvironment().

+ Here is the call graph for this function:

Field Documentation

◆ $had_global_db

bool ilLanguagesInstalledAndUpdatedObjectiveTest::$had_global_db
private

◆ $previous_global_db

mixed ilLanguagesInstalledAndUpdatedObjectiveTest::$previous_global_db = null
private

Definition at line 41 of file ilLanguagesInstalledAndUpdatedObjectiveTest.php.

Referenced by tearDown().


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