New way to compile the dictionaries, allowing for incremental modification via XML

SVN:trunk[2712]
This commit is contained in:
Romain Quetiez
2013-04-30 16:14:37 +00:00
parent 7fcf922ee0
commit 21f0d96146
3 changed files with 184 additions and 13 deletions

View File

@@ -1570,10 +1570,6 @@ class Config
{
$aWebServiceCategories = array_unique(array_merge($aWebServiceCategories, $aModuleInfo['webservice']));
}
if (isset($aModuleInfo['dictionary']))
{
$aDictionaries = array_unique(array_merge($aDictionaries, $aModuleInfo['dictionary']));
}
if (isset($aModuleInfo['settings']))
{
list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
@@ -1609,6 +1605,17 @@ class Config
$this->SetAppModules($aAppModules);
$this->SetDataModels($aDataModels);
$this->SetWebServiceCategories($aWebServiceCategories);
// Scan dictionaries
//
if (!is_null($sModulesDir))
{
foreach(glob(APPROOT.$sModulesDir.'/dictionaries/*.dict.php') as $sFilePath)
{
$sFile = basename($sFilePath);
$aDictionaries[] = $sModulesDir.'/dictionaries/'.$sFile;
}
}
$this->SetDictionaries($aDictionaries);
}
}

View File

@@ -257,7 +257,21 @@ EOF;
{
$this->Log("Compilation of module $sModuleName in version $sModuleVersion produced not code at all. No file written.");
}
} // foreach module
// Compile the dictionaries -out of the modules
//
$sDictDir = $sTargetDir.'/dictionaries';
if (!is_dir($sDictDir))
{
$this->Log("Creating directory $sDictDir");
mkdir($sDictDir, 0777, true);
}
$oDictionaries = $this->oFactory->ListActiveChildNodes('dictionaries', 'dictionary');
foreach($oDictionaries as $oDictionaryNode)
{
$this->CompileDictionary($oDictionaryNode, $sTargetDir);
}
}
@@ -451,10 +465,18 @@ EOF;
/**
* Adds quotes and escape characters
*/
protected function QuoteForPHP($sStr)
protected function QuoteForPHP($sStr, $bSimpleQuotes = false)
{
$sEscaped = str_replace(array('\\', '"', "\n"), array('\\\\', '\\"', '\\n'), $sStr);
$sRet = '"'.$sEscaped.'"';
if ($bSimpleQuotes)
{
$sEscaped = str_replace(array('\\', "'"), array('\\\\', "\\'"), $sStr);
$sRet = "'$sEscaped'";
}
else
{
$sEscaped = str_replace(array('\\', '"', "\n"), array('\\\\', '\\"', '\\n'), $sStr);
$sRet = '"'.$sEscaped.'"';
}
return $sRet;
}
@@ -1408,8 +1430,38 @@ EOF;
return $sPHP;
} // function CompileUserRights
protected function CompileDictionary($oDictionaryNode, $sTargetDir)
{
$sLang = $oDictionaryNode->getAttribute('id');
$sEnglishLanguageDesc = $oDictionaryNode->GetChildText('english_description');
$sLocalizedLanguageDesc = $oDictionaryNode->GetChildText('localized_description');
$aEntriesPHP = array();
$oEntries = $oDictionaryNode->GetUniqueElement('entries');
foreach($oEntries->getElementsByTagName('entry') as $oEntry)
{
$sStringCode = $oEntry->getAttribute('id');
$sValue = $oEntry->GetText();
$aEntriesPHP[] = "\t'$sStringCode' => ".self::QuoteForPHP($sValue, true).",";
}
$sEntriesPHP = implode("\n", $aEntriesPHP);
$sEscEnglishLanguageDesc = self::QuoteForPHP($sEnglishLanguageDesc);
$sEscLocalizedLanguageDesc = self::QuoteForPHP($sLocalizedLanguageDesc);
$sPHPDict =
<<<EOF
<?php
//
// Dictionary built by the compiler for the language "$sLang"
//
Dict::Add('$sLang', $sEscEnglishLanguageDesc, $sEscLocalizedLanguageDesc, array(
$sEntriesPHP
));
EOF;
$sSafeLang = str_replace(' ', '-', strtolower(trim($sLang)));
$sDictFile = $sTargetDir.'/dictionaries/'.$sSafeLang.'.dict.php';
file_put_contents($sDictFile, $sPHPDict);
}
}
?>
?>

View File

@@ -111,6 +111,24 @@ class MFModule
{
return array();
}
public function GetDictionaryFiles()
{
$aDictionaries = array();
if ($hDir = opendir($this->sRootDir))
{
while (($sFile = readdir($hDir)) !== false)
{
$aMatches = array();
if (preg_match("/^[^\\.]+.dict.".$this->sName.".php$/i", $sFile, $aMatches)) // Dictionary files are named like <Lang>.dict.<ModuleName>.php
{
$aDictionaries[] = $this->sRootDir.'/'.$sFile;
}
}
closedir($hDir);
}
return $aDictionaries;
}
}
/**
@@ -125,15 +143,20 @@ class ModelFactory
protected $oModules;
protected $oClasses;
protected $oMenus;
protected $oDictionaries;
static protected $aLoadedClasses;
static protected $aWellKnownParents = array('DBObject', 'CMDBObject','cmdbAbstractObject');
// static protected $aWellKnownMenus = array('DataAdministration', 'Catalogs', 'ConfigManagement', 'Contact', 'ConfigManagementCI', 'ConfigManagement:Shortcuts', 'ServiceManagement');
static protected $aLoadedModules;
static protected $aLoadErrors;
protected $aDict;
protected $aDictKeys;
public function __construct($aRootDirs, $aRootNodeExtensions = array())
{
$this->aDict = array();
$this->aDictKeys = array();
$this->aRootDirs = $aRootDirs;
$this->oDOMDocument = new MFDocument();
$this->oRoot = $this->oDOMDocument->CreateElement('itop_design');
@@ -143,6 +166,9 @@ class ModelFactory
$this->oRoot->AppendChild($this->oModules);
$this->oClasses = $this->oDOMDocument->CreateElement('classes');
$this->oRoot->AppendChild($this->oClasses);
$this->oDictionaries = $this->oDOMDocument->CreateElement('dictionaries');
$this->oRoot->AppendChild($this->oDictionaries);
foreach (self::$aWellKnownParents as $sWellKnownParent)
{
$this->AddWellKnownParent($sWellKnownParent);
@@ -353,6 +379,65 @@ class ModelFactory
$oDeltaRoot = $oDocument->childNodes->item(0);
$this->LoadDelta($oDocument, $oDeltaRoot, $this->oDOMDocument);
}
$aDictionaries = $oModule->GetDictionaryFiles();
try
{
$this->ResetTempDictionary();
foreach($aDictionaries as $sPHPFile)
{
$sDictFileContents = file_get_contents($sPHPFile);
$sDictFileContents = str_replace(array('<'.'?'.'php', '?'.'>'), '', $sDictFileContents);
$sDictFileContents = str_replace('Dict::Add', '$this->AddToTempDictionary', $sDictFileContents);
eval($sDictFileContents);
}
foreach ($this->aDict as $sLanguageCode => $aDictDefinition)
{
$oNodes = $this->GetNodeById('dictionary', $sLanguageCode, $this->oDictionaries);
if ($oNodes->length == 0)
{
$oXmlDict = $this->oDOMDocument->CreateElement('dictionary');
$oXmlDict->setAttribute('id', $sLanguageCode);
$this->oDictionaries->AddChildNode($oXmlDict);
$oXmlEntries = $this->oDOMDocument->CreateElement('english_description', $aDictDefinition['english_description']);
$oXmlDict->AppendChild($oXmlEntries);
$oXmlEntries = $this->oDOMDocument->CreateElement('localized_description', $aDictDefinition['localized_description']);
$oXmlDict->AppendChild($oXmlEntries);
$oXmlEntries = $this->oDOMDocument->CreateElement('entries');
$oXmlDict->AppendChild($oXmlEntries);
}
else
{
$oXmlDict = $oNodes->item(0);
$oXmlEntries = $oXmlDict->GetUniqueElement('entries');
}
foreach ($aDictDefinition['entries'] as $sCode => $sLabel)
{
$oXmlEntry = $this->oDOMDocument->CreateElement('entry');
$oXmlEntry->setAttribute('id', $sCode);
$oXmlValue = $this->oDOMDocument->CreateCDATASection($sLabel);
$oXmlEntry->appendChild($oXmlValue);
if (array_key_exists($sLanguageCode, $this->aDictKeys) && array_key_exists($sCode, $this->aDictKeys[$sLanguageCode]))
{
$oXmlEntries->RedefineChildNode($oXmlEntry);
}
else
{
$oXmlEntries->appendChild($oXmlEntry);
}
$this->aDictKeys[$sLanguageCode][$sCode] = true;
}
}
}
catch(Exception $e)
{
throw new Exception('Failed to load dictionary file "'.$sPHPFile.'", reason: '.$e->getMessage());
}
}
catch(Exception $e)
{
@@ -365,6 +450,33 @@ class ModelFactory
}
}
/**
* Collects the PHP Dict entries into the ModelFactory for transforming the dictionary into an XML structure
* @param string $sLanguageCode The language code
* @param string $sEnglishLanguageDesc English description of the language (unused but kept for API compatibility)
* @param string $sLocalizedLanguageDesc Localized description of the language (unused but kept for API compatibility)
* @param hash $aEntries The entries to load: string_code => translation
*/
protected function AddToTempDictionary($sLanguageCode, $sEnglishLanguageDesc, $sLocalizedLanguageDesc, $aEntries)
{
$this->aDict[$sLanguageCode]['english_description'] = $sEnglishLanguageDesc;
$this->aDict[$sLanguageCode]['localized_description'] = $sLocalizedLanguageDesc;
if (!array_key_exists('entries', $this->aDict[$sLanguageCode]))
{
$this->aDict[$sLanguageCode]['entries'] = array();
}
foreach($aEntries as $sKey => $sValue)
{
$this->aDict[$sLanguageCode]['entries'][$sKey] = $sValue;
}
}
protected function ResetTempDictionary()
{
$this->aDict = array();
}
/**
* XML load errors (XML format and validation)
*/
@@ -568,7 +680,7 @@ class ModelFactory
public function GetClassXMLTemplate($sName, $sIcon)
{
$sHeader = '<?xml version="1.0" encoding="utf-8"?'.'>';
$sHeader = '<?'.'xml version="1.0" encoding="utf-8"?'.'>';
return
<<<EOF
$sHeader