Index: branches/RC/core/install/install_schema.sql =================================================================== diff -u -N -r11290 -r11319 --- branches/RC/core/install/install_schema.sql (.../install_schema.sql) (revision 11290) +++ branches/RC/core/install/install_schema.sql (.../install_schema.sql) (revision 11319) @@ -87,9 +87,11 @@ Queued int(10) unsigned NOT NULL default '0', SendRetries int(10) unsigned NOT NULL default '0', LastSendRetry int(10) unsigned NOT NULL default '0', + MailingId int(10) unsigned NOT NULL, PRIMARY KEY (EmailQueueId), KEY LastSendRetry (LastSendRetry), - KEY SendRetries (SendRetries) + KEY SendRetries (SendRetries), + KEY MailingId (MailingId) ); CREATE TABLE EmailSubscribers ( Index: branches/RC/core/kernel/utility/email_send.php =================================================================== diff -u -N -r10098 -r11319 --- branches/RC/core/kernel/utility/email_send.php (.../email_send.php) (revision 10098) +++ branches/RC/core/kernel/utility/email_send.php (.../email_send.php) (revision 11319) @@ -1905,7 +1905,7 @@ * Performs mail delivery (supports delayed delivery) * * @param string $mesasge message, if not given, then use composed one - * @param bool $immediate_send send message now + * @param bool $immediate_send send message now or MailingId * @param bool $immediate_clear clear message parts after message is sent * */ @@ -1933,7 +1933,7 @@ } if ($composed) { - if ($immediate_send) { + if ($immediate_send === true) { $send_method = 'Send'.$this->sendMethod; $result = $this->$send_method($message_headers, $message_body); @@ -1949,6 +1949,7 @@ 'Queued' => adodb_mktime(), 'SendRetries' => 0, 'LastSendRetry' => 0, + 'MailingId' => (int)$immediate_send, ); $fields_hash['MessageHeaders'] = serialize($message_headers); $fields_hash['MessageBody'] =& $message_body; @@ -1961,7 +1962,7 @@ } // if not immediate send, then send result is positive :) - return !$immediate_send ? true : false; + return $immediate_send !== true ? true : false; } } Index: branches/RC/core/units/mailing_lists/mailing_list_eh.php =================================================================== diff -u -N --- branches/RC/core/units/mailing_lists/mailing_list_eh.php (revision 0) +++ branches/RC/core/units/mailing_lists/mailing_list_eh.php (revision 11319) @@ -0,0 +1,311 @@ + Array ('self' => 'edit'), + 'OnGenerateEmailQueue' => Array ('self' => true), + 'OnProcessEmailQueue' => Array ('self' => true), + ); + + $this->permMapping = array_merge($this->permMapping, $permissions); + } + + /** + * Prepare recipient list + * + * @param kEvent $event + */ + function OnNew(&$event) + { + parent::OnNew($event); + + $recipient_type = $this->Application->GetVar('mailing_recipient_type'); + if (!$recipient_type) { + return ; + } + + $recipients = $this->Application->GetVar($recipient_type); + if ($recipients) { + $object =& $event->getObject(); + /* @var $object kDBItem */ + + $to = $recipient_type . '_' . implode(';' . $recipient_type . '_', array_keys($recipients)); + + $object->SetDBField('To', $to); + } + } + + /** + * Don't allow to delete mailings in progress + * + * @param kEvent $event + */ + function customProcessing(&$event, $type) + { + if ($event->Name == 'OnMassDelete' && $type == 'before') { + $ids = $event->getEventParam('ids'); + if ($ids) { + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); + + $sql = 'SELECT ' . $id_field . ' + FROM ' . $table_name . ' + WHERE ' . $id_field . ' IN (' . implode(',', $ids) . ') AND Status <> ' . MAILING_LIST_PARTIALLY_PROCESSED; + $allowed_ids = $this->Conn->GetCol($sql); + + $event->setEventParam('ids', $allowed_ids); + } + } + } + + /** + * Delete all realted mails in email queue + * + * @param kEvent $event + */ + function OnAfterItemDelete(&$event) + { + parent::OnAfterItemDelete($event); + + $this->_deleteQueue($event); + + $object =& $event->getObject(); + /* @var $object kDBItem */ + + // delete mailing attachments after mailing is deleted + $attachments = $object->GetField('Attachments', 'file_paths'); + if ($attachments) { + $attachments = explode('|', $attachments); + + foreach ($attachments as $attachment_file) { + if (file_exists($attachment_file)) { + unlink($attachment_file); + } + } + } + } + + /** + * Cancels given mailing and deletes all it's email queue + * + * @param kEvent $event + */ + function OnCancelMailing(&$event) + { + $object =& $event->getObject( Array('skip_autoload' => true) ); + /* @var $object kDBItem */ + + $ids = $this->StoreSelectedIDs($event); + + if ($ids) { + foreach ($ids as $id) { + $object->Load($id); + $object->SetDBField('Status', MAILING_LIST_CANCELLED); + $object->Update(); + } + } + + $this->clearSelectedIDs($event); + } + + /** + * Checks, that at least one message text field is filled + * + * @param kEvent $event + */ + function OnBeforeItemCreate(&$event) + { + parent::OnBeforeItemCreate($event); + + $object =& $event->getObject(); + /* @var $object kDBItem */ + + if (!$this->Application->GetVar('mailing_recipient_type')) { + // user manually typed email addresses -> normalize + $recipients = str_replace(',', ';', $object->GetDBField('To')); + $recipients = array_map('trim', explode(';', $recipients)); + + $object->SetDBField('To', implode(';', $recipients)); + } + + if (!$object->GetDBField('MessageText')) { + $object->setRequired('MessageHtml', true); + } + + // remember user, who created mailing, because of his name + // is needed for "From" field, but mailing occurs from cron + $user_id = $this->Application->RecallVar('user_id'); + $object->SetDBField('PortalUserId', $user_id); + } + + /** + * Deletes mailing list email queue, when it becomes cancelled + * + * @param kEvent $event + */ + function OnAfterItemUpdate(&$event) + { + parent::OnAfterItemUpdate($event); + + $object =& $event->getObject(); + /* @var $object kDBItem */ + + $status = $object->GetDBField('Status'); + if (($status != $object->GetOriginalField('Status')) && ($status == MAILING_LIST_CANCELLED)) { + $this->_deleteQueue($event); + } + } + + /** + * Deletes email queue records related with given mailing list + * + * @param kEvent $event + */ + function _deleteQueue(&$event) + { + $object =& $event->getObject(); + /* @var $object kDBItem */ + + $sql = 'DELETE FROM ' . $this->Application->getUnitOption('email-queue', 'TableName') . ' + WHERE MailingId = ' . $object->GetID(); + $this->Conn->Query($sql); + } + + /** + * Allows to safely get mailing configuration variables + * + * @param string $variable_name + * @return int + */ + function _ensureDefault($variable_name) + { + $value = $this->Application->ConfigValue($variable_name); + if ($value === false) { + // ensure default value, when configuration variable is missing + return 10; + } + + if (!$value) { + // configuration variable found, but it's value is empty or zero + return false; + } + + return $value; + } + + /** + * Generates email queue for active mailing lists + * + * @param kEvent $event + */ + function OnGenerateEmailQueue(&$event) + { + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); + + $where_clause = Array ( + 'Status NOT IN (' . MAILING_LIST_CANCELLED . ',' . MAILING_LIST_PROCESSED . ')', + '(EmailsQueued < EmailsTotal) OR (EmailsTotal = 0)', + '`To` <> ""', + ); + + $sql = 'SELECT * + FROM ' . $table_name . ' + WHERE (' . implode(') AND (', $where_clause) . ') + ORDER BY ' . $id_field . ' ASC'; + $mailing_lists = $this->Conn->Query($sql, $id_field); + if (!$mailing_lists) { + return ; + } + + // queue 10 emails per step summary from all mailing lists (FIFO logic) + $to_queue = $this->_ensureDefault('MailingListQueuePerStep'); + if ($to_queue === false) { + return ; + } + + $mailing_list_helper =& $this->Application->recallObject('MailingListHelper'); + /* @var $mailing_list_helper MailingListHelper */ + + foreach ($mailing_lists as $mailing_id => $mailing_data) { + if ($mailing_data['EmailsTotal'] == 0) { + // no work performed on this mailing list -> calculate totals + $updated_fields = $mailing_list_helper->generateRecipients($mailing_id, $mailing_data); + $updated_fields['Status'] = MAILING_LIST_PARTIALLY_PROCESSED; + $mailing_data = array_merge_recursive2($mailing_data, $updated_fields); + + $this->Conn->doUpdate($updated_fields, $table_name, $id_field . ' = ' . $mailing_id); + } + + $emails = unserialize( $mailing_data['ToParsed'] ); + if (!$emails) { + continue; + } + + // queue allowed count of emails + $i = 0; + $process_count = count($emails) >= $to_queue ? $to_queue : count($emails); + + while ($i < $process_count) { + $mailing_list_helper->queueEmail($emails[$i], $mailing_id, $mailing_data); + $i++; + } + + // remove processed emails from array + $to_queue -= $process_count; // decrement available for processing email count + array_splice($emails, 0, $process_count); + $updated_fields = Array ( + 'ToParsed' => serialize($emails), + 'EmailsQueued' => $mailing_data['EmailsQueued'] + $process_count, + ); + $mailing_data = array_merge_recursive2($mailing_data, $updated_fields); + $this->Conn->doUpdate($updated_fields, $table_name, $id_field . ' = ' . $mailing_id); + + if (!$to_queue) { + // emails to be queued per step reached -> leave + break; + } + } + } + + /** + * Process email queue from cron + * + * @param kEvent $event + */ + function OnProcessEmailQueue(&$event) + { + $deliver_count = $this->_ensureDefault('MailingListSendPerStep'); + if ($deliver_count === false) { + return ; + } + + $queue_table = $this->Application->getUnitOption('email-queue', 'TableName'); + + // get queue part to send + $sql = 'SELECT * + FROM ' . $queue_table . ' + WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ') + LIMIT 0,' . $deliver_count; + $messages = $this->Conn->Query($sql); + + if (!$messages) { + // no more messages left in queue + return ; + } + + $mailing_list_helper =& $this->Application->recallObject('MailingListHelper'); + /* @var $mailing_list_helper MailingListHelper */ + + $mailing_list_helper->processQueue($messages); + } + } \ No newline at end of file Index: branches/RC/core/units/email_queue/email_queue_config.php =================================================================== diff -u -N -r11154 -r11319 --- branches/RC/core/units/email_queue/email_queue_config.php (.../email_queue_config.php) (revision 11154) +++ branches/RC/core/units/email_queue/email_queue_config.php (.../email_queue_config.php) (revision 11319) @@ -28,7 +28,7 @@ 'Sections' => Array ( 'in-portal:email_queue' => Array ( - 'parent' => 'in-portal:email_folder', + 'parent' => 'in-portal:mailing_folder', 'icon' => 'email_log', 'label' => 'la_tab_EmailQueue', 'url' => Array('t' => 'logs/email_logs/email_queue_list', 'pass' => 'm'), @@ -57,6 +57,7 @@ 'Queued' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'not_null' => 1, 'default' => 0), 'SendRetries' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), 'LastSendRetry' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'not_null' => 1, 'default' => 0), + 'MailingId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), ), 'Grids' => Array ( @@ -70,6 +71,7 @@ 'Queued' => Array ('title' => 'la_col_Queued', 'filter_block' => 'grid_date_range_filter', ), 'SendRetries' => Array ('title' => 'la_col_SendRetries', 'filter_block' => 'grid_range_filter', ), 'LastSendRetry' => Array ('title' => 'la_col_LastSendRetry', 'filter_block' => 'grid_date_range_filter', ), + 'MailingId' => Array ('title' => 'la_col_MailingList', 'filter_block' => 'grid_range_filter', ), ), ), ), Index: branches/RC/core/admin_templates/logs/email_logs/email_log_tabs.tpl =================================================================== diff -u -N --- branches/RC/core/admin_templates/logs/email_logs/email_log_tabs.tpl (revision 10842) +++ branches/RC/core/admin_templates/logs/email_logs/email_log_tabs.tpl (revision 0) @@ -1,11 +0,0 @@ - - - - -
- - - - -
-
\ No newline at end of file Index: branches/RC/core/admin_templates/logs/email_logs/email_log_list.tpl =================================================================== diff -u -N -r11226 -r11319 --- branches/RC/core/admin_templates/logs/email_logs/email_log_list.tpl (.../email_log_list.tpl) (revision 11226) +++ branches/RC/core/admin_templates/logs/email_logs/email_log_list.tpl (.../email_log_list.tpl) (revision 11319) @@ -1,6 +1,6 @@ - + Index: branches/RC/core/install/install_data.sql =================================================================== diff -u -N -r11290 -r11319 --- branches/RC/core/install/install_data.sql (.../install_data.sql) (revision 11290) +++ branches/RC/core/install/install_data.sql (.../install_data.sql) (revision 11319) @@ -68,6 +68,8 @@ INSERT INTO ConfigurationAdmin VALUES ('UseOutputCompression', 'la_Text_Website', 'la_config_UseOutputCompression', 'checkbox', '', '', 10.18, 0, 1); INSERT INTO ConfigurationAdmin VALUES ('OutputCompressionLevel', 'la_Text_Website', 'la_config_OutputCompressionLevel', 'text', '', '', 10.19, 0, 1); INSERT INTO ConfigurationAdmin VALUES ('MailFunctionHeaderSeparator', 'la_Text_smtp_server', 'la_config_MailFunctionHeaderSeparator', 'radio', NULL, '1=la_Linux,2=la_Windows', 30.08, 0, 0); +INSERT INTO ConfigurationAdmin VALUES ('MailingListQueuePerStep', 'la_Text_smtp_server', 'la_config_MailingListQueuePerStep', 'text', NULL, NULL, 30.09, 0, 0); +INSERT INTO ConfigurationAdmin VALUES ('MailingListSendPerStep', 'la_Text_smtp_server', 'la_config_MailingListSendPerStep', 'text', NULL, NULL, 30.10, 0, 0); INSERT INTO ConfigurationAdmin VALUES ('UseToolbarLabels', 'la_Text_Website', 'la_config_UseToolbarLabels', 'checkbox', NULL , NULL , 10.20, 0, 0); INSERT INTO ConfigurationAdmin VALUES ('UseSmallHeader', 'la_Text_Website', 'la_config_UseSmallHeader', 'checkbox', '', '', 10.21, 0, 0); INSERT INTO ConfigurationAdmin VALUES ('User_Default_Registration_Country', 'la_Text_General', 'la_config_DefaultRegistrationCountry', 'select', NULL , '=+,SELECT DestName AS OptionName, DestId AS OptionValue FROM StdDestinations WHERE DestParentId IS NULL Order BY OptionName', 10.111, 0, 0); @@ -233,6 +235,8 @@ INSERT INTO ConfigurationValues VALUES (DEFAULT, 'UseOutputCompression', '0', 'In-Portal', 'in-portal:configure_general'); INSERT INTO ConfigurationValues VALUES (DEFAULT, 'OutputCompressionLevel', '7', 'In-Portal', 'in-portal:configure_general'); INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MailFunctionHeaderSeparator', 1, 'In-Portal', 'in-portal:configure_general'); +INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MailingListQueuePerStep', 10, 'In-Portal', 'in-portal:configure_general'); +INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MailingListSendPerStep', 10, 'In-Portal', 'in-portal:configure_general'); INSERT INTO ConfigurationValues VALUES (DEFAULT, 'CategoriesRebuildSerial', '0', 'In-Portal', ''); INSERT INTO ConfigurationValues VALUES (DEFAULT, 'UseToolbarLabels', '1', 'In-Portal', 'in-portal:configure_general'); INSERT INTO ConfigurationValues VALUES (DEFAULT, 'UseSmallHeader', '0', 'In-Portal', 'in-portal:configure_general'); Index: branches/RC/core/units/general/helpers/permissions_helper.php =================================================================== diff -u -N -r11245 -r11319 --- branches/RC/core/units/general/helpers/permissions_helper.php (.../permissions_helper.php) (revision 11245) +++ branches/RC/core/units/general/helpers/permissions_helper.php (.../permissions_helper.php) (revision 11319) @@ -456,9 +456,9 @@ $groups = explode(',', $this->Application->RecallVar('UserGroups')); } else { // checking not current user - $sql = 'SELECT GroupId FROM '.TABLE_PREFIX.'UserGroup - WHERE (PortalUserId = '.$user_id.') AND - ( (MembershipExpires IS NULL) OR ( MembershipExpires >= UNIX_TIMESTAMP() ) )'; + $sql = 'SELECT GroupId + FROM '.TABLE_PREFIX.'UserGroup + WHERE (PortalUserId = '.$user_id.') AND ( (MembershipExpires IS NULL) OR ( MembershipExpires >= UNIX_TIMESTAMP() ) )'; $groups = $this->Conn->GetCol($sql); array_push($groups, $this->Application->ConfigValue('User_LoggedInGroup') ); } @@ -500,8 +500,8 @@ } else { $sql = 'SELECT ParentPath - FROM '.$this->Application->getUnitOption('c', 'TableName').' - WHERE CategoryId = '.$cat_id; + FROM '.$this->Application->getUnitOption('c', 'TableName').' + WHERE CategoryId = '.$cat_id; $cat_hierarchy = $this->Conn->GetOne($sql); } Index: branches/RC/core/admin_templates/users/users_list.tpl =================================================================== diff -u -N -r11205 -r11319 --- branches/RC/core/admin_templates/users/users_list.tpl (.../users_list.tpl) (revision 11205) +++ branches/RC/core/admin_templates/users/users_list.tpl (.../users_list.tpl) (revision 11319) @@ -55,14 +55,28 @@ a_toolbar.AddButton( new ToolBarSeparator('sep2') ); - + /* a_toolbar.AddButton( new ToolBarButton('e-mail', '', function() { set_hidden_field('remove_specials[u.regular]', 1); openSelector('emailmessages', '', 'UserEmail', null, 'OnPrepareMassRecipients'); } ) ); + */ + + + a_toolbar.AddButton( + new ToolBarButton( + 'e-mail', + '', + function() { + Application.SetVar('remove_specials[u.regular]', 1); + Application.SetVar('mailing_recipient_type', 'u'); + openSelector('mailing-list', '', 'UserEmail', null, 'OnNew'); + } + ) + ); a_toolbar.AddButton( new ToolBarButton('export', '', function() { Index: branches/RC/core/units/general/helpers/mailing_list_helper.php =================================================================== diff -u -N --- branches/RC/core/units/general/helpers/mailing_list_helper.php (revision 0) +++ branches/RC/core/units/general/helpers/mailing_list_helper.php (revision 11319) @@ -0,0 +1,270 @@ +Application->recallObject('EmailSender'); + /* @var $esender kEmailSendingHelper */ + + if ($this->_mailingId != $mailing_id) { + if (is_numeric($this->_mailingId)) { + // clear fields after previous mailing processing + $esender->Clear(); + } + + // 1. set headers same for all emails + list ($mailing_data['FromName'], $mailing_data['FromEmail']) = $this->_getSenderData($mailing_data); + $esender->SetFrom($mailing_data['FromEmail'], $mailing_data['FromName']); + + $esender->SetSubject($mailing_data['Subject']); + $esender->SetBody($mailing_data['MessageHtml'], $mailing_data['MessageText']); + + // 2. add attachment if any + $attachments = $mailing_data['Attachments'] ? explode('|', $mailing_data['Attachments']) : Array (); + + foreach ($attachments as $attachment) { + $esender->AddAttachment(FULL_PATH . ITEM_FILES_PATH . $attachment); + } + + $this->_mailingId = $mailing_id; + } + + // 3. set recipient specific fields + $esender->SetEncodedEmailHeader('To', $email, $email); + $esender->Deliver(null, $mailing_id, false); + + // 4. write to log + $log_fields_hash = Array ( + 'fromuser' => $mailing_data['FromName'] . '<' . $mailing_data['FromEmail'] . '>', + 'addressto' => $email, + 'subject' => $mailing_data['Subject'], + 'timestamp' => adodb_mktime(), + 'EventParams' => serialize( Array ('MailingId' => $mailing_id) ), + ); + + $this->Conn->doInsert($log_fields_hash, TABLE_PREFIX . 'EmailLog'); + } + + /** + * Returns mass mail sender name & email + * + * @return Array + */ + function _getSenderData(&$mailing_data) + { + $is_root = true; + if ($mailing_data['PortalUserId'] > 0) { + $sender =& $this->Application->recallObject('u.-item', null, Array ('skip_autoload' => true)); + /* @var $sender UsersItem */ + + $sender->Load($mailing_data['PortalUserId']); + + $email_address = $sender->GetDBField('Email'); + $name = trim( $sender->GetDBField('FirstName') . ' ' . $sender->GetDBField('LastName') ); + $is_root = false; + } + + if ($is_root || !$email_address) { + $email_address = $this->Application->ConfigValue('Smtp_AdminMailFrom'); + } + + if ($is_root || !$name) { + $name = strip_tags( $this->Application->ConfigValue('Site_Name') ); + } + + return Array ($name, $email_address); + } + + /** + * Generates recipients emails based on "To" field value + * + * @param int $id + * @param Array $fields_hash + */ + function generateRecipients($id, $fields_hash) + { + $recipients = explode(';', $fields_hash['To']); + + // 1. group recipients by types + $recipients_grouped = Array (); + foreach ($recipients as $recipient) { + if (strpos($recipient, '_') !== false) { + list ($recipient_type, $recipient_id) = explode('_', $recipient); + } + else { + $recipient_type = 'direct'; + $recipient_id = $recipient; + } + + if (!array_key_exists($recipient_type, $recipients_grouped)) { + $recipients_grouped[$recipient_type] = Array (); + } + + $recipients_grouped[$recipient_type][] = $recipient_id; + } + + // for each group convert ids to names + $recpient_emails = Array (); + foreach ($recipients_grouped as $recipient_type => $group_recipients) { + $recpient_emails = array_merge($recpient_emails, $this->_getRecipientEmails($recipient_type, $group_recipients)); + } + + $recpient_emails = array_unique($recpient_emails); + + return Array ( + 'ToParsed' => serialize($recpient_emails), + 'EmailsTotal' => count($recpient_emails), + ); + } + + function _getRecipientEmails($recipient_type, $recipient_ids) + { + if (strpos($recipient_type, '.') !== false) { + // remove special + list ($recipient_type, ) = explode('.', $recipient_type); + } + + if ($recipient_type != 'u' && $recipient_type != 'g') { + // theese are already emails + return $recipient_ids; + } + + switch ($recipient_type) { + case 'u': + $sql = 'SELECT Email + FROM ' . TABLE_PREFIX . 'PortalUser + WHERE (PortalUserId IN (' . implode(',', $recipient_ids) . ')) AND (Email <> "")'; + break; + + case 'g': + $sql = 'SELECT u.Email + FROM ' . TABLE_PREFIX . 'UserGroup ug + LEFT JOIN ' . TABLE_PREFIX . 'PortalUser u ON u.PortalUserId = ug.PortalUserId + WHERE (ug.GroupId IN (' . implode(',', $recipient_ids) . ')) AND (u.Email <> "")'; + break; + } + + return $this->Conn->GetCol($sql); + } + + function getRecipientNames($recipient_type, $recipient_ids) + { + if (strpos($recipient_type, '.') !== false) { + // remove special + list ($recipient_type, ) = explode('.', $recipient_type); + } + + switch ($recipient_type) { + case 'u': + $title_field = 'Email'; + break; + + case 'g': + $title_field = 'Name'; + break; + + default: + $title_field = false; + break; + } + + if ($title_field === false || !$recipient_ids) { + return $recipient_ids; + } + + $id_field = $this->Application->getUnitOption($recipient_type, 'IDField'); + $table_name = $this->Application->getUnitOption($recipient_type, 'TableName'); + + $sql = 'SELECT ' . $title_field . ' + FROM ' . $table_name . ' + WHERE ' . $id_field . ' IN (' . implode(',', $recipient_ids) . ')'; + return $this->Conn->GetCol($sql); + } + + /** + * Updates information about sent email count based on given totals by mailings + * + * @param Array $mailing_totals + */ + function _updateSentTotals($mailing_totals) + { + if (array_key_exists(0, $mailing_totals)) { + // don't update sent email count for mails queued directly (not via mailing lists) + unset($mailing_totals[0]); + } + + $id_field = $this->Application->getUnitOption('mailing-list', 'IDField'); + $table_name = $this->Application->getUnitOption('mailing-list', 'TableName'); + + // update sent email count for each processed mailing + foreach ($mailing_totals as $mailing_id => $mailing_total) { + $sql = 'UPDATE ' . $table_name . ' + SET EmailsSent = EmailsSent + ' . $mailing_total . ' + WHERE ' . $id_field . ' = ' . $mailing_id; + $this->Conn->Query($sql); + } + + // mark mailings, that were processed completely + $sql = 'UPDATE ' . $table_name . ' + SET Status = ' . MAILING_LIST_PROCESSED . ' + WHERE (Status = ' . MAILING_LIST_PARTIALLY_PROCESSED . ') AND (EmailsSent = EmailsTotal)'; + $this->Conn->Query($sql); + } + + /** + * Sent given messages from email queue + * + * @param Array $messages + */ + function processQueue(&$messages) + { + $esender =& $this->Application->recallObject('EmailSender'); + /* @var $esender kEmailSendingHelper */ + + $queue_table = $this->Application->getUnitOption('email-queue', 'TableName'); + + $i = 0; + $message = Array (); + $mailing_totals = Array (); + $message_count = count($messages); + + while ($i < $message_count) { + $message[0] = unserialize($messages[$i]['MessageHeaders']); + $message[1] =& $messages[$i]['MessageBody']; + $delivered = $esender->Deliver($message, true); // immediate send! + + if ($delivered) { + // send succseeded, delete from queue + $sql = 'DELETE FROM ' . $queue_table . ' + WHERE EmailQueueId = ' . $messages[$i]['EmailQueueId']; + $this->Conn->Query($sql); + + $mailing_id = $messages[$i]['MailingId']; + if (!array_key_exists($mailing_id, $mailing_totals)) { + $mailing_totals[$mailing_id] = 0; + } + $mailing_totals[$mailing_id]++; + } + else { + // send failed, increment retries counter + $sql = 'UPDATE ' . $queue_table . ' + SET SendRetries = SendRetries + 1, LastSendRetry = ' . adodb_mktime() . ' + WHERE EmailQueueId = ' . $messages[$i]['EmailQueueId']; + $this->Conn->Query($sql); + } + $i++; + } + + $this->_updateSentTotals($mailing_totals); + } + } \ No newline at end of file Index: branches/RC/core/kernel/constants.php =================================================================== diff -u -N -r11024 -r11319 --- branches/RC/core/kernel/constants.php (.../constants.php) (revision 11024) +++ branches/RC/core/kernel/constants.php (.../constants.php) (revision 11319) @@ -94,4 +94,10 @@ // place for product file uploads (sort of "/system/images" but for all other files) define('ITEM_FILES_PATH', (defined('WRITEBALE_BASE') ? WRITEBALE_BASE : '/kernel') . '/downloads/'); + + // mailing list statuses + define('MAILING_LIST_NOT_PROCESSED', 1); + define('MAILING_LIST_PARTIALLY_PROCESSED', 2); + define('MAILING_LIST_PROCESSED', 3); + define('MAILING_LIST_CANCELLED', 4); ?> \ No newline at end of file Index: branches/RC/core/install/upgrades.sql =================================================================== diff -u -N -r11290 -r11319 --- branches/RC/core/install/upgrades.sql (.../upgrades.sql) (revision 11290) +++ branches/RC/core/install/upgrades.sql (.../upgrades.sql) (revision 11319) @@ -962,4 +962,14 @@ INSERT INTO StopWords VALUES (90, '~'),(152, 'on'),(157, 'see'),(156, 'put'),(128, 'and'),(154, 'or'),(155, 'other'),(153, 'one'),(126, 'as'),(127, 'at'),(125, 'are'),(91, '!'),(92, '@'),(93, '#'),(94, '$'),(95, '%'),(96, '^'),(97, '&'),(98, '*'),(99, '('),(100, ')'),(101, '-'),(102, '_'),(103, '='),(104, '+'),(105, '['),(106, '{'),(107, ']'),(108, '}'),(109, '\\'),(110, '|'),(111, ';'),(112, ':'),(113, ''''),(114, '"'),(115, '<'),(116, '.'),(117, '>'),(118, '/'),(119, '?'),(120, 'ah'),(121, 'all'),(122, 'also'),(123, 'am'),(124, 'an'),(151, 'of'),(150, 'note'),(149, 'not'),(148, 'no'),(147, 'may'),(146, 'its'),(145, 'it'),(144, 'is'),(143, 'into'),(142, 'in'),(141, 'had'),(140, 'has'),(139, 'have'),(138, 'from'),(137, 'form'),(136, 'for'),(135, 'end'),(134, 'each'),(133, 'can'),(132, 'by'),(130, 'be'),(131, 'but'),(129, 'any'),(158, 'that'),(159, 'the'),(160, 'their'),(161, 'there'),(162, 'these'),(163, 'they'),(164, 'this'),(165, 'through'),(166, 'thus'),(167, 'to'),(168, 'two'),(169, 'too'),(170, 'up'),(171, 'where'),(172, 'which'),(173, 'with'),(174, 'were'),(175, 'was'),(176, 'you'),(177, 'yet'); INSERT INTO ConfigurationAdmin VALUES ('CheckStopWords', 'la_Text_Website', 'la_config_CheckStopWords', 'checkbox', '', '', 10.29, 0, 0); -INSERT INTO ConfigurationValues VALUES (DEFAULT, 'CheckStopWords', '0', 'In-Portal', 'in-portal:configure_general'); \ No newline at end of file +INSERT INTO ConfigurationValues VALUES (DEFAULT, 'CheckStopWords', '0', 'In-Portal', 'in-portal:configure_general'); + +ALTER TABLE EmailQueue + ADD MailingId INT UNSIGNED NOT NULL, + ADD INDEX (MailingId); + +INSERT INTO ConfigurationAdmin VALUES ('MailingListQueuePerStep', 'la_Text_smtp_server', 'la_config_MailingListQueuePerStep', 'text', NULL, NULL, 30.09, 0, 0); +INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MailingListQueuePerStep', 10, 'In-Portal', 'in-portal:configure_general'); + +INSERT INTO ConfigurationAdmin VALUES ('MailingListSendPerStep', 'la_Text_smtp_server', 'la_config_MailingListSendPerStep', 'text', NULL, NULL, 30.10, 0, 0); +INSERT INTO ConfigurationValues VALUES (DEFAULT, 'MailingListSendPerStep', 10, 'In-Portal', 'in-portal:configure_general'); \ No newline at end of file Index: branches/RC/core/admin_templates/mailing_lists/mailing_list_tabs.tpl =================================================================== diff -u -N --- branches/RC/core/admin_templates/mailing_lists/mailing_list_tabs.tpl (revision 0) +++ branches/RC/core/admin_templates/mailing_lists/mailing_list_tabs.tpl (revision 11319) @@ -0,0 +1,11 @@ +
+ + + +
+ + + + +
+
\ No newline at end of file Index: branches/RC/core/admin_templates/mailing_lists/mailing_list_list.tpl =================================================================== diff -u -N --- branches/RC/core/admin_templates/mailing_lists/mailing_list_list.tpl (revision 0) +++ branches/RC/core/admin_templates/mailing_lists/mailing_list_list.tpl (revision 11319) @@ -0,0 +1,78 @@ + + + + + + + + + + + +
+ +
+ + + + \ No newline at end of file Index: branches/RC/core/units/logs/email_logs/email_logs_config.php =================================================================== diff -u -N -r11154 -r11319 --- branches/RC/core/units/logs/email_logs/email_logs_config.php (.../email_logs_config.php) (revision 11154) +++ branches/RC/core/units/logs/email_logs/email_logs_config.php (.../email_logs_config.php) (revision 11319) @@ -27,24 +27,15 @@ 'PermSection' => Array ('main' => 'in-portal:emaillog'), 'Sections' => Array ( - 'in-portal:email_folder' => Array ( + 'in-portal:emaillog' => Array ( 'parent' => 'in-portal:reports', 'icon' => 'email_log', 'label' => 'la_tab_EmailLog', - 'permissions' => Array (), + 'url' => Array('t' => 'logs/email_logs/email_log_list', 'pass' => 'm'), + 'permissions' => Array ('view', 'delete'), 'priority' => 4, 'type' => stTREE, ), - - 'in-portal:emaillog' => Array ( - 'parent' => 'in-portal:email_folder', - 'icon' => 'email_log', - 'label' => 'la_tab_EmailLog', - 'url' => Array('t' => 'logs/email_logs/email_log_list', 'pass' => 'm'), - 'permissions' => Array ('view', 'delete'), - 'priority' => 1, - 'type' => stTAB, - ), ), 'ListSQLs' => Array ( Index: branches/RC/core/units/email_events/email_events_event_handler.php =================================================================== diff -u -N -r10632 -r11319 --- branches/RC/core/units/email_events/email_events_event_handler.php (.../email_events_event_handler.php) (revision 10632) +++ branches/RC/core/units/email_events/email_events_event_handler.php (.../email_events_event_handler.php) (revision 11319) @@ -392,12 +392,13 @@ * 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('Smtp_ProcessEmailsPerStep'); + $deliver_count = $this->Application->ConfigValue('MailingListSendPerStep'); if ($deliver_count === false) { $deliver_count = 10; // 10 emails per script run (if not specified directly) } @@ -409,8 +410,8 @@ if ($email_queue_progress === false) { $emails_sent = 0; $sql = 'SELECT COUNT(*) - FROM '.TABLE_PREFIX.'EmailQueue - WHERE (SendRetries < 5) AND (LastSendRetry < '.(adodb_mktime() - 7200).')'; + 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); } @@ -421,8 +422,8 @@ $sql = 'SELECT * FROM '.TABLE_PREFIX.'EmailQueue - WHERE (SendRetries < 5) AND (LastSendRetry < '.(adodb_mktime() - 7200).') - LIMIT 0,'.$deliver_count; + WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ') + LIMIT 0,' . $deliver_count; $messages = $this->Conn->Query($sql); $message_count = count($messages); @@ -435,37 +436,11 @@ return ; } - $esender =& $this->Application->recallObject('EmailSender'); - /* @var $esender kEmailSendingHelper */ + $mailing_list_helper =& $this->Application->recallObject('MailingListHelper'); + /* @var $mailing_list_helper MailingListHelper */ - $i = 0; - $message = Array (); - while ($i < $message_count) { - $message[0] = unserialize($messages[$i]['MessageHeaders']); - $message[1] =& $messages[$i]['MessageBody']; - $delivered = $esender->Deliver($message, true); // immediate send! + $mailing_list_helper->processQueue($messages); - if ($delivered) { - // send succseeded, delete from queue - $sql = 'DELETE FROM '.TABLE_PREFIX.'EmailQueue - WHERE EmailQueueId = '.$messages[$i]['EmailQueueId']; - $this->Conn->Query($sql); - } - else { - // send failed, increment retries counter - $sql = 'UPDATE '.TABLE_PREFIX.'EmailQueue - SET SendRetries = SendRetries + 1, LastSendRetry = '.adodb_mktime().' - WHERE EmailQueueId = '.$messages[$i]['EmailQueueId']; - $this->Conn->Query($sql); - } - $i++; - } - - $wait_time = $this->Application->ConfigValue('Smtp_StepWaitTime'); - if ($wait_time !== false) { - sleep((int)$wait_time); - } - if ($processing_type = 'return_progress') { $emails_sent += $message_count; if ($emails_sent >= $total_emails) { Index: branches/RC/core/units/email_messages/email_messages_event_handler.php =================================================================== diff -u -N -r10533 -r11319 --- branches/RC/core/units/email_messages/email_messages_event_handler.php (.../email_messages_event_handler.php) (revision 10533) +++ branches/RC/core/units/email_messages/email_messages_event_handler.php (.../email_messages_event_handler.php) (revision 11319) @@ -241,10 +241,11 @@ * Generates email queue using progress bar * * @param kEvent $event + * @todo Move to MailingList */ function OnPrepareEmailQueue(&$event) { - $prepare_count = $this->Application->ConfigValue('Smtp_ProcessEmailsPerStep'); + $prepare_count = $this->Application->ConfigValue('MailingListQueuePerStep'); if ($prepare_count === false) { // 10 recipients per script run (if none defined in config) $prepare_count = 10; Index: branches/RC/core/admin_templates/logs/email_logs/email_queue_list.tpl =================================================================== diff -u -N -r11226 -r11319 --- branches/RC/core/admin_templates/logs/email_logs/email_queue_list.tpl (.../email_queue_list.tpl) (revision 11226) +++ branches/RC/core/admin_templates/logs/email_logs/email_queue_list.tpl (.../email_queue_list.tpl) (revision 11319) @@ -1,6 +1,6 @@ - + Index: branches/RC/core/kernel/db/db_tag_processor.php =================================================================== diff -u -N -r11267 -r11319 --- branches/RC/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 11267) +++ branches/RC/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 11319) @@ -2294,6 +2294,12 @@ return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin); } + /** + * Allows to retrieve given setting from unit config + * + * @param Array $params + * @return mixed + */ function UnitOption($params) { return $this->Application->getUnitOption($this->Prefix, $params['name']); Index: branches/RC/core/admin_templates/groups/groups_list.tpl =================================================================== diff -u -N -r11165 -r11319 --- branches/RC/core/admin_templates/groups/groups_list.tpl (.../groups_list.tpl) (revision 11165) +++ branches/RC/core/admin_templates/groups/groups_list.tpl (.../groups_list.tpl) (revision 11319) @@ -30,13 +30,27 @@ a_toolbar.AddButton( new ToolBarSeparator('sep1') ); - + /* a_toolbar.AddButton( new ToolBarButton('e-mail', '', function() { openSelector('emailmessages', '', 'UserEmail', null, 'OnPrepareMassRecipients'); } ) ); + */ + + + a_toolbar.AddButton( + new ToolBarButton( + 'e-mail', + '', + function() { + Application.SetVar('remove_specials[g.total]', 1); + Application.SetVar('mailing_recipient_type', 'g'); + openSelector('mailing-list', '', 'UserEmail', null, 'OnNew'); + } + ) + ); a_toolbar.AddButton( new ToolBarButton('view', '', function() { Index: branches/RC/core/kernel/utility/unit_config_reader.php =================================================================== diff -u -N -r11273 -r11319 --- branches/RC/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 11273) +++ branches/RC/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 11319) @@ -287,9 +287,9 @@ $this->ValidateConfig($prefix); } } - + $after_event = new kEvent('adm:OnAfterCacheRebuild'); - $this->Application->HandleEvent($after_event); + $this->Application->HandleEvent($after_event); } } Index: branches/RC/core/admin_templates/mailing_lists/mailing_list_edit.tpl =================================================================== diff -u -N --- branches/RC/core/admin_templates/mailing_lists/mailing_list_edit.tpl (revision 0) +++ branches/RC/core/admin_templates/mailing_lists/mailing_list_edit.tpl (revision 11319) @@ -0,0 +1,143 @@ + + + + + + +
+ + + + + +
+ + + + +
+ + + + + + <> + ; + + + + "> + + + + " type="text" name="" id="" value="" tabindex="" size="" maxlength=""> + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + \ No newline at end of file Index: branches/RC/core/units/general/helpers/helpers_config.php =================================================================== diff -u -N -r11107 -r11319 --- branches/RC/core/units/general/helpers/helpers_config.php (.../helpers_config.php) (revision 11107) +++ branches/RC/core/units/general/helpers/helpers_config.php (.../helpers_config.php) (revision 11319) @@ -1,33 +1,34 @@ 'helpers', - 'EventHandlerClass' => Array('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'), + $config = Array ( + 'Prefix' => 'helpers', + 'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'), - 'RegisterClasses' => Array( - Array('pseudo'=>'kMultiLanguageHelper','class'=>'kMultiLanguageHelper','file'=>'multilanguage.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.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' => Array('kHelper')), - Array('pseudo'=>'CountHelper','class'=>'kCountHelper','file'=>'count_helper.php','build_event'=>'','require_classes'=>'kHelper'), + 'RegisterClasses' => Array ( + Array ('pseudo' => 'kMultiLanguageHelper', 'class' => 'kMultiLanguageHelper', 'file' => 'multilanguage.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.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' => Array('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' => Array('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' => 'MailingListHelper', 'class' => 'MailingListHelper', 'file' => 'mailing_list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'), + ), ); \ No newline at end of file Index: branches/RC/core/units/mailing_lists/mailing_list_tp.php =================================================================== diff -u -N --- branches/RC/core/units/mailing_lists/mailing_list_tp.php (revision 0) +++ branches/RC/core/units/mailing_lists/mailing_list_tp.php (revision 11319) @@ -0,0 +1,67 @@ +getObject($params); + /* @var $object kDBItem */ + + $recipients = explode(';', $object->GetDBField('To')); + + // 1. group recipients by types + $recipients_grouped = Array (); + foreach ($recipients as $recipient) { + if (strpos($recipient, '_') !== false) { + list ($recipient_type, $recipient_id) = explode('_', $recipient); + } + else { + $recipient_type = 'direct'; + $recipient_id = $recipient; + } + + if (!array_key_exists($recipient_type, $recipients_grouped)) { + $recipients_grouped[$recipient_type] = Array (); + } + + $recipients_grouped[$recipient_type][] = $recipient_id; + } + + $mailing_list_helper =& $this->Application->recallObject('MailingListHelper'); + /* @var $mailing_list_helper MailingListHelper */ + + // for each group convert ids to names + $recpient_names = Array (); + foreach ($recipients_grouped as $recipient_type => $group_recipients) { + $recpient_names = array_merge($recpient_names, $mailing_list_helper->getRecipientNames($recipient_type, $group_recipients)); + } + + $ret = ''; + $recipient_count = count($recpient_names); + $block_params = $this->prepareTagParams($params); + $block_params['name'] = $params['render_as']; + + foreach ($recpient_names as $recipient_index => $recipient_name) { + $block_params['recipient_name'] = $recipient_name; + $block_params['not_last'] = $recipient_index < $recipient_count - 1; + + $ret .= $this->Application->ParseBlock($block_params); + } + + return $ret; + } + + function IsManualRecipient($params) + { + $external_call = $this->Application->GetVar('mailing_recipient_type'); + + if ($external_call) { + return false; + } + + $object =& $this->getObject($params); + /* @var $object kDBItem */ + + return $object->IsNewItem(); + } + } \ No newline at end of file Index: branches/RC/core/units/mailing_lists/mailing_lists_config.php =================================================================== diff -u -N --- branches/RC/core/units/mailing_lists/mailing_lists_config.php (revision 0) +++ branches/RC/core/units/mailing_lists/mailing_lists_config.php (revision 11319) @@ -0,0 +1,122 @@ + 'mailing-list', + 'ItemClass' => Array ('class' => 'kDBItem', 'file' => '', 'build_event' => 'OnItemBuild'), + 'ListClass' => Array ('class' => 'kDBList', 'file' => '', 'build_event' => 'OnListBuild'), + 'EventHandlerClass' => Array ('class' => 'MailingListEventHandler', 'file' => 'mailing_list_eh.php', 'build_event' => 'OnBuild'), + 'TagProcessorClass' => Array ('class' => 'MailingListTagProcessor', 'file' => 'mailing_list_tp.php', 'build_event' => 'OnBuild'), + + 'AutoLoad' => true, + + 'QueryString' => Array ( + 1 => 'id', + 2 => 'Page', + 3 => 'event', + 4 => 'mode', + ), + + 'RegularEvents' => Array ( + 'generate_mailing_queue' => Array ('EventName' => 'OnGenerateEmailQueue', 'RunInterval' => 1800, 'Type' => reAFTER), + 'process_mailing_queue' => Array ('EventName' => 'OnProcessEmailQueue', 'RunInterval' => 1800, 'Type' => reAFTER), + ), + + 'IDField' => 'MailingId', + + 'TableName' => TABLE_PREFIX . 'MailingLists', + + 'TitlePresets' => Array ( + 'default' => Array ( + 'new_status_labels' => Array ('mailing-list' => '!la_title_AddingMailingList!'), + 'edit_status_labels' => Array ('mailing-list' => '!la_title_ViewingMailingList!'), + ), + + 'mailing_list_list' => Array ('prefixes' => Array ('mailing-list_List'), 'format' => "!la_title_MailingLists! (#mailing-list_recordcount#)"), + 'mailing_list_edit' => Array ('prefixes' => Array ('mailing-list'), 'format' => "#mailing-list_status#"), + ), + + 'PermSection' => Array('main' => 'in-portal:mailing_lists'), + + 'Sections' => Array ( + 'in-portal:mailing_folder' => Array ( + 'parent' => 'in-portal:users', + 'icon' => 'custom', + 'label' => 'la_title_MailingLists', + 'permissions' => Array (), + 'priority' => 3.1, + 'type' => stTREE, + ), + + 'in-portal:mailing_lists' => Array ( + 'parent' => 'in-portal:mailing_folder', + 'icon' => 'custom', + 'label' => 'la_title_MailingLists', + 'url' => Array('t' => 'mailing_lists/mailing_list_list', 'pass' => 'm'), + 'permissions' => Array('view', 'add', 'edit', 'delete'), + 'priority' => 1, + 'type' => stTAB, + ), + ), + + 'ListSQLs' => Array ( + '' => ' SELECT %1$s.* %2$s FROM %1$s', + ), + + 'ListSortings' => Array ( + '' => Array ( + 'Sorting' => Array ('MailingId' => 'desc'), + ) + ), + + 'Fields' => Array ( + 'MailingId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), + + 'PortalUserId' => Array( + 'type' => 'int', + 'formatter' => 'kLEFTFormatter', + 'options' => Array (-1 => 'root'), + 'left_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'PortalUser WHERE `%s` = \'%s\'', 'left_key_field' => 'PortalUserId', 'left_title_field' => 'Login', + 'required' => 1, 'not_null' => 1, 'default' => -1, + ), + + 'To' => Array ('type' => 'string', 'required' => 1, 'default' => NULL), + 'ToParsed' => Array ('type' => 'string', 'default' => NULL), + + 'Attachments' => Array ( + 'type' => 'string', + 'formatter' => 'kUploadFormatter', 'upload_dir' => ITEM_FILES_PATH, 'max_size' => 50000000, + 'multiple' => 10, 'direct_links' => true, 'file_types' => '*.*', 'files_description' => 'All Files', + 'default' => NULL + ), + + 'Subject' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'required' => 1, 'default' => ''), + 'MessageText' => Array ('type' => 'string', 'default' => NULL), + 'MessageHtml' => Array ('type' => 'string', 'default' => NULL), + + 'Status' => Array ( + 'type' => 'int', + 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_opt_NotProcessed', 2 => 'la_opt_PartiallyProcessed', 3 => 'la_opt_Processed', 4 => 'la_opt_Cancelled'), 'use_phrases' => 1, + 'not_null' => 1, 'required' => 1, 'default' => 1 + ), + + 'EmailsQueued' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), + 'EmailsSent' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), + 'EmailsTotal' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), + ), + + 'Grids' => Array ( + 'Default' => Array ( + 'Icons' => Array ('default' => 'icon16_custom.gif'), + 'Fields' => Array ( + 'MailingId' => Array ('title' => 'la_col_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', ), + 'Subject' => Array ('title' => 'la_col_Subject', 'filter_block' => 'grid_like_filter', ), + 'MessageText' => Array ('title' => 'la_col_MessageText', 'filter_block' => 'grid_like_filter', 'cut_first' => 100), + 'MessageHtml' => Array ('title' => 'la_col_MessageHtml', 'filter_block' => 'grid_like_filter', 'cut_first' => 100), + 'Status' => Array ('title' => 'la_col_Status', 'filter_block' => 'grid_options_filter',), + 'EmailsQueued' => Array ('title' => 'la_col_EmailsQueued', 'filter_block' => 'grid_range_filter',), + 'EmailsSent' => Array ('title' => 'la_col_EmailsSent', 'filter_block' => 'grid_range_filter',), + 'EmailsTotal' => Array ('title' => 'la_col_EmailsTotal', 'filter_block' => 'grid_range_filter',), + ), + ), + ), + ); \ No newline at end of file