mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-24 01:32:16 +02:00
Compare commits
2 Commits
develop
...
feature/95
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12083a909e | ||
|
|
2b9db73871 |
@@ -99,6 +99,22 @@ 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 contract types
|
||||||
|
static::LoadLocalizedData(
|
||||||
|
$sPreviousVersion,
|
||||||
|
$sCurrentVersion,
|
||||||
|
$oConfiguration,
|
||||||
|
'3.3.0',
|
||||||
|
dirname(__FILE__)."/data/{{language_code}}.data.itop-contacttype.xml"
|
||||||
|
);
|
||||||
|
static::LoadLocalizedData(
|
||||||
|
$sPreviousVersion,
|
||||||
|
$sCurrentVersion,
|
||||||
|
$oConfiguration,
|
||||||
|
'3.3.0',
|
||||||
|
dirname(__FILE__)."/data/{{language_code}}.data.itop-contracttype.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
|
||||||
if (utils::IsNullOrEmptyString($sPreviousVersion)) {
|
if (utils::IsNullOrEmptyString($sPreviousVersion)) {
|
||||||
|
|||||||
@@ -56,46 +56,13 @@ class TicketsInstaller extends ModuleInstallerAPI
|
|||||||
if (!MetaModel::IsValidClass($oTrigger->Get('target_class'))) {
|
if (!MetaModel::IsValidClass($oTrigger->Get('target_class'))) {
|
||||||
$oTrigger->DBDelete();
|
$oTrigger->DBDelete();
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
utils::EnrichRaisedException($oTrigger, $e);
|
utils::EnrichRaisedException($oTrigger, $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// It's not very clear if it make sense to test a particular version,
|
// Load localized structural data: predefined query phrases for notifications
|
||||||
// as the loading mechanism checks object existence using reconc_keys
|
static::LoadLocalizedData($sPreviousVersion, $sCurrentVersion, $oConfiguration, '3.0.0', dirname(__FILE__)."/data/{{language_code}}.data.itop-tickets.xml");
|
||||||
// and do not recreate them, nor update existing.
|
|
||||||
// Without test, new entries added to the data files, would be automatically loaded
|
|
||||||
if (($sPreviousVersion === '') ||
|
|
||||||
(version_compare($sPreviousVersion, $sCurrentVersion, '<')
|
|
||||||
&& version_compare($sPreviousVersion, '3.0.0', '<'))) {
|
|
||||||
$oDataLoader = new XMLDataLoader();
|
|
||||||
|
|
||||||
CMDBObject::SetTrackInfo("Initialization TicketsInstaller");
|
|
||||||
$oMyChange = CMDBObject::GetCurrentChange();
|
|
||||||
|
|
||||||
$sLang = null;
|
|
||||||
// - Try to get app. language from configuration fil (app. upgrade)
|
|
||||||
$sConfigFileName = APPCONF.'production/'.ITOP_CONFIG_FILE;
|
|
||||||
if (file_exists($sConfigFileName)) {
|
|
||||||
$oFileConfig = new Config($sConfigFileName);
|
|
||||||
if (is_object($oFileConfig)) {
|
|
||||||
$sLang = str_replace(' ', '_', strtolower($oFileConfig->GetDefaultLanguage()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - I still no language, get the default one
|
|
||||||
if (null === $sLang) {
|
|
||||||
$sLang = str_replace(' ', '_', strtolower($oConfiguration->GetDefaultLanguage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
$sFileName = dirname(__FILE__)."/data/{$sLang}.data.itop-tickets.xml";
|
|
||||||
SetupLog::Info("Searching file: $sFileName");
|
|
||||||
if (!file_exists($sFileName)) {
|
|
||||||
$sFileName = dirname(__FILE__)."/data/en_us.data.itop-tickets.xml";
|
|
||||||
}
|
|
||||||
SetupLog::Info("Loading file: $sFileName");
|
|
||||||
$oDataLoader->StartSession($oMyChange);
|
|
||||||
$oDataLoader->LoadFile($sFileName, false, true);
|
|
||||||
$oDataLoader->EndSession();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -309,4 +309,86 @@ abstract class ModuleInstallerAPI
|
|||||||
|
|
||||||
CMDBSource::CacheReset($sOrigTable);
|
CMDBSource::CacheReset($sOrigTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPreviousVersion The previous version of the module (empty string will force the loading)
|
||||||
|
* @param string $sCurrentVersion The current version of the module
|
||||||
|
* @param \Config $oConfiguration
|
||||||
|
* @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')
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \ConfigException
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
|
public static function LoadLocalizedData(string $sPreviousVersion, string $sCurrentVersion, Config $oConfiguration, string $sFirstLoadingVersion, string $sFilePattern): void
|
||||||
|
{
|
||||||
|
// It's not very clear if it makes sense to test a particular version,
|
||||||
|
// as the loading mechanism checks object existence using reconc_keys
|
||||||
|
// and do not recreate them, nor update existing.
|
||||||
|
// Without test, new entries added to the data files, would be automatically loaded
|
||||||
|
if (($sPreviousVersion === '') ||
|
||||||
|
(version_compare($sPreviousVersion, $sCurrentVersion, '<')
|
||||||
|
&& version_compare($sPreviousVersion, $sFirstLoadingVersion, '<'))) {
|
||||||
|
|
||||||
|
// Note: There is an issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk
|
||||||
|
if (utils::IsNullOrEmptyString($sPreviousVersion)) {
|
||||||
|
// Fresh install
|
||||||
|
$sDefaultLanguage = $oConfiguration->GetDefaultLanguage();
|
||||||
|
} else {
|
||||||
|
// Upgrade
|
||||||
|
$sDefaultLanguage = utils::GetConfig(true)->GetDefaultLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sFilePattern);
|
||||||
|
if ($sFileName !== '') {
|
||||||
|
SetupLog::Info("Loading file: $sFileName");
|
||||||
|
self::XMLFileLoad($sFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array|string $sFileName
|
||||||
|
* @param \XMLDataLoader $oDataLoader
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function XMLFileLoad(string $sFileName): void
|
||||||
|
{
|
||||||
|
if (file_exists($sFileName)) {
|
||||||
|
$oDataLoader = new XMLDataLoader();
|
||||||
|
CMDBObject::SetTrackInfo("Loading XML data from $sFileName");
|
||||||
|
$oMyChange = CMDBObject::GetCurrentChange();
|
||||||
|
SetupLog::Info("Loading file: $sFileName");
|
||||||
|
$oDataLoader->StartSession($oMyChange);
|
||||||
|
$oDataLoader->LoadFile($sFileName, false, true);
|
||||||
|
$oDataLoader->EndSession();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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')
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
{
|
||||||
|
$sLang = str_replace(' ', '_', strtolower($sLanguage));
|
||||||
|
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
|
||||||
|
if (!file_exists($sFileName)) {
|
||||||
|
$sLang = 'en_us';
|
||||||
|
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
|
||||||
|
}
|
||||||
|
if (file_exists($sFileName)) {
|
||||||
|
return $sFileName;
|
||||||
|
} else {
|
||||||
|
SetupLog::Warning("No data file matching the pattern $sFilePattern and language_code $sLang was found.");
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ namespace Combodo\iTop\Test\UnitTest\Setup;
|
|||||||
|
|
||||||
use CMDBSource;
|
use CMDBSource;
|
||||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||||
|
use Config;
|
||||||
use MetaModel;
|
use MetaModel;
|
||||||
use ModuleInstallerAPI;
|
use ModuleInstallerAPI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ModuleInstallerAPITest
|
* Class ModuleInstallerAPI
|
||||||
*
|
*
|
||||||
* @covers ModuleInstallerAPI
|
* @covers ModuleInstallerAPI
|
||||||
*
|
*
|
||||||
@@ -282,4 +283,105 @@ SQL
|
|||||||
|
|
||||||
$this->assertEquals($sOrigValue, $sDstValue, "Data was not moved as expected");
|
$this->assertEquals($sOrigValue, $sDstValue, "Data was not moved as expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||||
|
*/
|
||||||
|
public function testLoadLocalizedData_LoadsOnFirstInstall(): void
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->PrepareLocalizedDataTestContext('XML_Load_FirstInstall_', 'fr_fr');
|
||||||
|
$this->CreateLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
|
||||||
|
$this->CreateLocalizedDataFile($sTmpDir, "fr_fr", $sOrgName);
|
||||||
|
// When no previous version, and current version higher than the first loading version
|
||||||
|
ModuleInstallerAPI::LoadLocalizedData('', '3.3.0', $oConfig, '3.0.0', $sPattern);
|
||||||
|
// Then data loaded
|
||||||
|
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
|
||||||
|
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||||
|
*/
|
||||||
|
public function testLoadLocalizedData_DoesNotLoadWhenVersionConditionIsNotMet(): void
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->PrepareLocalizedDataTestContext('XML_Load_NoLoad_', 'en_us');
|
||||||
|
$this->CreateLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
|
||||||
|
|
||||||
|
// When a previous version that is lower than the first loading version, but higher or equal to the current version
|
||||||
|
ModuleInstallerAPI::LoadLocalizedData('3.0.0', '3.1.0', $oConfig, '3.0.0', $sPattern);
|
||||||
|
// Then no data loaded
|
||||||
|
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||||
|
*/
|
||||||
|
public function testLoadLocalizedData_FallbacksToEnUsWhenLanguageFileIsMissing(): void
|
||||||
|
{
|
||||||
|
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->PrepareLocalizedDataTestContext('XML_Load_Fallback_', 'fr_fr');
|
||||||
|
// Intentionally create ONLY en_us file
|
||||||
|
$this->CreateLocalizedDataFile($sTmpDir, 'en_us', $sOrgName);
|
||||||
|
// When loading localized data in fr_fr, but only en_us file exists
|
||||||
|
ModuleInstallerAPI::LoadLocalizedData('', '3.3.0', $oConfig, '3.0.0', $sPattern);
|
||||||
|
|
||||||
|
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 0);
|
||||||
|
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare common context for LoadLocalizedData tests.
|
||||||
|
*
|
||||||
|
* @return array{0: Config, 1: string, 2: string, 3: string, 4: string}
|
||||||
|
*/
|
||||||
|
private function PrepareLocalizedDataTestContext(string $sOrgNamePrefix, string $sLanguage): array
|
||||||
|
{
|
||||||
|
$oConfig = MetaModel::GetConfig();
|
||||||
|
$oConfig->SetDefaultLanguage($sLanguage);
|
||||||
|
$this->assertNotNull($oConfig);
|
||||||
|
|
||||||
|
$sOrgName = $sOrgNamePrefix.uniqid();
|
||||||
|
|
||||||
|
$sTmpDir = static::CreateTmpdir();
|
||||||
|
$this->aFileToClean[] = $sTmpDir;
|
||||||
|
$sPattern = $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml';
|
||||||
|
|
||||||
|
return [$oConfig, $sOrgName, $sTmpDir, $sPattern];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function CreateLocalizedDataFile(string $sDir, string $sLang, string $sOrgName): string
|
||||||
|
{
|
||||||
|
$sFilePath = $sDir.DIRECTORY_SEPARATOR.'data.'.$sLang.'.xml';
|
||||||
|
file_put_contents($sFilePath, $this->BuildOrganizationXml($sOrgName, $sLang));
|
||||||
|
|
||||||
|
return $sFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function BuildOrganizationXml(string $sOrgName, string $sLang): string
|
||||||
|
{
|
||||||
|
$iId = random_int(100000, 999999);
|
||||||
|
$sOrgNameXml = htmlspecialchars($sOrgName, ENT_XML1);
|
||||||
|
|
||||||
|
return <<<XML
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Set>
|
||||||
|
<Organization alias="Organization" id="{$iId}">
|
||||||
|
<name>{$sOrgNameXml}</name>
|
||||||
|
<code>{$sLang}</code>
|
||||||
|
<status>active</status>
|
||||||
|
</Organization>
|
||||||
|
</Set>
|
||||||
|
XML;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function AssertOrganizationCountByName(string $sOrgName, string $sLanguage, int $iExpectedCount): void
|
||||||
|
{
|
||||||
|
$sOrgTable = MetaModel::DBGetTable('Organization');
|
||||||
|
$iCount = (int) CMDBSource::QueryToScalar(
|
||||||
|
"SELECT COUNT(*) FROM `{$sOrgTable}` WHERE `name` = ".CMDBSource::Quote($sOrgName)." AND `code` = ".CMDBSource::Quote($sLanguage)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($iExpectedCount, $iCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user