Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1092244
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Aug 9, 4:04 PM
Size
40 KB
Mime Type
text/x-diff
Expires
Mon, Aug 11, 4:04 PM (1 h, 3 m)
Engine
blob
Format
Raw Data
Handle
707295
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/5.0.x/core/units/helpers/email_message_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/email_message_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/email_message_helper.php (revision 12400)
@@ -0,0 +1,43 @@
+<?php
+
+ class EmailMessageHelper extends kHelper {
+
+ /**
+ * Extracts Subject, Headers, Body fields from email message translation
+ *
+ * @param string $text
+ * @return Array
+ */
+ function parseTemplate($text)
+ {
+ $ret = Array ();
+ $headers = Array();
+ $lines = explode("\n", $text);
+
+ foreach ($lines as $line) {
+ if (strlen(trim($line)) == 0 || ($line == '.')) {
+ break;
+ }
+
+ $parts = explode(':', $line, 2);
+ if (strtolower($parts[0]) == 'subject') {
+ $ret['Subject'] = trim($parts[1]);
+ }
+ else {
+ $headers[] = $line;
+ }
+ }
+
+ $ret['Headers'] = implode("\n", $headers);
+
+ $message_body = '';
+ while ((list($line_id,$line) = each($lines))) {
+ $message_body .= $line;
+ }
+
+ $ret['Body'] = $message_body;
+
+ return $ret;
+ }
+
+ }
\ No newline at end of file
Index: branches/5.0.x/core/units/helpers/language_import_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/language_import_helper.php (revision 12399)
+++ branches/5.0.x/core/units/helpers/language_import_helper.php (revision 12400)
@@ -1,599 +1,608 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
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';
/**
* Debug language pack import process
*
* @var bool
*/
var $_debugMode = false;
function LanguageImportHelper()
{
parent::kHelper();
// "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 = 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".'<PHRASE Label="%s" Module="%s" Type="%s">%s</PHRASE>'."\n";
$event_tpl = "\t\t\t".'<EVENT MessageType="%s" Event="%s" Type="%s">%s</EVENT>'."\n";
$sql = 'SELECT * FROM %s WHERE LanguageId = %s';
$ret = '<LANGUAGES>'."\n";
foreach ($language_ids as $language_id) {
// languages
$row = $this->Conn->GetRow( sprintf($sql, $lang_table, $language_id) );
$ret .= "\t".'<LANGUAGE PackName="'.$row['PackName'].'" Encoding="'.$this->_exportEncoding.'"><DATEFORMAT>'.$row['DateFormat'].'</DATEFORMAT>';
$ret .= '<TIMEFORMAT>'.$row['TimeFormat'].'</TIMEFORMAT><INPUTDATEFORMAT>'.$row['InputDateFormat'].'</INPUTDATEFORMAT>';
$ret .= '<INPUTTIMEFORMAT>'.$row['InputTimeFormat'].'</INPUTTIMEFORMAT><DECIMAL>'.$row['DecimalPoint'].'</DECIMAL>';
$ret .= '<THOUSANDS>'.$row['ThousandSep'].'</THOUSANDS><CHARSET>'.$row['Charset'].'</CHARSET><DOCS_URL>'.$row['UserDocsUrl'].'</DOCS_URL>';
$ret .= '<UNITSYSTEM>'.$row['UnitSystem'].'</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".'<PHRASES>'."\n";
foreach($rows as $row)
{
$data = $this->_exportEncoding == 'base64' ? base64_encode($row['Translation']) : '<![CDATA['.$row['Translation'].']]>';
$ret .= sprintf($phrase_tpl, $row['Phrase'], $row['Module'], $row['PhraseType'], $data );
}
$ret .= "\t\t".'</PHRASES>'."\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".'<EVENTS>'."\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']) : '<![CDATA['.$row['Template'].']]>';
$ret .= sprintf($event_tpl, $row['MessageType'], $event_name, $event_type, $data );
}
$ret .= "\t\t".'</EVENTS>'."\n";
}
$ret .= "\t".'</LANGUAGE>'."\n";
}
$ret .= '</LANGUAGES>';
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)
{
+ $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) {
$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);
}
+ $parsed = $email_message_helper->parseTemplate($fields_hash['Template']);
+ $fields_hash['Subject'] = $parsed['Subject'];
+
$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');
+ if ($fields_hash) {
+ // at least one corresponding event declaration found by email event name+type given in translation
+ $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
Index: branches/5.0.x/core/units/helpers/helpers_config.php
===================================================================
--- branches/5.0.x/core/units/helpers/helpers_config.php (revision 12399)
+++ branches/5.0.x/core/units/helpers/helpers_config.php (revision 12400)
@@ -1,60 +1,61 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
$config = Array (
'Prefix' => 'helpers',
'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
'RegisterClasses' => Array (
Array ('pseudo' => 'kMultiLanguageHelper', 'class' => 'kMultiLanguageHelper', 'file' => 'multilanguage_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SearchHelper', 'class' => 'kSearchHelper', 'file' => 'search_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SectionsHelper', 'class' => 'kSectionsHelper', 'file' => 'sections_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PermissionsHelper', 'class' => 'kPermissionsHelper', 'file' => 'permissions_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModulesHelper', 'class' => 'kModulesHelper', 'file' => 'modules_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModRewriteHelper', 'class' => 'kModRewriteHelper', 'file' => 'mod_rewrite_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RecursiveHelper', 'class' => 'kRecursiveHelper', 'file' => 'recursive_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FilenamesHelper', 'class' => 'kFilenamesHelper', 'file' => 'filenames_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ClipboardHelper', 'class' => 'kClipboardHelper', 'file' => 'clipboard_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ColumnPickerHelper', 'class' => 'kColumnPickerHelper', 'file' => 'col_picker_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ThemesHelper', 'class' => 'kThemesHelper', 'file' => 'themes_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CaptchaHelper', 'class' => 'kCaptchaHelper', 'file' => 'captcha_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PriorityHelper', 'class' => 'kPriorityHelper', 'file' => 'priority_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CurlHelper', 'class' => 'kCurlHelper', 'file' => 'curl_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CountHelper', 'class' => 'kCountHelper', 'file' => 'count_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ImageHelper', 'class' => 'ImageHelper', 'file' => 'image_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FileHelper', 'class' => 'FileHelper', 'file' => 'file_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CategoryHelper', 'class' => 'CategoryHelper', 'file' => 'category_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CSVHelper', 'class' => 'kCSVHelper', 'file' => 'csv_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ChartHelper', 'class' => 'kChartHelper', 'file' => 'chart_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RatingHelper', 'class' => 'RatingHelper', 'file' => 'rating_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FCKHelper', 'class' => 'fckFCKHelper', 'file' => 'fck_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SpamHelper', 'class' => 'SpamHelper', 'file' => 'spam_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'TemplateHelper', 'class' => 'TemplateHelper', 'file' => 'template_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MailingListHelper', 'class' => 'MailingListHelper', 'file' => 'mailing_list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'JSONHelper', 'class' => 'JSONHelper', 'file' => 'json_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'SiteConfigHelper', 'pseudo' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'InpCustomFieldsHelper', 'pseudo' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kBracketsHelper', 'pseudo' => 'BracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kXMLHelper', 'pseudo' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kCatDBItemExportHelper', 'pseudo' => 'CatItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'EmailMessageHelper', 'pseudo' => 'EmailMessageHelper', 'file' => 'email_message_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
),
);
\ No newline at end of file
Index: branches/5.0.x/core/units/email_messages/email_messages_event_handler.php
===================================================================
--- branches/5.0.x/core/units/email_messages/email_messages_event_handler.php (revision 12399)
+++ branches/5.0.x/core/units/email_messages/email_messages_event_handler.php (revision 12400)
@@ -1,431 +1,412 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class EmailMessagesEventHandler extends kDBEventHandler
{
/**
* Replace id passed with id of email message
*
* @param kEvent $event
*/
function getPassedID(&$event)
{
$event->setEventParam('raise_warnings', 0);
$parent = parent::getPassedID($event);
if ($parent) {
return $parent;
}
$email_event_id = (int)$this->getEmailEventId();
$object =& $event->getObject();
$parent_info = $object->getLinkedInfo();
$sql = 'SELECT '.$object->IDField.'
FROM '.$object->TableName.'
WHERE ('.$parent_info['ForeignKey'].' = '.$parent_info['ParentId'].') AND (EventId = '.$email_event_id.')';
return (int)$this->Conn->GetOne($sql);
}
function getEmailEventId()
{
return parent::getPassedID( new kEvent('emailevents:OnDummy') );
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @access protected
* @see OnListBuild
*/
function SetCustomQuery(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
if ($event->Special == 'module') {
$module = $this->Application->GetVar('module');
$object->addFilter('module_filter', 'Module = ' . $this->Conn->qstr($module));
}
if (($event->Special == 'st') && !$this->Application->isDebugMode()) {
$object->addFilter('enabled_filter', TABLE_PREFIX . 'Events.Enabled <> ' . STATUS_DISABLED);
}
}
/**
* If loading empty item, then set parent id
*
* @param kEvent $event
*/
function OnBeforeItemLoad(&$event)
{
if (!$event->getEventParam('id')) {
$this->OnNew($event);
$event->status = erFATAL;
}
}
/**
* Sets event id
*
* @param kEvent $event
*/
function OnNew(&$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('EventId', $this->getEmailEventId());
$object->SetDBField('Headers', $this->Application->ConfigValue('Smtp_DefaultHeaders') );
}
/**
* Parse message template (split into header, subject & body)
*
* @param kEvent $event
*/
function OnAfterItemLoad(&$event)
{
$object =& $event->getObject();
-
- $lines = explode("\n", $object->GetDBField('Template') );
-
- $headers = Array();
-
- foreach($lines as $line)
- {
- if( strlen(trim($line)) == 0 || ($line == '.') ) break;
-
- $parts = explode(':', $line, 2);
- if(strtolower($parts[0]) == 'subject')
- {
- $object->SetDBField('Subject', trim($parts[1]) );
- }
- else
- {
- $headers[] = $line;
- }
- }
- $object->SetDBField('Headers', implode("\n", $headers) );
-
- $message_body = '';
- while( (list($line_id,$line) = each($lines)) )
- {
- $message_body .= $line;
- }
- $object->SetDBField('Body', $message_body);
+ /* @var $object kDBItem */
+
+ $email_message_helper =& $this->Application->recallObject('EmailMessageHelper');
+ /* @var $email_message_helper EmailMessageHelper */
+
+ $fields_hash = $email_message_helper->parseTemplate( $object->GetDBField('Template') );
+
+ $object->SetDBFieldsFromHash($fields_hash);
}
/**
* Merge body+subject+headers into message template
*
* @param kEvent $event
*/
function OnBeforeItemUpdate(&$event)
{
$this->parseVirtualFields($event);
}
/**
* Merge body+subject+headers into message template
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$this->parseVirtualFields($event);
}
/**
* Enabled/disables actual email event
*
* @param kEvent $event
*/
function OnAfterItemUpdate(&$event)
{
parent::OnAfterItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ($object->GetDBField('Enabled') != $object->GetOriginalField('Enabled')) {
$email_event =& $this->Application->recallObject('emailevents.-item', null, Array ('skip_autoload' => true));
/* @var $email_event kDBItem */
$email_event->Load( $object->GetDBField('EventId') );
if ($email_event->isLoaded()) {
$email_event->SetDBField('Enabled', $object->GetDBField('Enabled'));
$email_event->Update();
}
}
}
/**
* Merge body+subject+headers into message template
*
* @param kEvent $event
*/
function parseVirtualFields(&$event)
{
$object =& $event->getObject();
if( $object->GetDBField('Headers') || $object->GetDBField('Subject') || $object->GetDBField('Body') )
{
$ret = $object->GetDBField('Headers');
if($ret) $ret .= "\n";
$ret = $this->removeTrailingCRLF($ret);
$ret .= 'Subject: '.$object->GetDBField('Subject')."\n\n";
$ret .= $object->GetDBField('Body');
$object->SetDBField('Template', $ret);
}
}
/**
* Remove trailing CR/LF chars from string
*
* @param string $string
* @return string
*/
function removeTrailingCRLF($string)
{
return preg_replace('/(\n|\r)+/',"\\1",$string);
}
/**
* Prepares selected user(-s) or group(-s) for message sending
*
* @param kEvent $event
*/
function OnPrepareMassRecipients(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$object->Clear(0);
$event->redirect = false;
$this->Application->RemoveVar('recipient_ids');
$this->Application->RemoveVar('recipient_type');
$this->saveMassRecipients('u');
$this->saveMassRecipients('g', 'total');
}
function saveMassRecipients($prefix, $special = '')
{
$recipients = $this->Application->GetVar(rtrim($prefix.'_'.$special, '_'));
if ($recipients) {
$this->Application->StoreVar('recipient_ids', implode(',', array_keys($recipients)));
$this->Application->StoreVar('recipient_type', $prefix);
}
}
/**
* Sends mass mail
*
* @param kEvent $event
*/
function OnMassMail(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$object->setRequired('MassSubject', true);
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
list($id, $field_values) = each($items_info);
$object->SetFieldsFromHash($field_values);
}
if (!$object->Validate()) {
$event->redirect = false;
$event->status = erFAIL;
$object->setID($id);
return ;
}
$fields_hash = $object->GetFieldValues();
list ($fields_hash['FromEmail'], $fields_hash['FromName']) = $this->getSenderData();
if ($fields_hash['MassAttachment']) {
$field_options = $object->GetFieldOptions('MassAttachment');
$fields_hash['MassAttachment'] = $field_options['upload_dir'].$fields_hash['MassAttachment'];
}
$this->Application->RemoveVar('email_prepare_progress');
$this->Application->StoreVar('email_prepare_fields', serialize($fields_hash));
$event->redirect = 'emails/prepare_queue';
}
/**
* Generates email queue using progress bar
*
* @param kEvent $event
* @todo Move to MailingList
*/
function OnPrepareEmailQueue(&$event)
{
$prepare_count = $this->Application->ConfigValue('MailingListQueuePerStep');
if ($prepare_count === false) {
// 10 recipients per script run (if none defined in config)
$prepare_count = 10;
}
$email_prepare_progress = $this->Application->RecallVar('email_prepare_progress');
if ($email_prepare_progress === false) {
$emails_prepared = 0;
$total_emails = $this->getRecipientEmails(true);
$this->Application->StoreVar('email_prepare_progress', $emails_prepared.':'.$total_emails);
}
else {
list ($emails_prepared, $total_emails) = explode(':', $email_prepare_progress);
}
$recipient_emails = $this->getRecipientEmails(false, $emails_prepared.','.$prepare_count);
$recipient_email_count = count($recipient_emails);
if (!$recipient_email_count) {
// no recipients left to prepare
$this->finalizeQueuePreparing($fields_hash['MassAttachment']);
}
$fields_hash = unserialize($this->Application->RecallVar('email_prepare_fields'));
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
// 1. set headers same for all emails
$esender->SetFrom($fields_hash['FromEmail'], $fields_hash['FromName']);
$esender->SetSubject($fields_hash['MassSubject']);
$esender->SetBody($fields_hash['MassHtmlMessage'], $fields_hash['MassTextMessage']);
// 2. add attachment if any
if ($fields_hash['MassAttachment']) {
$esender->AddAttachment(FULL_PATH.$fields_hash['MassAttachment']);
}
foreach ($recipient_emails as $recipient_email) {
// 3. set recipient specific fields
$esender->SetTo($recipient_email, $recipient_email);
$esender->Deliver(null, false, false);
// 4. write to log
$log_fields_hash = Array (
'fromuser' => $fields_hash['FromName'],
'addressto' => $recipient_email,
'subject' => $fields_hash['MassSubject'],
'timestamp' => adodb_mktime(),
'event' => '',
);
$this->Conn->doInsert($log_fields_hash, TABLE_PREFIX.'EmailLog');
}
$emails_prepared += $recipient_email_count;
if ($emails_prepared >= $total_emails) {
$this->finalizeQueuePreparing($fields_hash['MassAttachment']);
}
$this->Application->StoreVar('email_prepare_progress', $emails_prepared.':'.$total_emails);
$event->status = erSTOP;
echo ($emails_prepared / $total_emails) * 100;
}
function finalizeQueuePreparing($attachment_file = null)
{
// variables from users/groups grid
$this->Application->RemoveVar('recipient_ids');
$this->Application->RemoveVar('recipient_type');
if ($attachment_file) {
unlink(FULL_PATH.$attachment_file);
}
// variables from email preparing process
// $this->Application->RemoveVar('email_prepare_progress');
// $this->Application->RemoveVar('email_prepare_fields');
// variables from email delivering process (not yet executed)
$this->Application->RemoveVar('email_queue_progress');
$this->Application->Redirect($this->Application->GetVar('finish_template'));
}
function getRecipientEmails($for_counting = false, $limit = null)
{
$recipient_type = $this->Application->RecallVar('recipient_type');
$recipient_ids = $this->Application->RecallVar('recipient_ids');
if (!$recipient_ids) {
return $for_counting ? 0 : Array ();
}
if ($recipient_type == 'u') {
$sql = 'SELECT '.($for_counting ? 'COUNT(*)' : 'Email').'
FROM '.TABLE_PREFIX.'PortalUser
WHERE PortalUserId IN ('.$recipient_ids.')';
}
else {
$sql = 'SELECT '.($for_counting ? 'COUNT(*)' : 'u.Email').'
FROM '.TABLE_PREFIX.'UserGroup ug
LEFT JOIN '.TABLE_PREFIX.'PortalUser u ON ug.PortalUserId = u.PortalUserId
WHERE ug.GroupId IN ('.$recipient_ids.')';
}
if ($for_counting) {
return $this->Conn->GetOne($sql);
}
if (isset($limit)) {
$sql .= ' LIMIT '.$limit;
}
return $this->Conn->GetCol($sql);
}
/**
* Returns mass mail sender name & email
*
* @return Array
*/
function getSenderData()
{
$user =& $this->Application->recallObject('u.current');
/* @var $user UsersItem */
if ($user->GetID() > 0) {
$email_address = $user->GetDBField('Email');
$name = $user->GetDBField('FirstName').' '.$user->GetDBField('LastName');
}
else {
$email_address = $this->Application->ConfigValue('Smtp_AdminMailFrom');
$name = strip_tags( $this->Application->ConfigValue('Site_Name') );
}
return Array ($email_address, $name);
}
}
\ No newline at end of file
Event Timeline
Log In to Comment