node. There are * two more nodes PHRASES and EVENTS for phrase and email event translations. * * v2 * ========== * All data, that will end up in Language table is now attributes of LANGUAGE node * and is name exactly as field name, that will be used to store that data. * * v4 * ========== * Hint & Column translation added to each phrase translation */ defined('FULL_PATH') or die('restricted access!'); define('LANG_OVERWRITE_EXISTING', 1); define('LANG_SKIP_EXISTING', 2); class LanguageImportHelper extends kHelper { /** * Current Language in import * * @var LanguagesItem */ var $lang_object = null; /** * Current user's IP address * * @var string */ var $ip_address = ''; /** * Event type + name mapping to id (from system) * * @var Array */ var $events_hash = Array (); /** * Language pack import mode * * @var int */ var $import_mode = LANG_SKIP_EXISTING; /** * Language IDs, that were imported * * @var Array */ var $_languages = Array (); /** * Temporary table names to perform import on * * @var Array */ var $_tables = Array (); /** * Phrase types allowed for import/export operations * * @var Array */ var $phrase_types_allowed = Array (); /** * Encoding, used for language pack exporting * * @var string */ var $_exportEncoding = 'base64'; /** * Exported data limits (all or only specified ones) * * @var Array */ var $_exportLimits = Array ( 'phrases' => false, 'emailevents' => false, ); /** * Debug language pack import process * * @var bool */ var $_debugMode = false; /** * Latest version of language pack format. Versions are not backwards compatible! * * @var int */ var $_latestVersion = 4; /** * Prefix-based serial numbers, that should be changed after import is finished * * @var Array */ var $changedPrefixes = Array (); public function __construct() { parent::__construct(); // "core/install/english.lang", phrase count: 3318, xml parse time on windows: 10s, insert time: 0.058s set_time_limit(0); ini_set('memory_limit', -1); $this->lang_object =& $this->Application->recallObject('lang.import', null, Array ('skip_autoload' => true)); if (!(defined('IS_INSTALL') && IS_INSTALL)) { // perform only, when not in installation mode $this->_updateEventsCache(); } $this->ip_address = getenv('HTTP_X_FORWARDED_FOR') ? getenv('HTTP_X_FORWARDED_FOR') : getenv('REMOTE_ADDR'); // $this->_debugMode = $this->Application->isDebugMode(); } /** * Performs import of given language pack (former Parse method) * * @param string $filename * @param string $phrase_types * @param Array $module_ids * @param int $import_mode * @return bool */ function performImport($filename, $phrase_types, $module_ids, $import_mode = LANG_SKIP_EXISTING) { // define the XML parsing routines/functions to call based on the handler path if (!file_exists($filename) || !$phrase_types /*|| !$module_ids*/) { return false; } if ($this->_debugMode) { $start_time = microtime(true); $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '")'); } if (defined('IS_INSTALL') && IS_INSTALL) { // new events could be added during module upgrade $this->_updateEventsCache(); } $this->_initImportTables(); $phrase_types = explode('|', substr($phrase_types, 1, -1) ); // $module_ids = explode('|', substr($module_ids, 1, -1) ); $this->phrase_types_allowed = array_flip($phrase_types); $this->import_mode = $import_mode; $this->_parseXML($filename); // copy data from temp tables to live foreach ($this->_languages as $language_id) { $this->_performUpgrade($language_id, 'phrases', 'PhraseKey', Array ('l%s_Translation', 'l%s_HintTranslation', 'l%s_ColumnTranslation', 'PhraseType')); $this->_performUpgrade($language_id, 'emailevents', 'EventId', Array ('l%s_Subject', 'Headers', 'MessageType', 'l%s_Body')); $this->_performUpgrade($language_id, 'country-state', 'CountryStateId', Array ('l%s_Name')); } $this->_initImportTables(true); $this->changedPrefixes = array_unique($this->changedPrefixes); foreach ($this->changedPrefixes as $prefix) { $this->Application->incrementCacheSerial($prefix); } if ($this->_debugMode) { $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '"): ' . (microtime(true) - $start_time)); } return true; } /** * Creates XML file with exported language data (former Create method) * * @param string $filename filename to export into * @param Array $phrase_types phrases types to export from modules passed in $module_ids * @param Array $language_ids IDs of languages to export * @param Array $module_ids IDs of modules to export phrases from */ function performExport($filename, $phrase_types, $language_ids, $module_ids) { $fp = fopen($filename,'w'); if (!$fp || !$phrase_types || !$module_ids || !$language_ids) { return false; } $phrase_types = explode('|', substr($phrase_types, 1, -1) ); $module_ids = explode('|', substr($module_ids, 1, -1) ); $ret = '' . "\n"; $export_fields = $this->_getExportFields(); $email_message_helper =& $this->Application->recallObject('EmailMessageHelper'); /* @var $email_message_helper EmailMessageHelper */ // get languages $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('lang','TableName') . ' WHERE LanguageId IN (' . implode(',', $language_ids) . ')'; $languages = $this->Conn->Query($sql, 'LanguageId'); // get phrases $phrase_modules = $module_ids; array_push($phrase_modules, ''); // for old language packs without module $phrase_modules = array_map(Array (&$this->Conn, 'qstr'), $phrase_modules); // apply phrase selection limit if ($this->_exportLimits['phrases']) { $escaped_phrases = array_map(Array (&$this->Conn, 'qstr'), $this->_exportLimits['phrases']); $limit_where = 'Phrase IN (' . implode(',', $escaped_phrases) . ')'; } else { $limit_where = 'TRUE'; } $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('phrases','TableName') . ' WHERE PhraseType IN (' . implode(',', $phrase_types) . ') AND Module IN (' . implode(',', $phrase_modules) . ') AND ' . $limit_where . ' ORDER BY Phrase'; $phrases = $this->Conn->Query($sql, 'PhraseId'); // email events $module_sql = preg_replace('/(.*),/U', 'INSTR(Module,\'\\1\') OR ', implode(',', $module_ids) . ','); // apply event selection limit if ($this->_exportLimits['emailevents']) { $escaped_email_events = array_map(Array (&$this->Conn, 'qstr'), $this->_exportLimits['emailevents']); $limit_where = '`Event` IN (' . implode(',', $escaped_email_events) . ')'; } else { $limit_where = 'TRUE'; } $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('emailevents', 'TableName') . ' WHERE `Type` IN (' . implode(',', $phrase_types) . ') AND (' . substr($module_sql, 0, -4) . ') AND ' . $limit_where . ' ORDER BY `Event`, `Type`'; $events = $this->Conn->Query($sql, 'EventId'); if (in_array('Core', $module_ids)) { // countries $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('country-state', 'TableName') . ' WHERE Type = ' . DESTINATION_TYPE_COUNTRY . ' ORDER BY `IsoCode`'; $countries = $this->Conn->Query($sql, 'CountryStateId'); // states $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('country-state', 'TableName') . ' WHERE Type = ' . DESTINATION_TYPE_STATE . ' ORDER BY `IsoCode`'; $states = $this->Conn->Query($sql, 'CountryStateId'); foreach ($states as $state_id => $state_data) { $country_id = $state_data['StateCountryId']; if (!array_key_exists('States', $countries[$country_id])) { $countries[$country_id]['States'] = Array (); } $countries[$country_id]['States'][] = $state_id; } } foreach ($languages as $language_id => $language_info) { // language $ret .= "\t" . ''; $ret .= $this->_exportEncoding == 'base64' ? base64_encode($replacements) : ''; $ret .= '' . "\n"; } // phrases if ($phrases) { $ret .= "\t\t" . '' . "\n"; foreach ($phrases as $phrase_id => $phrase) { $translation = $phrase['l' . $language_id . '_Translation']; $hint_translation = $phrase['l' . $language_id . '_HintTranslation']; $column_translation = $phrase['l' . $language_id . '_ColumnTranslation']; if (!$translation) { // phrase is not translated on given language continue; } if ( $this->_exportEncoding == 'base64' ) { $data = base64_encode($translation); $hint_translation = base64_encode($hint_translation); $column_translation = base64_encode($column_translation); } else { $data = ''; $hint_translation = htmlspecialchars($hint_translation); $column_translation = htmlspecialchars($column_translation); } $attributes = Array ( 'Label="' . $phrase['Phrase'] . '"', 'Module="' . $phrase['Module'] . '"', 'Type="' . $phrase['PhraseType'] . '"' ); if ( $phrase['l' . $language_id . '_HintTranslation'] ) { $attributes[] = 'Hint="' . $hint_translation . '"'; } if ( $phrase['l' . $language_id . '_ColumnTranslation'] ) { $attributes[] = 'Column="' . $column_translation . '"'; } $ret .= "\t\t\t" . '' . $data . '' . "\n"; } $ret .= "\t\t" . '' . "\n"; } // email events if ($events) { $ret .= "\t\t" . '' . "\n"; foreach ($events as $event_id => $event) { $fields_hash = Array ( 'Headers' => $event['Headers'], 'Subject' => $event['l' . $language_id . '_Subject'], 'Body' => $event['l' . $language_id . '_Body'], ); $template = $email_message_helper->buildTemplate($fields_hash); if (!$template) { // email event is not translated on given language continue; } $data = $this->_exportEncoding == 'base64' ? base64_encode($template) : ''; $ret .= "\t\t\t" . '' . $data . ''."\n"; } $ret .= "\t\t" . '' . "\n"; } if (in_array('Core', $module_ids) && $countries) { $ret .= "\t\t" . '' . "\n"; foreach ($countries as $country_id => $country_data) { $translation = $country_data['l' . $language_id . '_Name']; if (!$translation) { // country is not translated on given language continue; } $data = $this->_exportEncoding == 'base64' ? base64_encode($translation) : $translation; if (array_key_exists('States', $country_data)) { $ret .= "\t\t\t" . '' . "\n"; foreach ($country_data['States'] as $state_id) { $translation = $states[$state_id]['l' . $language_id . '_Name']; if (!$translation) { // state is not translated on given language continue; } $data = $this->_exportEncoding == 'base64' ? base64_encode($translation) : $translation; $ret .= "\t\t\t\t" . '' . "\n"; } $ret .= "\t\t\t" . '' . "\n"; } else { $ret .= "\t\t\t" . '' . "\n"; } } $ret .= "\t\t" . '' . "\n"; } $ret .= "\t" . '' . "\n"; } $ret .= ''; fwrite($fp, $ret); fclose($fp); return true; } /** * Sets language pack encoding (not charset) used during export * * @param string $encoding */ function setExportEncoding($encoding) { $this->_exportEncoding = $encoding; } /** * Sets language pack data limits for export * * @param mixed $phrases * @param mixed $email_events */ function setExportLimits($phrases, $email_events) { if (!is_array($phrases)) { $phrases = str_replace(',', "\n", $phrases); $phrases = preg_replace("/\n+/", "\n", str_replace("\r", '', trim($phrases))); $phrases = $phrases ? array_map('trim', explode("\n", $phrases)) : Array (); } if (!is_array($email_events)) { $email_events = str_replace(',', "\n", $email_events); $email_events = preg_replace("/\n+/", "\n", str_replace("\r", '', trim($email_events))); $email_events = $email_events ? array_map('trim', explode("\n", $email_events)) : Array (); } $this->_exportLimits = Array ('phrases' => $phrases, 'emailevents' => $email_events); } /** * Performs upgrade of given language pack part * * @param int $language_id * @param string $prefix * @param string $unique_field * @param Array $data_fields */ function _performUpgrade($language_id, $prefix, $unique_field, $data_fields) { $live_records = $this->_getTableData($language_id, $prefix, $unique_field, $data_fields[0], false); $temp_records = $this->_getTableData($language_id, $prefix, $unique_field, $data_fields[0], true); if (!$temp_records) { // no data for given language return ; } // perform insert for records, that are missing in live table $to_insert = array_diff($temp_records, $live_records); if ($to_insert) { $to_insert = array_map(Array (&$this->Conn, 'qstr'), $to_insert); $sql = 'INSERT INTO ' . $this->Application->getUnitOption($prefix, 'TableName') . ' SELECT * FROM ' . $this->_tables[$prefix] . ' WHERE ' . $unique_field . ' IN (' . implode(',', $to_insert) . ')'; $this->Conn->Query($sql); // new records were added $this->changedPrefixes[] = $prefix; } // perform update for records, that are present in live table $to_update = array_diff($temp_records, $to_insert); if ($to_update) { $to_update = array_map(Array (&$this->Conn, 'qstr'), $to_update); $sql = 'UPDATE ' . $this->Application->getUnitOption($prefix, 'TableName') . ' live SET '; foreach ($data_fields as $index => $data_field) { $data_field = sprintf($data_field, $language_id); $sql .= ' live.' . $data_field . ' = ( SELECT temp' . $index . '.' . $data_field . ' FROM ' . $this->_tables[$prefix] . ' temp' . $index . ' WHERE temp' . $index . '.' . $unique_field . ' = live.' . $unique_field . ' ),'; } $sql = substr($sql, 0, -1); // cut last comma $where_clause = Array ( // this won't make any difference, but just in case $unique_field . ' IN (' . implode(',', $to_update) . ')', ); if ($this->import_mode == LANG_SKIP_EXISTING) { // empty OR not set $data_field = sprintf($data_fields[0], $language_id); $where_clause[] = '(' . $data_field . ' = "") OR (' . $data_field . ' IS NULL)'; } if ($where_clause) { $sql .= "\n" . 'WHERE (' . implode(') AND (', $where_clause) . ')'; } $this->Conn->Query($sql); if ($this->Conn->getAffectedRows() > 0) { // existing records were updated $this->changedPrefixes[] = $prefix; } } } /** * Returns data from given table used for language pack upgrade * * @param int $language_id * @param string $prefix * @param string $unique_field * @param string $data_field * @param bool $temp_mode * @return Array */ function _getTableData($language_id, $prefix, $unique_field, $data_field, $temp_mode = false) { $data_field = sprintf($data_field, $language_id); $table_name = $this->Application->getUnitOption($prefix, 'TableName'); if ($temp_mode) { // for temp table get only records, that have contents on given language (not empty and isset) $sql = 'SELECT ' . $unique_field . ' FROM ' . $this->Application->GetTempName($table_name, 'prefix:' . $prefix) . ' WHERE (' . $data_field . ' <> "") AND (' . $data_field . ' IS NOT NULL)'; } else { // for live table get all records, no matter on what language $sql = 'SELECT ' . $unique_field . ' FROM ' . $table_name; } return $this->Conn->GetCol($sql); } function _parseXML($filename) { if ($this->_debugMode) { $start_time = microtime(true); $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '")'); } $fdata = file_get_contents($filename); $xml_parser =& $this->Application->recallObject('kXMLHelper'); /* @var $xml_parser kXMLHelper */ $root_node =& $xml_parser->Parse($fdata); if (!is_object($root_node) || !is_a($root_node, 'kXMLNode')) { // invalid language pack contents return false; } if ($root_node->Children) { $this->_processLanguages($root_node->firstChild); } if ($this->_debugMode) { $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '"): ' . (microtime(true) - $start_time)); } return true; } /** * Creates temporary tables, used during language import * * @param bool $drop_only */ function _initImportTables($drop_only = false) { $this->_tables['phrases'] = $this->_prepareTempTable('phrases', $drop_only); $this->_tables['emailevents'] = $this->_prepareTempTable('emailevents', $drop_only); $this->_tables['country-state'] = $this->_prepareTempTable('country-state', $drop_only); } /** * Create temp table for prefix, if table already exists, then delete it and create again * * @param string $prefix * @param bool $drop_only * @return string Name of created temp table * @access protected */ protected function _prepareTempTable($prefix, $drop_only = false) { $id_field = $this->Application->getUnitOption($prefix, 'IDField'); $table = $this->Application->getUnitOption($prefix,'TableName'); $temp_table = $this->Application->GetTempName($table); $sql = 'DROP TABLE IF EXISTS %s'; $this->Conn->Query( sprintf($sql, $temp_table) ); if (!$drop_only) { $sql = 'CREATE TABLE ' . $temp_table . ' SELECT * FROM ' . $table . ' WHERE 0'; $this->Conn->Query($sql); $sql = 'ALTER TABLE %1$s CHANGE %2$s %2$s INT(11) NOT NULL DEFAULT "0"'; $this->Conn->Query( sprintf($sql, $temp_table, $id_field) ); switch ($prefix) { case 'phrases': $unique_field = 'PhraseKey'; break; case 'emailevents': $unique_field = 'EventId'; break; case 'country-state': $unique_field = 'CountryStateId'; break; default: throw new Exception('Unknown prefix "' . $prefix . '" during language pack import'); break; } $sql = 'ALTER TABLE ' . $temp_table . ' ADD UNIQUE (' . $unique_field . ')'; $this->Conn->Query($sql); } return $temp_table; } /** * Prepares mapping between event name+type and their ids in database * */ function _updateEventsCache() { $sql = 'SELECT EventId, CONCAT(Event,"_",Type) AS EventMix FROM ' . TABLE_PREFIX . 'Events'; $this->events_hash = $this->Conn->GetCol($sql, 'EventMix'); } /** * Returns language fields to be exported * * @return Array */ function _getExportFields() { return Array ( 'PackName', 'LocalName', 'DateFormat', 'TimeFormat', 'InputDateFormat', 'InputTimeFormat', 'DecimalPoint', 'ThousandSep', 'Charset', 'UnitSystem', 'Locale', 'UserDocsUrl' ); } /** * Processes parsed XML * * @param kXMLNode $language_node */ function _processLanguages(&$language_node) { if (array_key_exists('VERSION', $language_node->Parent->Attributes)) { // version present -> use it $version = $language_node->Parent->Attributes['VERSION']; } else { // version missing -> guess it if (is_object($language_node->FindChild('DATEFORMAT'))) { $version = 1; } elseif (array_key_exists('CHARSET', $language_node->Attributes)) { $version = 2; } } if ($version == 1) { $field_mapping = Array ( 'DATEFORMAT' => 'DateFormat', 'TIMEFORMAT' => 'TimeFormat', 'INPUTDATEFORMAT' => 'InputDateFormat', 'INPUTTIMEFORMAT' => 'InputTimeFormat', 'DECIMAL' => 'DecimalPoint', 'THOUSANDS' => 'ThousandSep', 'CHARSET' => 'Charset', 'UNITSYSTEM' => 'UnitSystem', 'DOCS_URL' => 'UserDocsUrl', ); } else { $export_fields = $this->_getExportFields(); } do { $language_id = false; $fields_hash = Array ( 'PackName' => $language_node->Attributes['PACKNAME'], 'LocalName' => $language_node->Attributes['PACKNAME'], 'Encoding' => $language_node->Attributes['ENCODING'], 'Charset' => 'utf-8', ); if ($version > 1) { foreach ($export_fields as $export_field) { $attribute_name = strtoupper($export_field); if (array_key_exists($attribute_name, $language_node->Attributes)) { $fields_hash[$export_field] = $language_node->Attributes[$attribute_name]; } } } $sub_node =& $language_node->firstChild; /* @var $sub_node kXMLNode */ do { switch ($sub_node->Name) { case 'PHRASES': if ($sub_node->Children) { if (!$language_id) { $language_id = $this->_processLanguage($fields_hash); } if ($this->_debugMode) { $start_time = microtime(true); } $this->_processPhrases($sub_node->firstChild, $language_id, $fields_hash['Encoding']); if ($this->_debugMode) { $this->Application->Debugger->appendHTML(__CLASS__ . '::' . '_processPhrases: ' . (microtime(true) - $start_time)); } } break; case 'EVENTS': if ($sub_node->Children) { if (!$language_id) { $language_id = $this->_processLanguage($fields_hash); } $this->_processEvents($sub_node->firstChild, $language_id, $fields_hash['Encoding']); } break; case 'COUNTRIES': if ($sub_node->Children) { if (!$language_id) { $language_id = $this->_processLanguage($fields_hash); } $this->_processCountries($sub_node->firstChild, $language_id, $fields_hash['Encoding']); } break; case 'REPLACEMENTS': // added since v2 $replacements = $sub_node->Data; if ($fields_hash['Encoding'] != 'plain') { $replacements = base64_decode($replacements); } $fields_hash['FilenameReplacements'] = $replacements; break; default: if ($version == 1) { $fields_hash[ $field_mapping[$sub_node->Name] ] = $sub_node->Data; } break; } } while (($sub_node =& $sub_node->NextSibling())); } while (($language_node =& $language_node->NextSibling())); } /** * Performs phases import * * @param kXMLNode $phrase_node * @param int $language_id * @param string $language_encoding */ function _processPhrases(&$phrase_node, $language_id, $language_encoding) { static $other_translations = Array (); if ($this->Application->isDebugMode()) { $this->Application->Debugger->profileStart('L[' . $language_id . ']P', 'Language: ' . $language_id . '; Phrases Import'); } do { $phrase_key = mb_strtoupper($phrase_node->Attributes['LABEL']); $fields_hash = Array ( 'Phrase' => $phrase_node->Attributes['LABEL'], 'PhraseKey' => $phrase_key, 'PhraseType' => $phrase_node->Attributes['TYPE'], 'Module' => array_key_exists('MODULE', $phrase_node->Attributes) ? $phrase_node->Attributes['MODULE'] : 'Core', 'LastChanged' => adodb_mktime(), 'LastChangeIP' => $this->ip_address, ); $translation = $phrase_node->Data; $hint_translation = isset($phrase_node->Attributes['HINT']) ? $phrase_node->Attributes['HINT'] : ''; $column_translation = isset($phrase_node->Attributes['COLUMN']) ? $phrase_node->Attributes['COLUMN'] : ''; if (array_key_exists($fields_hash['PhraseType'], $this->phrase_types_allowed)) { if ($language_encoding != 'plain') { $translation = base64_decode($translation); $hint_translation = base64_decode($hint_translation); $column_translation = base64_decode($column_translation); } if (array_key_exists($phrase_key, $other_translations)) { $other_translations[$phrase_key]['l' . $language_id . '_Translation'] = $translation; $other_translations[$phrase_key]['l' . $language_id . '_HintTranslation'] = $hint_translation; $other_translations[$phrase_key]['l' . $language_id . '_ColumnTranslation'] = $column_translation; } else { $other_translations[$phrase_key] = Array ( 'l' . $language_id . '_Translation' => $translation, 'l' . $language_id . '_HintTranslation' => $hint_translation, 'l' . $language_id . '_ColumnTranslation' => $column_translation, ); } $fields_hash = array_merge($fields_hash, $other_translations[$phrase_key]); $this->Conn->doInsert($fields_hash, $this->_tables['phrases'], 'REPLACE', false); } } while (($phrase_node =& $phrase_node->NextSibling())); if ($this->Application->isDebugMode()) { $this->Application->Debugger->profileFinish('L[' . $language_id . ']P', 'Language: ' . $language_id . '; Phrases Import'); } $this->Conn->doInsert($fields_hash, $this->_tables['phrases'], 'REPLACE'); } /** * Performs email event import * * @param kXMLNode $event_node * @param int $language_id * @param string $language_encoding */ function _processEvents(&$event_node, $language_id, $language_encoding) { static $other_translations = Array (); if ($this->Application->isDebugMode()) { $this->Application->Debugger->profileStart('L[' . $language_id . ']E', 'Language: ' . $language_id . '; Events Import'); } $email_message_helper =& $this->Application->recallObject('EmailMessageHelper'); /* @var $email_message_helper EmailMessageHelper */ do { $event_id = $this->_getEventId($event_node->Attributes['EVENT'], $event_node->Attributes['TYPE']); if ($event_id) { if ($language_encoding == 'plain') { $template = rtrim($event_node->Data); } else { $template = base64_decode($event_node->Data); } $parsed = $email_message_helper->parseTemplate($template); $fields_hash = Array ( 'EventId' => $event_id, 'Event' => $event_node->Attributes['EVENT'], 'Type' => $event_node->Attributes['TYPE'], 'MessageType' => $event_node->Attributes['MESSAGETYPE'], ); if (array_key_exists($event_id, $other_translations)) { $other_translations[$event_id]['l' . $language_id . '_Subject'] = $parsed['Subject']; $other_translations[$event_id]['l' . $language_id . '_Body'] = $parsed['Body']; } else { $other_translations[$event_id] = Array ( 'l' . $language_id . '_Subject' => $parsed['Subject'], 'l' . $language_id . '_Body' => $parsed['Body'], ); } if ($parsed['Headers']) { $other_translations[$event_id]['Headers'] = $parsed['Headers']; } elseif (!$parsed['Headers'] && !array_key_exists('Headers', $other_translations[$event_id])) { $other_translations[$event_id]['Headers'] = $parsed['Headers']; } $fields_hash = array_merge($fields_hash, $other_translations[$event_id]); $this->Conn->doInsert($fields_hash, $this->_tables['emailevents'], 'REPLACE', false); } } while (($event_node =& $event_node->NextSibling())); if ($this->Application->isDebugMode()) { $this->Application->Debugger->profileFinish('L[' . $language_id . ']E', 'Language: ' . $language_id . '; Events Import'); } if (isset($fields_hash)) { // at least one email event in language pack was found in database $this->Conn->doInsert($fields_hash, $this->_tables['emailevents'], 'REPLACE'); } } /** * Performs country_state translation import * * @param kXMLNode $country_state_node * @param int $language_id * @param string $language_encoding */ function _processCountries(&$country_state_node, $language_id, $language_encoding, $process_states = false) { static $other_translations = Array (); do { if ($process_states) { $country_state_id = $this->_getStateId($country_state_node->Parent->Attributes['ISO'], $country_state_node->Attributes['ISO']); } else { $country_state_id = $this->_getCountryId($country_state_node->Attributes['ISO']); } if ($country_state_id) { if ($language_encoding == 'plain') { $translation = rtrim($country_state_node->Attributes['TRANSLATION']); } else { $translation = base64_decode($country_state_node->Attributes['TRANSLATION']); } $fields_hash = Array ( 'CountryStateId' => $country_state_id, ); if (array_key_exists($country_state_id, $other_translations)) { $other_translations[$country_state_id]['l' . $language_id . '_Name'] = $translation; } else { $other_translations[$country_state_id] = Array ( 'l' . $language_id . '_Name' => $translation, ); } $fields_hash = array_merge($fields_hash, $other_translations[$country_state_id]); $this->Conn->doInsert($fields_hash, $this->_tables['country-state'], 'REPLACE', false); if (!$process_states && $country_state_node->Children) { $this->_processCountries($country_state_node->firstChild, $language_id, $language_encoding, true); } } } while (($country_state_node =& $country_state_node->NextSibling())); $this->Conn->doInsert($fields_hash, $this->_tables['country-state'], 'REPLACE'); } /** * Creates/updates language based on given fields and returns it's id * * @param Array $fields_hash * @return int */ function _processLanguage($fields_hash) { // 1. get language from database $sql = 'SELECT ' . $this->lang_object->IDField . ' FROM ' . $this->lang_object->TableName . ' WHERE PackName = ' . $this->Conn->qstr($fields_hash['PackName']); $language_id = $this->Conn->GetOne($sql); if ($language_id) { // 2. language found -> update, when allowed $this->lang_object->Load($language_id); if ($this->import_mode == LANG_OVERWRITE_EXISTING) { // update live language record based on data from xml $this->lang_object->SetFieldsFromHash($fields_hash); $this->lang_object->Update(); } } else { // 3. language not found -> create $this->lang_object->SetFieldsFromHash($fields_hash); $this->lang_object->SetDBField('Enabled', STATUS_ACTIVE); if ($this->lang_object->Create()) { $language_id = $this->lang_object->GetID(); if (defined('IS_INSTALL') && IS_INSTALL) { // language created during install becomes admin interface language $this->lang_object->setPrimary(true, true); } } } // 4. collect ID of every processed language if (!in_array($language_id, $this->_languages)) { $this->_languages[] = $language_id; } return $language_id; } /** * Returns event id based on it's name and type * * @param string $event_name * @param string $event_type * @return int */ function _getEventId($event_name, $event_type) { $cache_key = $event_name . '_' . $event_type; return array_key_exists($cache_key, $this->events_hash) ? $this->events_hash[$cache_key] : 0; } /** * Returns country id based on it's 3letter ISO code * * @param string $iso * @return int */ function _getCountryId($iso) { static $cache = null; if (!isset($cache)) { $sql = 'SELECT CountryStateId, IsoCode FROM ' . TABLE_PREFIX . 'CountryStates WHERE Type = ' . DESTINATION_TYPE_COUNTRY; $cache = $this->Conn->GetCol($sql, 'IsoCode'); } return array_key_exists($iso, $cache) ? $cache[$iso] : false; } /** * Returns state id based on 3letter country ISO code and 2letter state ISO code * * @param string $country_iso * @param string $state_iso * @return int */ function _getStateId($country_iso, $state_iso) { static $cache = null; if (!isset($cache)) { $sql = 'SELECT CountryStateId, CONCAT(StateCountryId, "-", IsoCode) AS IsoCode FROM ' . TABLE_PREFIX . 'CountryStates WHERE Type = ' . DESTINATION_TYPE_STATE; $cache = $this->Conn->GetCol($sql, 'IsoCode'); } $country_id = $this->_getCountryId($country_iso); return array_key_exists($country_id . '-' . $state_iso, $cache) ? $cache[$country_id . '-' . $state_iso] : false; } }