Index: branches/5.2.x/core/units/email_events/email_events_event_handler.php =================================================================== diff -u -N --- branches/5.2.x/core/units/email_events/email_events_event_handler.php (revision 15601) +++ branches/5.2.x/core/units/email_events/email_events_event_handler.php (revision 0) @@ -1,756 +0,0 @@ - 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'), - 'OnSend' => 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 ) { - list ($user_id, ) = each($items_info); - - $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 ''; - - foreach ($data as $item) { - echo '' . htmlspecialchars($item, null, CHARSET) . ''; - } - - echo ''; - } - - /** - * 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); - } - - /** - * Sends selected e-mail event - * - * @param kEvent $event - * @return void - * @access protected - */ - protected function OnSend(kEvent $event) - { - $object = $event->getObject(Array ('skip_autoload' => true)); - /* @var $object kDBItem */ - - $ids = $this->StoreSelectedIDs($event); - - foreach ($ids as $id) { - $object->Load($id); - - if ( $object->GetDBField('Type') == EmailEvent::EVENT_TYPE_ADMIN ) { - $this->Application->EmailEventAdmin($object->GetDBField('Event')); - } - else { - $this->Application->EmailEventUser($object->GetDBField('Event')); - } - } - - $this->clearSelectedIDs($event); - } - } \ No newline at end of file