Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Sat, May 3, 11:27 AM

in-portal

Index: branches/5.2.x/core/units/helpers/email_message_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/email_message_helper.php (revision 15464)
+++ branches/5.2.x/core/units/helpers/email_message_helper.php (revision 15465)
@@ -1,91 +1,91 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 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.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kEmailMessageHelper extends kHelper {
/**
* Extracts Subject, Headers, Body fields from email message translation
*
* @param string|SimpleXMLElement $text
* @param string $message_type
* @return Array
*/
function parseTemplate($text, $message_type = '')
{
$ret = Array ('Subject' => '', 'Headers' => '', 'HtmlBody' => '', 'PlainTextBody' => '');
if ( $message_type == '' ) {
// this is v5+ e-mail event text as xml node
foreach ($ret as $field => $value) {
$node_name = strtoupper($field);
$ret[$field] = (string)$text->$node_name;
}
return $ret;
}
$line_id = 1;
$headers = Array();
$lines = explode("\n", $text); // "\n" is lost in process
foreach ($lines as $line_id => $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'] = $headers ? implode("\n", $headers) : null; // it's null field
$lines = array_slice($lines, $line_id + 1);
// add "\n", that was lost before
$ret[$message_type == 'html' ? 'HtmlBody' : 'PlainTextBody'] = implode("\n", $lines);
return $ret;
}
/**
* Parses contents of given object field and sets error, when invalid in-portal tags found
* @param kDBItem $object
* @param string $field
* @return void
* @access public
*/
public function parseField($object, $field)
{
$this->Application->InitParser();
try {
$this->Application->Parser->CompileRaw($object->GetField($field), 'email_template');
}
- catch (ParserException $e) {
+ catch (Exception $e) {
if ( $this->Application->isDebugMode() ) {
$this->Application->Debugger->appendHTML('<b style="color: red;">Error in Email Template:</b> ' . $e->getMessage() . ' (line: ' . $e->getLine() . ')');
}
$object->SetError($field, 'parsing_error');
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/phrases/phrases_event_handler.php
===================================================================
--- branches/5.2.x/core/units/phrases/phrases_event_handler.php (revision 15464)
+++ branches/5.2.x/core/units/phrases/phrases_event_handler.php (revision 15465)
@@ -1,503 +1,520 @@
<?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.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class PhrasesEventHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnItemBuild' => Array ('self' => true, 'subitem' => true),
'OnPreparePhrase' => Array ('self' => true, 'subitem' => true),
'OnExportPhrases' => Array ('self' => 'view'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
+ * Hides phrases from disabled modules
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function SetCustomQuery(kEvent $event)
+ {
+ parent::SetCustomQuery($event);
+
+ $object = $event->getObject();
+ /* @var $object kDBList */
+
+ $object->addFilter('module_filter', '%1$s.Module IN (SELECT Name FROM ' . TABLE_PREFIX . 'Modules WHERE Loaded = 1)');
+ }
+
+ /**
* Apply some special processing to object being
* recalled before using it in other events that
* call prepareObject
*
* @param kDBItem|kDBList $object
* @param kEvent $event
* @return void
* @access protected
*/
protected function prepareObject(&$object, kEvent $event)
{
// don't call parent
if ( $event->Special == 'import' || $event->Special == 'export' ) {
$this->RemoveRequiredFields($object);
$object->setRequired(Array ('ExportDataTypes', 'LangFile', 'PhraseType', 'Module'));
// allow multiple phrase types to be selected during import/export
$object->SetFieldOption('PhraseType', 'type', 'string');
}
}
/**
* Allow to create phrases from front end in debug mode with DBG_PHRASES constant set
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent $event)
{
if ( !$this->Application->isAdmin && $this->Application->isDebugMode(false) && kUtil::constOn('DBG_PHRASES') ) {
$allow_events = Array ('OnCreate', 'OnUpdate');
if ( in_array($event->Name, $allow_events) ) {
return true;
}
}
return parent::CheckPermission($event);
}
/**
* Prepares phrase for translation
*
* @param kEvent $event
*/
function OnPreparePhrase($event)
{
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if (!$label) {
return ;
}
// we got label, try to get it's ID then if any
$phrase_id = $this->_getPhraseId($label);
if ($phrase_id) {
$event->SetRedirectParam($event->getPrefixSpecial(true) . '_id', $phrase_id);
$event->SetRedirectParam('pass', 'm,' . $event->getPrefixSpecial());
$next_template = $this->Application->GetVar('next_template');
if ($next_template) {
$event->SetRedirectParam('next_template', $next_template);
}
}
else {
$event->CallSubEvent('OnNew');
}
if ($this->Application->GetVar('simple_mode')) {
$event->SetRedirectParam('simple_mode', 1);
}
}
function _getPhraseId($phrase)
{
$sql = 'SELECT ' . $this->Application->getUnitOption($this->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . '
WHERE PhraseKey = ' . $this->Conn->qstr( mb_strtoupper($phrase) );
return $this->Conn->GetOne($sql);
}
/**
* Sets phrase type based on place where it's created (to display on form only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreCreate(kEvent $event)
{
parent::OnPreCreate($event);
$object = $event->getObject();
/* @var $object kDBItem */
$this->_setPhraseModule($object);
}
/**
* Forces new label in case if issued from get link
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnNew(kEvent $event)
{
parent::OnNew($event);
$object = $event->getObject();
/* @var $object kDBItem */
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if ( $label ) {
// phrase is created in language, used to display phrases
$object->SetDBField('Phrase', $label);
$object->SetDBField('PhraseType', $this->_getPhraseType($label)); // to show on form
$object->SetDBField('PrimaryTranslation', $this->_getPrimaryTranslation($label));
}
$this->_setPhraseModule($object);
if ( $event->Special == 'export' || $event->Special == 'import' ) {
$object->SetDBField('PhraseType', '|0|1|2|');
$object->SetDBField('Module', '|' . implode('|', array_keys($this->Application->ModuleInfo)) . '|');
$export_mode = $this->Application->GetVar('export_mode');
if ( $export_mode != 'lang' ) {
$object->SetDBField('ExportDataTypes', '|' . $export_mode . '|');
}
}
}
/**
* Returns given phrase translation on primary language
*
* @param string $phrase
* @return string
* @access protected
*/
protected function _getPrimaryTranslation($phrase)
{
$sql = 'SELECT l' . $this->Application->GetDefaultLanguageId() . '_Translation
FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . '
WHERE PhraseKey = ' . $this->Conn->qstr( mb_strtoupper($phrase) );
return $this->Conn->GetOne($sql);
}
/**
* Sets new phrase module
*
* @param kDBItem $object
* @return void
* @access protected
*/
protected function _setPhraseModule(&$object)
{
$last_module = $this->Application->GetVar('last_module');
if ( $last_module ) {
$object->SetDBField('Module', $last_module);
}
}
/**
* Forces create to use live table
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCreate(kEvent $event)
{
if ( $this->Application->GetVar($event->Prefix . '_label') ) {
$object = $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
if ( $this->Application->GetVar('m_lang') != $this->Application->GetVar('lang_id') ) {
$object->SwitchToLive();
}
$this->returnToOriginalTemplate($event);
}
parent::OnCreate($event);
}
/**
* Redirects to original template after phrase is being update
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent $event)
{
if ( $this->Application->GetVar($event->Prefix . '_label') ) {
$this->returnToOriginalTemplate($event);
}
parent::OnUpdate($event);
}
/**
* Returns to original template after phrase adding/editing
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function returnToOriginalTemplate(kEvent $event)
{
$next_template = $this->Application->GetVar('next_template');
if ( $next_template ) {
$event->redirect = $next_template;
$event->SetRedirectParam('opener', 's');
}
}
/**
* Set last change info, when phrase is created
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemCreate(kEvent $event)
{
parent::OnBeforeItemCreate($event);
$object = $event->getObject();
/* @var $object kDBItem */
$primary_language_id = $this->Application->GetDefaultLanguageId();
if ( !$object->GetDBField('l' . $primary_language_id . '_Translation') ) {
// no translation on primary language -> try to copy from other language
$src_languages = Array ('lang_id', 'm_lang'); // editable language, theme language
foreach ($src_languages as $src_language) {
$src_language = $this->Application->GetVar($src_language);
$src_value = $src_language ? $object->GetDBField('l' . $src_language . '_Translation') : false;
if ( $src_value ) {
$object->SetDBField('l' . $primary_language_id . '_Translation', $src_value);
break;
}
}
}
$this->_phraseChanged($event);
}
/**
* Update last change info, when phrase is updated
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemUpdate(kEvent $event)
{
parent::OnBeforeItemUpdate($event);
$this->_phraseChanged($event);
}
/**
* Set's phrase key and last change info, used for phrase updating and loading
*
* @param kEvent $event
*/
function _phraseChanged($event)
{
$object = $event->getObject();
/* @var $object kDBItem */
$label = $object->GetDBField('Phrase');
$object->SetDBField('PhraseKey', mb_strtoupper($label));
$object->SetDBField('PhraseType', $this->_getPhraseType($label));
if ( $this->translationChanged($object) ) {
$object->SetDBField('LastChanged_date', adodb_mktime() );
$object->SetDBField('LastChanged_time', adodb_mktime() );
$object->SetDBField('LastChangeIP', $_SERVER['REMOTE_ADDR']);
}
$this->Application->Session->SetCookie('last_module', $object->GetDBField('Module'));
}
/**
* Returns phrase type, that corresponds given phrase label
*
* @param string $label
* @return int
* @access protected
*/
protected function _getPhraseType($label)
{
$phrase_type_map = Array (
'LU' => Language::PHRASE_TYPE_FRONT,
'LA' => Language::PHRASE_TYPE_ADMIN,
'LC' => Language::PHRASE_TYPE_COMMON
);
$label = mb_strtoupper($label);
$label_prefix = substr($label, 0, 2);
return isset($phrase_type_map[$label_prefix]) ? $phrase_type_map[$label_prefix] : Language::PHRASE_TYPE_COMMON;
}
/**
* Checks, that at least one of phrase's translations was changed
*
* @param kDBItem $object
* @return bool
*/
function translationChanged(&$object)
{
$changed_fields = array_keys( $object->GetChangedFields() );
$translation_fields = Array ('Translation', 'HintTranslation', 'ColumnTranslation');
foreach ($changed_fields as $changed_field) {
$changed_field = preg_replace('/^l[\d]+_/', '', $changed_field);
if ( in_array($changed_field, $translation_fields) ) {
return true;
}
}
return false;
}
/**
* Changes default module to custom (when available)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent $event)
{
parent::OnAfterConfigRead($event);
if ($this->Application->findModule('Name', 'Custom')) {
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Module']['default'] = 'Custom';
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
// make sure, that PrimaryTranslation column always refrers to primary language column
$language_id = $this->Application->GetVar('lang_id');
if (!$language_id) {
$language_id = $this->Application->GetVar('m_lang');
}
$primary_language_id = $this->Application->GetDefaultLanguageId();
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
foreach ($calculated_fields[''] as $field_name => $field_expression) {
$field_expression = str_replace('%5$s', $language_id, $field_expression);
$field_expression = str_replace('%4$s', $primary_language_id, $field_expression);
$calculated_fields[''][$field_name] = $field_expression;
}
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
if ($this->Application->GetVar('regional')) {
$this->Application->setUnitOption($event->Prefix, 'PopulateMlFields', true);
}
}
/**
* Saves changes & changes language
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreSaveAndChangeLanguage(kEvent $event)
{
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if ( $label && !$this->UseTempTables($event) ) {
$phrase_id = $this->_getPhraseId($label);
if ( $phrase_id ) {
$event->CallSubEvent('OnUpdate');
$event->SetRedirectParam('opener', 's');
}
else {
$event->CallSubEvent('OnCreate');
$event->SetRedirectParam('opener', 's');
}
if ( $event->status != kEvent::erSUCCESS ) {
return;
}
$event->SetRedirectParam($event->getPrefixSpecial() . '_event', 'OnPreparePhrase');
$event->SetRedirectParam('pass_events', true);
}
if ( $this->Application->GetVar('simple_mode') ) {
$event->SetRedirectParam('simple_mode', 1);
}
parent::OnPreSaveAndChangeLanguage($event);
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnEdit(kEvent $event)
{
parent::OnEdit($event);
// use language from grid, instead of primary language used by default
$event->SetRedirectParam('m_lang', $this->Application->GetVar('m_lang'));
}
/**
* Stores ids of selected phrases and redirects to export language step 1
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnExportPhrases(kEvent $event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$this->Application->setUnitOption('phrases', 'AutoLoad', false);
$this->StoreSelectedIDs($event);
$this->Application->StoreVar('export_language_ids', $this->Application->GetVar('m_lang'));
$event->setRedirectParams(
Array (
'phrases.export_event' => 'OnNew',
'pass' => 'all,phrases.export',
'export_mode' => $event->Prefix,
)
);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/email_events/email_events_event_handler.php
===================================================================
--- branches/5.2.x/core/units/email_events/email_events_event_handler.php (revision 15464)
+++ branches/5.2.x/core/units/email_events/email_events_event_handler.php (revision 15465)
@@ -1,726 +1,729 @@
<?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.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class EmailEventsEventsHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnFrontOnly' => Array ('self' => 'edit'),
'OnSaveSelected' => Array ('self' => 'view'),
'OnProcessEmailQueue' => Array ('self' => 'add|edit'),
'OnExportEmailEvents' => Array ('self' => 'view'),
'OnSuggestAddress' => Array ('self' => 'add|edit'),
// events only for developers
'OnPreCreate' => Array ('self' => 'debug'),
'OnDelete' => Array ('self' => 'debug'),
'OnDeleteAll' => Array ('self' => 'debug'),
'OnMassDelete' => Array ('self' => 'debug'),
'OnMassApprove' => Array ('self' => 'debug'),
'OnMassDecline' => Array ('self' => 'debug'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Changes permission section to one from REQUEST, not from config
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent $event)
{
$module = $this->Application->GetVar('module');
if ( strlen($module) > 0 ) {
// checking permission when lising module email events in separate section
$module = explode(':', $module, 2);
if ( count($module) == 1 ) {
$main_prefix = $this->Application->findModule('Name', $module[0], 'Var');
}
else {
$exceptions = Array ('Category' => 'c', 'Users' => 'u');
$main_prefix = $exceptions[$module[1]];
}
$section = $this->Application->getUnitOption($main_prefix . '.email', 'PermSection');
$event->setEventParam('PermSection', $section);
}
// checking permission when listing all email events when editing language
return parent::CheckPermission($event);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent $event)
{
parent::SetCustomQuery($event);
$object = $event->getObject();
/* @var $object kDBList */
if ( $event->Special == 'module' ) {
$module = $this->Application->GetVar('module');
$object->addFilter('module_filter', '%1$s.Module = ' . $this->Conn->qstr($module));
}
+ else {
+ $object->addFilter('module_filter', '%1$s.Module IN (SELECT Name FROM ' . TABLE_PREFIX . 'Modules WHERE Loaded = 1)');
+ }
if ( !$event->Special && !$this->Application->isDebugMode() ) {
// no special
$object->addFilter('enabled_filter', '%1$s.Enabled <> ' . STATUS_DISABLED);
}
}
/**
* Prepares new kDBItem object
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnNew(kEvent $event)
{
parent::OnNew($event);
$mapping = Array ('conf' => 'VariableValue', 'site-domain' => 'DefaultEmailRecipients');
if ( isset($mapping[$event->Special]) ) {
$object = $event->getObject();
/* @var $object kDBItem */
$target_object = $this->Application->recallObject($event->Special);
/* @var $target_object kDBList */
$object->SetDBField('Recipients', $target_object->GetDBField($mapping[$event->Special]));
}
}
/**
* Set default headers
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreCreate(kEvent $event)
{
parent::OnPreCreate($event);
$object = $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('Headers', $this->Application->ConfigValue('Smtp_DefaultHeaders'));
$this->setRequired($event);
}
/**
* Sets status Front-End Only to selected email events
*
* @param kEvent $event
*/
function OnFrontOnly($event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$ids = implode(',', $this->StoreSelectedIDs($event));
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'UPDATE ' . $table_name . '
SET FrontEndOnly = 1
WHERE EventId IN (' . $ids . ')';
$this->Conn->Query($sql);
$this->clearSelectedIDs($event);
}
/**
* Sets selected user to email events selected
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSelectUser(kEvent $event)
{
if ( $event->Special != 'module' ) {
parent::OnSelectUser($event);
return;
}
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$items_info = $this->Application->GetVar('u');
if ( $items_info ) {
$user_id = array_shift(array_keys($items_info));
$selected_ids = $this->getSelectedIDs($event, true);
$ids = $this->Application->RecallVar($event->getPrefixSpecial() . '_selected_ids');
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'UPDATE ' . $table_name . '
SET ' . $this->Application->RecallVar('dst_field') . ' = ' . $user_id . '
WHERE ' . $id_field . ' IN (' . $ids . ')';
$this->Conn->Query($sql);
}
$this->finalizePopup($event);
}
/**
* Saves selected ids to session
*
* @param kEvent $event
*/
function OnSaveSelected($event)
{
$this->StoreSelectedIDs($event);
}
/**
* Process emails from queue
*
* @param kEvent $event
* @todo Move to MailingList
*/
function OnProcessEmailQueue($event)
{
$deliver_count = $event->getEventParam('deliver_count');
if ( $deliver_count === false ) {
$deliver_count = $this->Application->ConfigValue('MailingListSendPerStep');
if ( $deliver_count === false ) {
$deliver_count = 10; // 10 emails per script run (if not specified directly)
}
}
$processing_type = $this->Application->GetVar('type');
if ( $processing_type = 'return_progress' ) {
$email_queue_progress = $this->Application->RecallVar('email_queue_progress');
if ( $email_queue_progress === false ) {
$emails_sent = 0;
$sql = 'SELECT COUNT(*)
FROM ' . TABLE_PREFIX . 'EmailQueue
WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ')';
$total_emails = $this->Conn->GetOne($sql);
$this->Application->StoreVar('email_queue_progress', $emails_sent . ':' . $total_emails);
}
else {
list ($emails_sent, $total_emails) = explode(':', $email_queue_progress);
}
}
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'EmailQueue
WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ')
LIMIT 0,' . $deliver_count;
$messages = $this->Conn->Query($sql);
$message_count = count($messages);
if ( !$message_count ) {
// no messages left to send in queue
if ( $processing_type = 'return_progress' ) {
$this->Application->RemoveVar('email_queue_progress');
$this->Application->Redirect($this->Application->GetVar('finish_template'));
}
return;
}
$mailing_list_helper = $this->Application->recallObject('MailingListHelper');
/* @var $mailing_list_helper MailingListHelper */
$mailing_list_helper->processQueue($messages);
if ( $processing_type = 'return_progress' ) {
$emails_sent += $message_count;
if ( $emails_sent >= $total_emails ) {
$this->Application->RemoveVar('email_queue_progress');
$this->Application->Redirect($this->Application->GetVar('finish_template'));
}
$this->Application->StoreVar('email_queue_progress', $emails_sent . ':' . $total_emails);
$event->status = kEvent::erSTOP;
echo ($emails_sent / $total_emails) * 100;
}
}
/**
* Prefills module dropdown
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent $event)
{
parent::OnAfterConfigRead($event);
$options = Array ();
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ( $module_name == 'In-Portal' ) {
continue;
}
$options[$module_name] = $module_name;
}
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Module']['options'] = $options;
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
if ( $this->Application->GetVar('regional') ) {
$this->Application->setUnitOption($event->Prefix, 'PopulateMlFields', true);
}
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnEdit(kEvent $event)
{
parent::OnEdit($event);
// use language from grid, instead of primary language used by default
$event->SetRedirectParam('m_lang', $this->Application->GetVar('m_lang'));
}
/**
* Fixes default recipient type
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemLoad(kEvent $event)
{
parent::OnAfterItemLoad($event);
$object = $event->getObject();
/* @var $object kDBItem */
if ( !$this->Application->isDebugMode(false) ) {
if ( $object->GetDBField('AllowChangingRecipient') ) {
$object->SetDBField('RecipientType', EmailEvent::RECIPIENT_TYPE_TO);
}
else {
$object->SetDBField('RecipientType', EmailEvent::RECIPIENT_TYPE_CC);
}
}
// process replacement tags
$records = Array ();
$replacement_tags = $object->GetDBField('ReplacementTags');
$replacement_tags = $replacement_tags ? unserialize($replacement_tags) : Array ();
foreach ($replacement_tags as $tag => $replacement) {
$records[] = Array ('Tag' => $tag, 'Replacement' => $replacement);
}
$minput_helper = $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$xml = $minput_helper->prepareMInputXML($records, Array ('Tag', 'Replacement'));
$object->SetDBField('ReplacementTagsXML', $xml);
$this->setRequired($event);
}
/**
* Performs custom validation + keep read-only fields
*
* @param kEvent $event
*/
function _itemChanged($event)
{
$object = $event->getObject();
/* @var $object kDBItem */
if ( !$this->Application->isDebugMode(false) ) {
// only allow to enable/disable event while in debug mode
$to_restore = Array ('Enabled', 'AllowChangingSender', 'AllowChangingRecipient');
if ( !$object->GetOriginalField('AllowChangingSender') ) {
$to_restore = array_merge($to_restore, Array ('CustomSender', 'SenderName', 'SenderAddressType', 'SenderAddress'));
}
if ( !$object->GetOriginalField('AllowChangingRecipient') ) {
$to_restore = array_merge($to_restore, Array ('CustomRecipient' /*, 'Recipients'*/));
}
// prevent specific fields from editing
foreach ($to_restore as $restore_field) {
$original_value = $object->GetOriginalField($restore_field);
if ( $object->GetDBField($restore_field) != $original_value ) {
$object->SetDBField($restore_field, $original_value);
}
}
}
// process replacement tags
if ( $object->GetDBField('ReplacementTagsXML') ) {
$minput_helper = $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$replacement_tags = Array ();
$records = $minput_helper->parseMInputXML($object->GetDBField('ReplacementTagsXML'));
foreach ($records as $record) {
$replacement_tags[trim($record['Tag'])] = trim($record['Replacement']);
}
$object->SetDBField('ReplacementTags', $replacement_tags ? serialize($replacement_tags) : NULL);
}
if ( $this->translationChanged($object) ) {
$object->SetDBField('LastChanged_date', TIMENOW);
$object->SetDBField('LastChanged_time', TIMENOW);
}
$this->setRequired($event);
}
/**
* Dynamically changes required fields
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function setRequired(kEvent $event)
{
$object = $event->getObject();
/* @var $object kDBItem */
$language_prefix = 'l' . $this->Application->GetVar('m_lang') . '_';
$object->setRequired($language_prefix . 'HtmlBody', !$object->GetField('PlainTextBody'));
$object->setRequired($language_prefix . 'PlainTextBody', !$object->GetField('HtmlBody'));
}
/**
* Checks, that at least one of phrase's translations was changed
*
* @param kDBItem $object
* @return bool
*/
function translationChanged($object)
{
$changed_fields = array_keys($object->GetChangedFields());
$translation_fields = Array ('Subject', 'HtmlBody', 'PlainTextBody');
foreach ($changed_fields as $changed_field) {
$changed_field = preg_replace('/^l[\d]+_/', '', $changed_field);
if ( in_array($changed_field, $translation_fields) ) {
return true;
}
}
return false;
}
/**
* Don't allow to enable/disable events in non-debug mode
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemCreate(kEvent $event)
{
parent::OnBeforeItemCreate($event);
$this->_itemChanged($event);
}
/**
* Don't allow to enable/disable events in non-debug mode
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemUpdate(kEvent $event)
{
parent::OnBeforeItemUpdate($event);
$this->_itemChanged($event);
}
/**
* Suggest address based on typed address and selected address type
*
* @param kEvent $event
*/
function OnSuggestAddress($event)
{
$event->status = kEvent::erSTOP;
$address_type = $this->Application->GetVar('type');
$address = $this->Application->GetVar('value');
$limit = $this->Application->GetVar('limit');
if ( !$limit ) {
$limit = 20;
}
switch ($address_type) {
case EmailEvent::ADDRESS_TYPE_EMAIL:
$field = 'Email';
$table_name = TABLE_PREFIX . 'Users';
break;
case EmailEvent::ADDRESS_TYPE_USER:
$field = 'Username';
$table_name = TABLE_PREFIX . 'Users';
break;
case EmailEvent::ADDRESS_TYPE_GROUP:
$field = 'Name';
$table_name = TABLE_PREFIX . 'UserGroups';
break;
default:
$field = $table_name = '';
break;
}
if ( $field ) {
$sql = 'SELECT DISTINCT ' . $field . '
FROM ' . $table_name . '
WHERE ' . $field . ' LIKE ' . $this->Conn->qstr($address . '%') . '
ORDER BY ' . $field . ' ASC
LIMIT 0,' . $limit;
$data = $this->Conn->GetCol($sql);
}
else {
$data = Array ();
}
$this->Application->XMLHeader();
echo '<suggestions>';
foreach ($data as $item) {
echo '<item>' . htmlspecialchars($item) . '</item>';
}
echo '</suggestions>';
}
/**
* Does custom validation
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemValidate(kEvent $event)
{
parent::OnBeforeItemValidate($event);
$object = $event->getObject();
/* @var $object kDBItem */
// validate email subject and body for parsing errors
$this->_validateEmailTemplate($object);
// validate sender and recipient addresses
if ( $object->GetDBField('CustomSender') ) {
$this->_validateAddress($event, 'Sender');
}
$this->_validateAddress($event, 'Recipient');
$this->_validateBindEvent($object);
}
/**
* Validates subject and body fields of Email template
*
* @param kDBItem $object
* @return void
* @access protected
*/
protected function _validateEmailTemplate($object)
{
$email_message_helper = $this->Application->recallObject('kEmailMessageHelper');
/* @var $email_message_helper kEmailMessageHelper */
$email_message_helper->parseField($object, 'Subject');
$email_message_helper->parseField($object, 'HtmlBody');
$email_message_helper->parseField($object, 'PlainTextBody');
}
/**
* Validates address using given field prefix
*
* @param kEvent $event
* @param string $field_prefix
* @return void
* @access protected
*/
protected function _validateAddress($event, $field_prefix)
{
$object = $event->getObject();
/* @var $object kDBItem */
$address_type = $object->GetDBField($field_prefix . 'AddressType');
$object->setRequired($field_prefix . 'Address', $address_type > 0);
$address = $object->GetDBField($field_prefix . 'Address');
if ( !$address ) {
// don't validate against empty address
return;
}
switch ($address_type) {
case EmailEvent::ADDRESS_TYPE_EMAIL:
if ( !preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $address) ) {
$object->SetError($field_prefix . 'Address', 'invalid_email');
}
break;
case EmailEvent::ADDRESS_TYPE_USER:
$sql = 'SELECT PortalUserId
FROM ' . TABLE_PREFIX . 'Users
WHERE Username = ' . $this->Conn->qstr($address);
if ( !$this->Conn->GetOne($sql) ) {
$object->SetError($field_prefix . 'Address', 'invalid_user');
}
break;
case EmailEvent::ADDRESS_TYPE_GROUP:
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'UserGroups
WHERE Name = ' . $this->Conn->qstr($address);
if ( !$this->Conn->GetOne($sql) ) {
$object->SetError($field_prefix . 'Address', 'invalid_group');
}
break;
}
}
/**
* Checks that bind event is specified in correct format and exists
*
* @param kDBItem $object
*/
protected function _validateBindEvent($object)
{
$event_string = $object->GetDBField('BindToSystemEvent');
if ( !$event_string ) {
return;
}
try {
$this->Application->eventImplemented(new kEvent($event_string));
}
catch (Exception $e) {
$object->SetError('BindToSystemEvent', 'invalid_event', '+' . $e->getMessage());
}
}
/**
* Stores ids of selected phrases and redirects to export language step 1
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnExportEmailEvents(kEvent $event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$this->Application->setUnitOption('phrases', 'AutoLoad', false);
$this->StoreSelectedIDs($event);
$this->Application->StoreVar('export_language_ids', $this->Application->GetVar('m_lang'));
$event->setRedirectParams(
Array (
'phrases.export_event' => 'OnNew',
'pass' => 'all,phrases.export',
'export_mode' => $event->Prefix,
)
);
}
/**
* Deletes all subscribers to e-mail event after it was deleted
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemDelete(kEvent $event)
{
parent::OnAfterItemDelete($event);
$object = $event->getObject();
/* @var $object kDBItem */
$sql = 'SELECT SubscriptionId
FROM ' . TABLE_PREFIX . 'SystemEventSubscriptions
WHERE EmailEventId = ' . $object->GetID();
$ids = $this->Conn->GetCol($sql);
if ( !$ids ) {
return;
}
$temp_handler = $this->Application->recallObject('system-event-subscription_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems('system-event-subscription', '', $ids);
}
}
\ No newline at end of file

Event Timeline