Index: branches/RC/core/units/general/helpers/language_import_helper.php =================================================================== diff -u -N --- branches/RC/core/units/general/helpers/language_import_helper.php (revision 11952) +++ branches/RC/core/units/general/helpers/language_import_helper.php (revision 0) @@ -1,596 +0,0 @@ -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 = getmicrotime(); - $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', 'Phrase'); - $this->_performUpgrade($language_id, 'emailmessages', 'EventId'); - } - - $this->_initImportTables(true); - - if ($this->_debugMode) { - $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '"): ' . (getmicrotime() - $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) ); - - $this->events_hash = array_flip($this->events_hash); - - $lang_table = $this->Application->getUnitOption('lang','TableName'); - $phrases_table = $this->Application->getUnitOption('phrases','TableName'); - $emailevents_table = $this->Application->getUnitOption('emailmessages','TableName'); - $mainevents_table = $this->Application->getUnitOption('emailevents','TableName'); - - $phrase_tpl = "\t\t\t".'%s'."\n"; - $event_tpl = "\t\t\t".'%s'."\n"; - $sql = 'SELECT * FROM %s WHERE LanguageId = %s'; - $ret = ''."\n"; - foreach ($language_ids as $language_id) { - // languages - $row = $this->Conn->GetRow( sprintf($sql, $lang_table, $language_id) ); - $ret .= "\t".''.$row['DateFormat'].''; - $ret .= ''.$row['TimeFormat'].''.$row['InputDateFormat'].''; - $ret .= ''.$row['InputTimeFormat'].''.$row['DecimalPoint'].''; - $ret .= ''.$row['ThousandSep'].''.$row['Charset'].''.$row['UserDocsUrl'].''; - $ret .= ''.$row['UnitSystem'].''."\n"; - - // phrases - $phrases_sql = 'SELECT * FROM '.$phrases_table.' WHERE LanguageId = %s AND PhraseType IN (%s) AND Module IN (%s) ORDER BY Phrase'; - if( in_array('In-Portal',$module_ids) ) array_push($module_ids, ''); // for old language packs - $rows = $this->Conn->Query( sprintf($phrases_sql,$language_id, implode(',',$phrase_types), '\''.implode('\',\'',$module_ids).'\'' ) ); - if($rows) - { - $ret .= "\t\t".''."\n"; - foreach($rows as $row) - { - $data = $this->_exportEncoding == 'base64' ? base64_encode($row['Translation']) : ''; - $ret .= sprintf($phrase_tpl, $row['Phrase'], $row['Module'], $row['PhraseType'], $data ); - } - $ret .= "\t\t".''."\n"; - } - - // email events - if( in_array('In-Portal',$module_ids) ) unset( $module_ids[array_search('',$module_ids)] ); // for old language packs - $module_sql = preg_replace('/(.*) OR $/', '\\1', preg_replace('/(.*),/U', 'INSTR(Module,\'\\1\') OR ', implode(',', $module_ids).',' ) ); - - $sql = 'SELECT EventId FROM '.$mainevents_table.' WHERE '.$module_sql; - $event_ids = $this->Conn->GetCol($sql); - - if($event_ids) - { - $ret .= "\t\t".''."\n"; - $event_sql = ' SELECT em.* - FROM '.$emailevents_table.' em - LEFT JOIN '.$mainevents_table.' e ON e.EventId = em.EventId - WHERE em.LanguageId = %s AND em.EventId IN (%s) - ORDER BY e.Event, e.Type'; - $rows = $this->Conn->Query( sprintf($event_sql,$language_id, $event_ids ? implode(',',$event_ids) : '' ) ); - foreach($rows as $row) - { - if (!array_key_exists($row['EventId'], $this->events_hash)) { - // don't export existing translations of missing events - continue; - } - - list($event_name, $event_type) = explode('_', $this->events_hash[ $row['EventId'] ] ); - $data = $this->_exportEncoding == 'base64' ? base64_encode($row['Template']) : ''; - $ret .= sprintf($event_tpl, $row['MessageType'], $event_name, $event_type, $data ); - } - $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; - } - - /** - * Performs upgrade of given language pack part - * - * @param int $language_id - * @param string $prefix - * @param string $unique_field - */ - function _performUpgrade($language_id, $prefix, $unique_field) - { - // TODO: find a way to compare (intersect,diff) phrases in non-case sensitive way, but keeping original case in result - $live_records = $this->_getTableData($language_id, $prefix, $unique_field, false); - $temp_records = $this->_getTableData($language_id, $prefix, $unique_field, true); - - if ($this->import_mode == LANG_OVERWRITE_EXISTING) { - // remove existing records before copy - $common_records = array_intersect($temp_records, $live_records); - if ($common_records) { - $live_records = array_diff($live_records, $common_records); // remove overlaping records - $common_records = array_map(Array(&$this->Conn, 'qstr'), $common_records); - - $sql = 'DELETE FROM ' . $this->Application->getUnitOption($prefix, 'TableName') . ' - WHERE (LanguageId = ' . $language_id . ') AND (' . $unique_field . ' IN (' . implode(',', $common_records) . '))'; - $this->Conn->Query($sql); - } - } - - $temp_records = array_diff($temp_records, $live_records); - - if (!$temp_records) { - // no new records found in temp table while comparing it to live table - return ; - } - - $temp_records = array_map(Array(&$this->Conn, 'qstr'), $temp_records); - - $sql = 'INSERT INTO ' . $this->Application->getUnitOption($prefix, 'TableName') . ' - SELECT * - FROM ' . $this->_tables[$prefix] . ' - WHERE (LanguageId = ' . $language_id . ')'; - - if ($live_records) { - // subsctract live records from temp table during coping - $sql .= ' AND (' . $unique_field . ' IN (' . implode(',', $temp_records) . '))'; - } - - $this->Conn->Query($sql); - } - - /** - * Returns data from given table used for language pack upgrade - * - * @param int $language_id - * @param string $prefix - * @param string $unique_field - * @param bool $temp_mode - * @return Array - */ - function _getTableData($language_id, $prefix, $unique_field, $temp_mode = false) - { - $table_name = $this->Application->getUnitOption($prefix, 'TableName'); - - if ($temp_mode) { - $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $prefix); - } - - $sql = 'SELECT ' . $unique_field . ' - FROM ' . $table_name . ' - WHERE LanguageId = ' . $language_id; - return $this->Conn->GetCol($sql); - } - - function _parseXML($filename) - { - if ($this->_debugMode) { - $start_time = getmicrotime(); - $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 . '"): ' . (getmicrotime() - $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['emailmessages'] = $this->_prepareTempTable('emailmessages', $drop_only); - } - - /** - * Create temp table for prefix, if table already exists, then delete it and create again - * - * @param string $prefix - */ - function _prepareTempTable($prefix, $drop_only = false) - { - $idfield = $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 %s SELECT * FROM %s WHERE 0'; - $this->Conn->Query( sprintf($sql, $temp_table, $table) ); - - $sql = 'ALTER TABLE %1$s CHANGE %2$s %2$s INT(11) NOT NULL'; - $this->Conn->Query( sprintf($sql, $temp_table, $idfield) ); - } - - 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'); - } - - /** - * Processes parsed XML - * - * @param kXMLNode $language_node - */ - function _processLanguages(&$language_node) - { - $field_mapping = Array ( - 'DATEFORMAT' => 'DateFormat', - 'TIMEFORMAT' => 'TimeFormat', - 'INPUTDATEFORMAT' => 'InputDateFormat', - 'INPUTTIMEFORMAT' => 'InputTimeFormat', - 'DECIMAL' => 'DecimalPoint', - 'THOUSANDS' => 'ThousandSep', - 'CHARSET' => 'Charset', - 'UNITSYSTEM' => 'UnitSystem', - 'DOCS_URL' => 'UserDocsUrl', - ); - - do { - $language_id = false; - - $fields_hash = Array ( - 'PackName' => $language_node->Attributes['PACKNAME'], - 'LocalName' => $language_node->Attributes['PACKNAME'], - 'Encoding' => $language_node->Attributes['ENCODING'], - 'Charset' => 'iso-8859-1', - ); - - $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 = getmicrotime(); - } - - $this->_processPhrases($sub_node->firstChild, $language_id, $fields_hash['Encoding']); - - if ($this->_debugMode) { - $this->Application->Debugger->appendHTML(__CLASS__ . '::' . '_processPhrases: ' . (getmicrotime() - $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; - - default: - $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) - { - do { - $fields_hash = Array ( - 'LanguageId' => $language_id, - 'Phrase' => $phrase_node->Attributes['LABEL'], - '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, - ); - - if (array_key_exists($fields_hash['PhraseType'], $this->phrase_types_allowed)) { - if ($language_encoding != 'plain') { - $fields_hash['Translation'] = base64_decode($fields_hash['Translation']); - } - - $this->Conn->doInsert($fields_hash, $this->_tables['phrases'], 'INSERT', false); - } - } while (($phrase_node =& $phrase_node->NextSibling())); - - $this->Conn->doInsert($fields_hash, $this->_tables['phrases'], 'INSERT'); - } - - /** - * Performs email event import - * - * @param kXMLNode $event_node - * @param int $language_id - * @param string $language_encoding - */ - function _processEvents(&$event_node, $language_id, $language_encoding) - { - do { - $event_id = $this->_getEventId($event_node->Attributes['EVENT'], $event_node->Attributes['TYPE']); - if ($event_id) { - $fields_hash = Array ( - 'LanguageId' => $language_id, - 'EventId' => $event_id, - 'MessageType' => $event_node->Attributes['MESSAGETYPE'], - ); - - if ($language_encoding == 'plain') { - $fields_hash['Template'] = rtrim($event_node->Data); - } - else { - $fields_hash['Template'] = base64_decode($event_node->Data); - } - - $this->Conn->doInsert($fields_hash, $this->_tables['emailmessages'], 'INSERT', false); - } - } while (($event_node =& $event_node->NextSibling())); - - $this->Conn->doInsert($fields_hash, $this->_tables['emailmessages'], 'INSERT'); - } - - /** - * 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; - } - } \ No newline at end of file