Compare commits

...

4 Commits

Author SHA1 Message Date
v-dumas
03fd49f688 N°9553 - Refactor methods to be clearer on what it does 2026-06-02 17:36:01 +02:00
v-dumas
b68df9ec07 N°9553 - fix typo 2026-06-01 12:47:24 +02:00
v-dumas
a8b8e2d81d N°9553 - take into account feedbacks from review 2026-06-01 12:39:26 +02:00
v-dumas
9443d87172 N°9553 - LoadLocalizedData: review feedbacks + improved tests 2026-06-01 12:34:18 +02:00
7 changed files with 156 additions and 129 deletions

View File

@@ -26,7 +26,6 @@ SetupWebPage::AddModule(
], ],
'data.struct' => [ 'data.struct' => [
'data/en_us.data.itop-brand.xml', 'data/en_us.data.itop-brand.xml',
'data/en_us.data.itop-networkdevicetype.xml',
'data/en_us.data.itop-osfamily.xml', 'data/en_us.data.itop-osfamily.xml',
'data/en_us.data.itop-osversion.xml', 'data/en_us.data.itop-osversion.xml',
], ],
@@ -102,6 +101,8 @@ if (!class_exists('ConfigMgmtInstaller')) {
*/ */
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{ {
// load localized data for NetworkDeviceType
static::LoadLocalizedDataOnCrossingVersion($oConfiguration, $sPreviousVersion, $sCurrentVersion,'3.3.0',__DIR__."/data/{{language_code}}.data.itop-networkdevicetype.xml" );
} }
} }
} }

View File

@@ -88,13 +88,7 @@ if (!class_exists('ServiceMgmtProviderInstaller')) {
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{ {
// Load localized structural data: contract types // Load localized structural data: contract types
static::LoadLocalizedData( static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-contracttype.xml");
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-contracttype.xml"
);
} }
} }
} }

View File

@@ -85,13 +85,7 @@ if (!class_exists('ServiceMgmtInstaller')) {
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{ {
// Load localized structural data: contact types and document types // Load localized structural data: contact types and document types
static::LoadLocalizedData( static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-contracttype.xml");
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-contracttype.xml"
);
} }
} }
} }

View File

@@ -100,20 +100,8 @@ if (!class_exists('StructureInstaller')) {
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{ {
// Load localized structural data: contact types and document types // Load localized structural data: contact types and document types
static::LoadLocalizedData( static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-contacttype.xml");
$oConfiguration, static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-documenttype.xml");
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-contacttype.xml"
);
static::LoadLocalizedData(
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-documenttype.xml"
);
// Default language will be used for actions // Default language will be used for actions
// Note: There is a issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk // Note: There is a issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk

View File

@@ -61,6 +61,6 @@ class TicketsInstaller extends ModuleInstallerAPI
} }
} }
// Load localized structural data: predefined query phrases for notifications // Load localized structural data: predefined query phrases for notifications
static::LoadLocalizedData($oConfiguration, $sPreviousVersion, $sCurrentVersion, '3.0.0', __DIR__."/data/{{language_code}}.data.itop-tickets.xml"); static::LoadLocalizedDataOnCrossingVersion($oConfiguration, $sPreviousVersion, $sCurrentVersion, '3.0.0', __DIR__."/data/{{language_code}}.data.itop-tickets.xml");
} }
} }

View File

@@ -311,7 +311,7 @@ abstract class ModuleInstallerAPI
/** /**
* @param \Config $oConfiguration * @param \Config $oConfiguration
* @param string $sPreviousVersion The previous version of the module (empty string will force the loading) * @param string $sPreviousVersion The previous version of the module (empty string in case of first install)
* @param string $sCurrentVersion The current version of the module * @param string $sCurrentVersion The current version of the module
* @param string $sFirstLoadingVersion The first module version for which the data loading should be performed (e.g. '3.0.0') * @param string $sFirstLoadingVersion The first module version for which the data loading should be performed (e.g. '3.0.0')
* @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml') * @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
@@ -321,74 +321,51 @@ abstract class ModuleInstallerAPI
* @throws \CoreException * @throws \CoreException
* @throws \CoreUnexpectedValue * @throws \CoreUnexpectedValue
*/ */
public static function LoadLocalizedData(Config $oConfiguration, string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void public static function LoadLocalizedDataOnCrossingVersion(Config $oConfiguration, ?string $sPreviousVersion, ?string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
{ {
self::AssertLoadLocalizedDataParametersAreValid($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sFilePattern); self::AssertLoadLocalizedDataParametersAreValid($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion);
// It's not very clear if it makes sense to test a particular version, // The loading is done only if
// as the loading mechanism checks object existence using reconc_keys // - it's a first install of the module
// and do not recreate them, nor update existing. // - or it's an upgrade of that module (PreviousVersion is less than the CurrentVersion), which means that we are really upgrading (and not reinstalling the same version or downgrading), and
// Without test, new entries added to the data files, would be automatically loaded // - either the FirstLoadingVersion is between the PreviousVersion and the CurrentVersion
// - or the FirstLoadingVersion is empty, forcing the loading on all upgrades,
if (($sPreviousVersion === '') || if (($sPreviousVersion === '') ||
(version_compare($sPreviousVersion, $sCurrentVersion, '<') (version_compare($sPreviousVersion, $sCurrentVersion, '<')
&& version_compare($sPreviousVersion, $sFirstLoadingVersion, '<'))) { && version_compare($sPreviousVersion, $sFirstLoadingVersion, '<')
&& version_compare($sFirstLoadingVersion, $sCurrentVersion, '<='))) {
// Note: There is an issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk self::LoadLocalizedData($oConfiguration, $sFilePattern);
if (utils::IsNullOrEmptyString($sPreviousVersion)) { }
// Fresh install }
$sDefaultLanguage = $oConfiguration->GetDefaultLanguage(); /**
} else { * @param \Config $oConfiguration
// Upgrade * @param string $sPreviousVersion The previous version of the module (empty string in case of first install)
$sDefaultLanguage = utils::GetConfig(true)->GetDefaultLanguage(); * @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
} *
* @return void
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sFilePattern); */
if ($sFileName !== '') { public static function LoadLocalizedDataOnNewInstall(Config $oConfiguration, ?string $sPreviousVersion, string $sFilePattern): void
self::XMLFileLoad($sFileName); {
} if (utils::IsNullOrEmptyString($sPreviousVersion)) {
self::LoadLocalizedData($oConfiguration, $sFilePattern);
} }
} }
/** /**
* @throws \CoreUnexpectedValue * @param \Config $oConfiguration
*/ * @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
private static function AssertLoadLocalizedDataParametersAreValid(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
{
if (($sPreviousVersion !== '') && !self::IsValidLocalizedDataVersion($sPreviousVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sPreviousVersion to be empty or match x.y[.z][-name], got '{$sPreviousVersion}'");
}
if (!self::IsValidLocalizedDataVersion($sCurrentVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sCurrentVersion to match x.y[.z][-name], got '{$sCurrentVersion}'");
}
if (!self::IsValidLocalizedDataVersion($sFirstLoadingVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sFirstLoadingVersion to match x.y[.z][-name], got '{$sFirstLoadingVersion}'");
}
if (utils::IsNullOrEmptyString($sFilePattern)) {
throw new CoreUnexpectedValue('LoadLocalizedData expects sFilePattern to be a non-empty string');
}
if (substr_count($sFilePattern, '{{language_code}}') !== 1) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sFilePattern to contain the exact placeholder '{{language_code}}' exactly once");
}
}
private static function IsValidLocalizedDataVersion(string $sVersion): bool
{
return (preg_match('/^\d+\.\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)?$/', $sVersion) === 1);
}
/**
* @param array|string $sFileName
* @param \XMLDataLoader $oDataLoader
* *
* @return void * @return void
* @throws \Exception * @throws \Exception
*/ */
public static function XMLFileLoad(string $sFileName): void protected static function LoadLocalizedData(Config $oConfiguration, string $sFilePattern): void
{ {
if (substr_count($sFilePattern, '{{language_code}}') !== 1) {
throw new CoreUnexpectedValue("LoadLocalizedData expects $sFilePattern to contain the exact placeholder '{{language_code}}' exactly once");
}
$sDefaultLanguage = $oConfiguration->GetDefaultLanguage();
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sFilePattern);
if (!file_exists($sFileName)) { if (!file_exists($sFileName)) {
throw new Exception("File $sFileName not found"); throw new Exception("File $sFileName not found");
} }
@@ -401,19 +378,39 @@ abstract class ModuleInstallerAPI
$oDataLoader->EndSession(); $oDataLoader->EndSession();
} }
/**
* @throws \CoreUnexpectedValue
*/
private static function AssertLoadLocalizedDataParametersAreValid(?string $sPreviousVersion, ?string $sCurrentVersion, string $sFirstLoadingVersion): void
{
if (($sPreviousVersion !== '') && !self::IsValidLocalizedDataVersion($sPreviousVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sPreviousVersion to be empty or match x.y[.z][-name], got '{$sPreviousVersion}'");
}
if (!self::IsValidLocalizedDataVersion($sCurrentVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sCurrentVersion to match x.y[.z][-name], got '{$sCurrentVersion}'");
}
if (($sFirstLoadingVersion !== '') && !self::IsValidLocalizedDataVersion($sFirstLoadingVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sFirstLoadingVersion to match x.y[.z][-name], got '{$sFirstLoadingVersion}'");
}
}
private static function IsValidLocalizedDataVersion(string $sVersion): bool
{
return (preg_match('/^\d+\.\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)?$/', $sVersion) === 1);
}
/** /**
* @param string $sLanguage The language code to use for localization (e.g. 'EN US') * @param string $sLanguage The language code to use for localization (e.g. 'EN US')
* @param string $sFilePattern The full path+name of the file to localize, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml') * @param string $sFilePattern The full path+name of the file to localize, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
* *
* @return string The localized file name if found, or an empty string if not found * @return string The localized file name if found, or an empty string if not found
* @throws \ConfigException
* @throws \CoreException
*/ */
public static function GetLocalizedFileName($sLanguage, string $sFilePattern): string private static function GetLocalizedFileName($sLanguage, string $sFilePattern): string
{ {
$sLang = str_replace(' ', '_', strtolower($sLanguage)); $sLang = str_replace(' ', '_', strtolower($sLanguage));
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern); $sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
if (!file_exists($sFileName)) { if (!file_exists($sFileName)) {
SetupLog::Debug("No data file found matching the pattern $sFilePattern and language_code $sLang. Trying with 'en_us' as fallback.");
$sLang = 'en_us'; $sLang = 'en_us';
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern); $sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
} }

View File

@@ -285,61 +285,89 @@ SQL
} }
/** /**
* @covers \ModuleInstallerAPI::LoadLocalizedData * @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_RequiredLanguageProvider
*/ */
public function testLoadLocalizedData_LoadsOnFirstInstall(): void public function testLoadLocalizedData_LoadRequiredLanguageOnFirstInstall(string $sRequiredLanguage, array $aAvailableLanguages, array $aExpectedCountByLanguage): void
{ {
// Given // Given
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_FirstInstall_', 'fr_fr'); [$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_RequiredLanguage_', $sRequiredLanguage, $aAvailableLanguages);
$this->GivenLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
$this->GivenLocalizedDataFile($sTmpDir, "fr_fr", $sOrgName);
// When no previous version, and current version higher than the first loading version // When no previous version, and current version higher than the first loading version
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', '3.3.0', '3.0.0', $sPattern); ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.3.0', '3.0.0', $sPattern);
// Then data loaded // Then data loaded
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0); foreach ($aExpectedCountByLanguage as $sLanguage => $iExpectedCount) {
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 1); $this->AssertOrganizationCountByName($sOrgName, $sLanguage, $iExpectedCount);
}
}
public function LoadLocalizedData_RequiredLanguageProvider(): array
{
return [
'Required fr_fr and file exists' => [
'required language' => 'fr_fr',
'available languages' => ['en_us', 'fr_fr'],
'expected counts' => ['en_us' => 0, 'fr_fr' => 1],
],
'Required en_us and file exists' => [
'required language' => 'en_us',
'available languages' => ['en_us', 'fr_fr'],
'expected counts' => ['en_us' => 1, 'fr_fr' => 0],
],
'Required fr_fr but fallback to en_us' => [
'required language' => 'fr_fr',
'available languages' => ['en_us'],
'expected counts' => ['en_us' => 1, 'fr_fr' => 0],
],
'Required de_de and file exists' => [
'required language' => 'de_de',
'available languages' => ['en_us', 'fr_fr', 'de_de'],
'expected counts' => ['en_us' => 0, 'fr_fr' => 0, 'de_de' => 1],
],
'Required de_de but fallback to en_us' => [
'required language' => 'de_de',
'available languages' => ['en_us', 'fr_fr'],
'expected counts' => ['en_us' => 1, 'fr_fr' => 0, 'de_de' => 0],
],
];
} }
/** /**
* @covers \ModuleInstallerAPI::LoadLocalizedData * @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_VersionConditionNotMetProvider
*/ */
public function testLoadLocalizedData_DoesNotLoadWhenVersionConditionIsNotMet(): void public function testLoadLocalizedData_DoesNotLoadWhenVersionConditionIsNotMet(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion): void
{ {
// Given // Given
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_NoLoad_', 'en_us'); [$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_NoLoad_', 'en_us', ['en_us']);
$this->GivenLocalizedDataFile($sTmpDir, "en_us", $sOrgName); // When version gate conditions are not met
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, $sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
// When a previous version that is lower than the first loading version, but higher or equal to the current version
ModuleInstallerAPI::LoadLocalizedData($oConfig, '3.0.0', '3.1.0', '3.0.0', $sPattern);
// Then no data loaded // Then no data loaded
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0); $this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
} }
/** public function LoadLocalizedData_VersionConditionNotMetProvider(): array
* @covers \ModuleInstallerAPI::LoadLocalizedData
*/
public function testLoadLocalizedData_FallbacksToEnUsWhenLanguageFileIsMissing(): void
{ {
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_Fallback_', 'fr_fr'); return [
// Intentionally create ONLY en_us file 'Equal versions (reinstall)' => ['3.1.0', '3.1.0', '3.0.0'],
$this->GivenLocalizedDataFile($sTmpDir, 'en_us', $sOrgName); 'Downgrade attempt' => ['3.2.0', '3.1.0', '3.0.0'],
// When loading localized data in fr_fr, but only en_us file exists 'Upgrade but first loading version already passed' => ['3.1.0', '3.2.0', '3.0.0'],
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', '3.3.0', '3.0.0', $sPattern); 'Upgrade with boundary equality on first loading version' => ['3.0.0', '3.1.0', '3.0.0'],
'Upgrade but first loading version empty' => ['3.1.0', '3.2.0', ''],
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 0); ];
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
} }
/** /**
* @covers \ModuleInstallerAPI::LoadLocalizedData * @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_ValidVersionFormatsProvider * @dataProvider LoadLocalizedData_ValidVersionFormatsProvider
*/ */
public function testLoadLocalizedData_AcceptsSupportedVersionFormats(string $sCurrentVersion, string $sFirstLoadingVersion): void public function testLoadLocalizedData_AcceptsSupportedVersionFormats(string $sCurrentVersion, string $sFirstLoadingVersion): void
{ {
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_ValidVersion_', 'en_us'); [$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_ValidVersion_', 'en_us', ['en_us']);
$this->GivenLocalizedDataFile($sTmpDir, 'en_us', $sOrgName);
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', $sCurrentVersion, $sFirstLoadingVersion, $sPattern); ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1); $this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
} }
@@ -348,11 +376,39 @@ SQL
{ {
return [ return [
'Current version with suffix' => ['3.2-dev', '3.0.0'], 'Current version with suffix' => ['3.2-dev', '3.0.0'],
'Current version x.y.z' => ['1.2.4', '1.0'], 'Current version x.y.z' => ['10.12.140-Tagada34', '1.0'],
'Current version x.y.z-suffix' => ['2.3.3-beta', '2.0.0'], 'Current version x.y.z-suffix' => ['2.3.3-beta', '2.3.3-alpha'],
'Current version x.y.z-1' => ['1.2.4-1', '1.0.3-2'], 'Current version x.y.z-1' => ['1.2.4-1', '1.0.3-2'],
]; ];
} }
// Test when a file is loaded twice because of the version conditions, it doesn't create duplicates (idempotent loading)
public function testLoadLocalizedData_IdempotentLoading(): void
{
// Given
[$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_Idempotent_', 'en_us', ['en_us']);
// When LoadLocalizedData is called twice with conditions that would load the file both times
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.1.0', '3.0.0', $sPattern);
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '3.1.0', '3.2.0', '', $sPattern);
// Then no duplicate data loaded
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
}
/**
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_InvalidParametersProvider
*/
public function testLoadLocalizedData_ThrowsOnInvalidParameters(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sPattern, string $sExpectedMessage): void
{
$oConfig = MetaModel::GetConfig();
$this->assertNotNull($oConfig);
$this->expectException(\CoreUnexpectedValue::class);
$this->expectExceptionMessage($sExpectedMessage);
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, $sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
}
public function LoadLocalizedData_InvalidParametersProvider(): array public function LoadLocalizedData_InvalidParametersProvider(): array
{ {
@@ -388,13 +444,6 @@ SQL
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{LANGUAGE_CODE}}.xml', 'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{LANGUAGE_CODE}}.xml',
'message' => "{{language_code}}", 'message' => "{{language_code}}",
], ],
'Parent directory does not exist' => [
'previous' => '',
'current' => '3.2.0',
'first' => '3.0.0',
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'missing'.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml',
'message' => 'parent directory',
],
]; ];
} }
@@ -403,7 +452,7 @@ SQL
* *
* @return array{0: Config, 1: string, 2: string, 3: string, 4: string} * @return array{0: Config, 1: string, 2: string, 3: string, 4: string}
*/ */
private function GivenLocalizedDataTestContext(string $sOrgNamePrefix, string $sLanguage): array private function GivenLocalizedDataTestContext(string $sOrgNamePrefix, string $sLanguage, array $aAvailableLanguages = []): array
{ {
$oConfig = MetaModel::GetConfig(); $oConfig = MetaModel::GetConfig();
$oConfig->SetDefaultLanguage($sLanguage); $oConfig->SetDefaultLanguage($sLanguage);
@@ -415,7 +464,11 @@ SQL
$this->aFileToClean[] = $sTmpDir; $this->aFileToClean[] = $sTmpDir;
$sPattern = $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml'; $sPattern = $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml';
return [$oConfig, $sOrgName, $sTmpDir, $sPattern]; foreach ($aAvailableLanguages as $sAvailableLanguage) {
$this->GivenLocalizedDataFile($sTmpDir, $sAvailableLanguage, $sOrgName);
}
return [$oConfig, $sOrgName, $sPattern];
} }
private function GivenLocalizedDataFile(string $sDir, string $sLang, string $sOrgName): string private function GivenLocalizedDataFile(string $sDir, string $sLang, string $sOrgName): string