t('Views mail configuration'), 'description' => t('Configure Views Mail for sending of e-mails using Views. Also review and clear logs.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('views_mail_settings'), 'access callback' => 'user_access', 'access arguments' => array('administer views mail'), ); $items['admin/settings/views_mail/settings'] = array( 'title' => t('Settings'), 'description' => t('Configure Views Mail settings.'), 'weight' => 10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/settings/views_mail/logs'] = array( 'title' => t('Views Mail log views'), 'page callback' => 'drupal_get_form', 'page arguments' => array('views_mail_logs'), 'access callback' => 'user_access', 'access arguments' => array('administer views mail'), 'weight' => 20, 'type' => MENU_LOCAL_TASK, ); $items['admin/settings/views_mail/logs/view/%'] = array( 'title' => t('Log viewer'), 'page callback' => 'views_mail_logs_view', 'access callback' => 'user_access', 'access arguments' => array('administer views mail'), 'weight' => 10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/settings/views_mail/clear'] = array( 'title' => t('Clear Views Mail sent log'), 'page callback' => 'drupal_get_form', 'page arguments' => array('views_mail_clear_logs_confirm'), 'access callback' => 'user_access', 'access arguments' => array('administer views mail'), 'weight' => 30, 'type' => MENU_LOCAL_TASK, ); $items['views_mail'] = array( 'title' => t('Views Mail processing'), 'page callback' => 'drupal_get_form', 'page arguments' => array('views_mail_select_view'), 'access callback' => 'user_access', 'access arguments' => array('send views mail'), ); $items['views_mail/user'] = array( 'title' => t('Confirm Views Mail removal'), 'page callback' => 'views_mail_remove', 'access callback' => 'user_access', 'access arguments' => array('unsubscribe from views mail'), 'type' => MENU_CALLBACK, ); $items['views_mail/view/%'] = array( 'title' => t('Select recipients'), 'page callback' => 'views_mail_view_view', 'access callback' => 'user_access', 'access arguments' => array('send views mail'), 'weight' => 11, 'type' => MENU_LOCAL_TASK, ); $items['views_mail/config/%'] = array( 'title' => t('Configure mailing'), 'page callback' => 'drupal_get_form', 'page arguments' => array('views_mail_view_configure'), 'access callback' => 'user_access', 'access arguments' => array('send views mail'), 'weight' => 12, 'type' => MENU_LOCAL_TASK, ); $items['views_mail/confirm/%'] = array( 'title' => t('Confirm mailing'), 'page callback' => 'drupal_get_form', 'page arguments' => array('views_mail_view_confirm'), 'access callback' => 'user_access', 'access arguments' => array('send views mail'), 'weight' => 20, 'type' => MENU_LOCAL_TASK, ); return $items; } /** * Prepare a list of newsletters for default selection. */ function views_mail_default_newsletters() { $options = array(); $res = db_query("SELECT {term_data}.tid,{term_data}.name FROM {term_data} INNER JOIN {vocabulary} ON {term_data}.vid = {vocabulary}.vid WHERE {vocabulary}.module = 'simplenews' ORDER BY {term_data}.name"); while ($view = db_fetch_object($res)) { $options[$view->tid] = $view->name; } return $options; } /** * Prepare a list of views that contain the views_mail tag for default selection. */ function views_mail_view_list() { $options = array(); // $res = db_query("SELECT name,description FROM {views_view} WHERE tag LIKE '%views_mail%' ORDER BY description"); $res = db_query("SELECT name,description FROM {views_view} WHERE tag = 'views_mail' ORDER BY description"); while ($view = db_fetch_object($res)) { $options[$view->name] = $view->description; } return $options; } /** * Select the view to use. */ function views_mail_select_view() { if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('Views Mail is running in debug mode.'); // DEBUG } $form['views_mail_view'] = array( '#type' => 'select', '#title' => t('Select view'), '#options' => views_mail_view_list(), '#description' => t('Select the view to use in order to generate the list of users to send e-mail to.'), '#required' => TRUE, ); $form['submit'] = array('#type' => 'submit', '#value' => t('Continue')); return $form; } /** * Process Views Mail select form submission. */ function views_mail_select_view_submit($form, &$form_state) { $view = $form_state['values']['views_mail_view']; $query = ""; $_SESSION['views_mail'][$view]['gid'] = 0; // This is designed to set the group context if it is present. if (isset($_REQUEST['gids'])) { $gids = $_GET['gids']; $gid = intval(current($_REQUEST['gids'])); $_SESSION['views_mail'][$view]['gid'] = $gid; $query = 'gids[]='.$gid; } drupal_goto('views_mail/view/'.$view, $query); } /** * Display view and use exposed filters to select the e-mail list you wish * wish to send to. */ function views_mail_view_view() { if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('Views Mail is running in debug mode.'); // DEBUG } $viewname = arg(2); // Create the embedded view $view = views_mail_embed_view($viewname, 'default', 'views_mail/view/'.$viewname); $args = $_SESSION['views_mail'][$viewname]['args']; drupal_set_message('Use the exposed filters below to select the list of e-mail addresses that you wish to send to. Once you see the desired list of recipients on this screen, then you may proceed by clicking on the '.l(t('Configure mailing'), "views_mail/config/$viewname", array('query' => "$args")).' tab. Do NOT continue on unless the list you see on this page contains the e-mail addresses to which you wish to send your message.'); // Set group context if (module_exists('og')) { // If gids[] are present, user is attempting to set the group, so // do that here. Note that the group session is also saved at the top // when the user selects the view. if (isset($_REQUEST['gids'])) { $gids = $_GET['gids']; $gid = intval(current($_REQUEST['gids'])); $_SESSION['views_mail'][$viewname]['gid'] = $gid; } // If group is set, then apply group context if ($_SESSION['views_mail'][$viewname]['gid'] > 0) { $gids = $_GET['gids']; $gid = $_SESSION['views_mail'][$viewname]['gid']; $group_node = node_load($gid); og_set_group_context($group_node); } } return $view; } /** * Configure how e-mail will be sent */ function views_mail_view_configure() { global $user; if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('Views Mail is running in debug mode.'); // DEBUG } drupal_set_message('Configure the mailing: Provide the sender, recipient, newsletter, subject, message and schedule information.'); $viewname = arg(2); $args = $_SESSION['views_mail'][$viewname]['args']; // Set group context if (module_exists('og')) { if ($_SESSION['views_mail'][$viewname]['gid'] > 0) { $gids = $_GET['gids']; $gid = $_SESSION['views_mail'][$viewname]['gid']; $group_node = node_load($gid); og_set_group_context($group_node); } } // If the subject and message variables have been set, then use them. $subject = ''; $message = ''; if (isset($_SESSION['views_mail'][$viewname]['subject'])) $subject = $_SESSION['views_mail'][$viewname]['subject']; if (isset($_SESSION['views_mail'][$viewname]['message'])) $message = $_SESSION['views_mail'][$viewname]['message']; // If the from_name and from_mail variables have been set, then use them. $from_name = $user->name; $from_mail = $user->mail; if (isset($_SESSION['views_mail'][$viewname]['from_name'])) $from_name = $_SESSION['views_mail'][$viewname]['from_name']; if (isset($_SESSION['views_mail'][$viewname]['from_mail'])) $from_mail = $_SESSION['views_mail'][$viewname]['from_mail']; // If the name_field and email_field variables have been set, then use them. $name_field = ''; $email_field = ''; $nid_field = 0; if (isset($_SESSION['views_mail'][$viewname]['name_field'])) $name_field = $_SESSION['views_mail'][$viewname]['name_field']; if (isset($_SESSION['views_mail'][$viewname]['email_field'])) $email_field = $_SESSION['views_mail'][$viewname]['email_field']; if (isset($_SESSION['views_mail'][$viewname]['nid_field'])) $nid_field = $_SESSION['views_mail'][$viewname]['nid_field']; // If the additional_mails variable has been set, then use it. $additional_mails = array(); if (isset($_SESSION['views_mail'][$viewname]['additional_mails'])) $additional_mails = $_SESSION['views_mail'][$viewname]['additional_mails']; // If the newsletter variable has been set, then use it. $newsletter = ''; if (isset($_SESSION['views_mail'][$viewname]['newsletter'])) $name_field = $_SESSION['views_mail'][$viewname]['newsletter']; // If the number and unit variables have been set, then use them. $number = 0; $unit = 86400; if (isset($_SESSION['views_mail'][$viewname]['number'])) $number = $_SESSION['views_mail'][$viewname]['number']; if (isset($_SESSION['views_mail'][$viewname]['unit'])) $unit = $_SESSION['views_mail'][$viewname]['unit']; $count = 0; $view = views_get_view($viewname); // $view->set_arguments($args); $view->set_items_per_page(0); $view->set_display('default'); $view->render(); foreach ($view->result as $result) { $count++; } if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('
'. print_r($view->display['default']->display_options, TRUE) .'
'); // DEBUG } $GLOBALS['current_view'] = &$view; $form['viewname'] = array( '#type' => 'hidden', '#value' => $viewname, ); $form['args'] = array( '#type' => 'hidden', '#value' => $args, ); $form['uid'] = array( '#type' => 'hidden', '#value' => $user->uid, ); $view_list = views_mail_view_list(); $form['viewname'] = array( '#type' => 'textfield', '#title' => 'View title', '#description' => t('The title of the view used for this mailing.'), '#value' => $view_list[$viewname], '#disabled' => TRUE ); $form['count'] = array( '#type' => 'textfield', '#title' => 'View count', '#description' => t('The number of records in this view. Please note that the number of e-mails in your final recipient list may be smaller than the number of view records indicated here. If there are multiple records with the same e-mail address, these records will not be duplicated in the final recipient list. Also, records listed here which contain invalid e-mail addresses will be ignored, as well as the e-mail addresses of users who have opted-out of Views Mail mailings.'), '#value' => $count, '#size' => 10, '#disabled' => TRUE ); $form['from_name'] = array( '#type' => 'textfield', '#title' => t('Sender name'), '#default_value' => $from_name, '#maxlength' => '50', '#required' => TRUE, ); $form['from_mail'] = array( '#type' => 'textfield', '#title' => t('Sender e-mail address'), '#default_value' => $from_mail, '#maxlength' => '60', '#required' => TRUE, ); // This gets the list of fields from the view that has been selected. // I think that the column key is created by combining the // table name and field name. $view_fields = array(); $view_email_fields = array(); foreach ($view->display['default']->display_options['fields'] as $name=>$value) { $field = $value['table'].'_'.$value['field']; $label = $value['label']; $view_fields[$field] = $label; $view_email_fields[$field] = $label; } $none_option[0] = 'None'; $view_fields_nid = array_merge($view_fields, $none_option); if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('view_fields
'. print_r($view_fields, TRUE) .'
'); // DEBUG } $form['name_field'] = array( '#type' => 'select', '#title' => t('Select recipient name field'), '#options' => $view_fields, '#default_value' => $name_field, '#description' => t('Select the field which contains the name of the person to whom the message will be sent.'), '#required' => TRUE, ); $form['email_field'] = array( '#type' => 'select', '#title' => t('Select recipient e-mail field'), '#options' => $view_fields, '#default_value' => $email_field, '#description' => t('Select the field which contains the e-mail address of the person to whom the message will be sent.'), '#required' => TRUE, ); $form['nid_field'] = array( '#type' => 'select', '#title' => t('Select recipient node id field'), '#options' => $view_fields_nid, '#default_value' => $nid_field, '#description' => t('Select the field which contains the node id (\'nid\') of the node record which contains the e-mail address of the person to whom the message will be sent. This is optional.'), '#required' => FALSE, ); $form['newsletter'] = array( '#type' => 'select', '#title' => t('Newsletter to send to this group'), '#default_value' => $newsletter, '#options' => views_mail_newsletters(), '#description' => t('The newsletter that contains the message to be sent. If you are going to enter a custom message below, then select the newsletter that will serve as your newsletter template'), '#required' => TRUE, ); $form['custom'] = array( '#type' => 'fieldset', '#title' => t('Custom message'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('You can enter your own subject line for this e-mail. You can also enter a custom message for this e-mail. If you enter anything into either the subject line or message body below, then these values will be used instead of those from the newsletter issue you have selected above. If you get to the Confirm screen and realize you need to modify text entered here, you must use your browser BACK key to return to this page. If you click on the \'Configure mailing\' tab, everything you entered will be lost.'), ); $form['custom']['subject'] = array( '#type' => 'textfield', '#title' => t('Subject'), '#default_value' => $subject, '#maxlength' => '130', '#description' => t('The subject to use for this e-mail. Leave blank to use the title of the newsletter.'), '#required' => FALSE, ); $form['custom']['views_mail_message'] = array( '#type' => 'textarea', '#title' => t('Message'), '#default_value' => $message, '#rows' => '5', '#required' => FALSE, '#description' => t('The message to use for this e-mail. Leave blank to use the body of the newsletter.'), ); $form['schedule'] = array( '#type' => 'fieldset', '#title' => t('Schedule'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('Set time period to wait before sending this message. If you wish this message to be sent immediately, do not enter anything here -- leave at 0.'), ); $form['schedule']['number'] = array( '#type' => 'textfield', '#title' => t('Number'), '#required' => true, '#size' => 3, '#default_value' => $number, ); $form['schedule']['unit'] = array( '#type' => 'select', '#title' => t('Unit'), '#options' => array( '1' => 'seconds', '60' => 'minutes', '3600' => 'hours', '86400' => 'days', ), '#default_value' => $unit, ); $form['additional'] = array( '#type' => 'fieldset', '#title' => t('Additional e-mail addresses'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('If your view contains additional e-mail address fields to which you would like to send this views mail, you can select them here.'), ); $form['additional']['additional_mails'] = array( '#type' => 'checkboxes', '#title' => t('Additional e-mail addresses'), '#options' => $view_email_fields, '#default_value' => $additional_mails, '#description' => t('Select the fields here which contain the additional e-mail addresses you would like to send this mailing to. Note that if you select the primary e-mail field here (selected above) it will not be duplicated in the mailing. Also note that the primary name field you selected above will be used for the e-mail addresses of all fields selected here. Do not select fields here that do not contain valid e-mail addresses.'), ); $form['submit'] = array('#type' => 'submit', '#value' => t('Continue')); return $form; } /** * Validate the configuration. */ function views_mail_view_configure_validate($form, &$form_state) { $view = $GLOBALS['current_view']; if ($form_state['values']['count'] == 0) { form_set_error('count', t('The view you have selected does not contain any recipients.')); } if (!valid_email_address($form_state['values']['from_mail'])) { form_set_error('from_mail', t('The sender e-mail address you have entered is not valid.')); } $name_field = $form_state['values']['name_field']; $email_field = $form_state['values']['email_field']; $nid_field = $form_state['values']['nid_field']; $additional_mails = $form_state['values']['additional_mails']; $count = views_mail_get_recipients($name_field, $email_field, $nid_field, $additional_mails, $view, TRUE); if ($count == 0) { form_set_error('email_field', t('Either the recipient or one of the additional e-mail fields you have selected does not contain a valid e-mail address.')); } } /** * Process the configuration. */ function views_mail_view_configure_submit($form, &$form_state) { $view = $GLOBALS['current_view']; $args = $_SESSION['views_mail'][$view->name]['args']; $name_field = $form_state['values']['name_field']; $email_field = $form_state['values']['email_field']; $nid_field = $form_state['values']['nid_field']; $additional_mails = $form_state['values']['additional_mails']; // Build the recipient list and store in session. $count = views_mail_get_recipients($name_field, $email_field, $nid_field, $additional_mails, $view, TRUE); $_SESSION['views_mail'][$view->name]['count'] = $count; $_SESSION['views_mail'][$view->name]['from_name'] = $form_state['values']['from_name']; $_SESSION['views_mail'][$view->name]['from_mail'] = $form_state['values']['from_mail']; $_SESSION['views_mail'][$view->name]['name_field'] = $form_state['values']['name_field']; $_SESSION['views_mail'][$view->name]['email_field'] = $form_state['values']['email_field']; $_SESSION['views_mail'][$view->name]['nid_field'] = $form_state['values']['nid_field']; $_SESSION['views_mail'][$view->name]['additional_mails'] = $form_state['values']['additional_mails']; $_SESSION['views_mail'][$view->name]['newsletter'] = $form_state['values']['newsletter']; $nid = $form_state['values']['newsletter']; if (empty($form_state['values']['subject'])) { $_SESSION['views_mail'][$view->name]['subject'] = views_mail_get_node_field($nid, 'title'); } else { $_SESSION['views_mail'][$view->name]['subject'] = $form_state['values']['subject']; } if (empty($form_state['values']['views_mail_message'])) { $_SESSION['views_mail'][$view->name]['message'] = views_mail_get_node_field($nid, 'body'); } else { $_SESSION['views_mail'][$view->name]['message'] = $form_state['values']['views_mail_message']; } $_SESSION['views_mail'][$view->name]['number'] = $form_state['values']['number']; $_SESSION['views_mail'][$view->name]['unit'] = $form_state['values']['unit']; drupal_goto('views_mail/confirm/'.$view->name, $args); } /** * Confirm the configuration. */ function views_mail_view_confirm() { if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('Views Mail is running in debug mode.'); // DEBUG } $viewname = arg(2); // Set group context if (module_exists('og')) { if ($_SESSION['views_mail'][$viewname]['gid'] > 0) { $gids = $_GET['gids']; $gid = $_SESSION['views_mail'][$viewname]['gid']; $group_node = node_load($gid); og_set_group_context($group_node); } } $recipients = $_SESSION['views_mail'][$viewname]['recipients']; $count = $_SESSION['views_mail'][$viewname]['count']; $from_name = $_SESSION['views_mail'][$viewname]['from_name']; $from_mail = $_SESSION['views_mail'][$viewname]['from_mail']; $subject = $_SESSION['views_mail'][$viewname]['subject']; $message = $_SESSION['views_mail'][$viewname]['message']; $number = $_SESSION['views_mail'][$viewname]['number']; $unit = $_SESSION['views_mail'][$viewname]['unit']; $form['confirm'] = array( '#value' => t('Are you sure you want to send this message to these recipients?
Clicking on the Confirm button below will begin the process of sending this mailing.') ); $form['count'] = array( '#type' => 'textfield', '#title' => 'Recipients', '#description' => t('Number of recipients who will be sent this mailing. See the list below. This list does not contain duplicate or invalid e-mail addresses. It also does not contain the e-mail addresses of users who have opted not to receive these types of mailings.'), '#size' => 10, '#value' => $count, '#disabled' => TRUE ); $form['from_name'] = array( '#type' => 'textfield', '#title' => 'Sender name', '#value' => $from_name, '#disabled' => TRUE ); $form['from_mail'] = array( '#type' => 'textfield', '#title' => 'Sender e-mail', '#value' => $from_mail, '#disabled' => TRUE ); $form['subject'] = array( '#type' => 'textfield', '#title' => 'Subject', '#value' => $subject, '#disabled' => TRUE ); $form['message_title'] = array( '#value' => t('Message:') ); $form['message_text'] = array( '#value' => $message ); if ($unit == 1) $value = t('Seconds.'); if ($unit == 60) $value = t('Minutes.'); if ($unit == 3600) $value = t('Hours.'); if ($unit == 86400) $value = t('Days.'); if ($number == 0) { $schedule = 'now'; } else { $schedule = $number.' '.$value; } $form['schedule'] = array( '#type' => 'textfield', '#title' => 'Schedule', '#value' => $schedule, '#description' => t('When to send this mailing.'), '#disabled' => TRUE ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Confirm and send'), ); $form['submit_text'] = array( '#value' => t('Clicking on this button will begin the send process.') ); $form['#suffix'] = views_mail_recipients_table($recipients, 'Recipients ('.$count.')'); return $form; } /** * Process the confirmation. */ function views_mail_view_confirm_submit($form, &$form_state) { global $user; $uid = $user->uid; $viewname = arg(2); $recipients = $_SESSION['views_mail'][$viewname]['recipients']; $count = $_SESSION['views_mail'][$viewname]['count']; $nid = $_SESSION['views_mail'][$viewname]['newsletter']; $filter = $_SESSION['views_mail'][$viewname]['args']; $from_name = $_SESSION['views_mail'][$viewname]['from_name']; $from_mail = $_SESSION['views_mail'][$viewname]['from_mail']; $subject = $_SESSION['views_mail'][$viewname]['subject']; $message = $_SESSION['views_mail'][$viewname]['message']; $number = $_SESSION['views_mail'][$viewname]['number']; $unit = $_SESSION['views_mail'][$viewname]['unit']; $created = time(); if ($number > 0) { $sent = time() + ($number * $unit); } else { $sent = time(); } $status = 0; $vmid = variable_get('views_mail_counter', 0) + 1; variable_set('views_mail_counter', $vmid); // Write views_mail record db_query("INSERT INTO {views_mail} (vmid, uid, nid, created, sent, view, filter, from_name, from_mail, subject, message, status, approved, recipients_scheduled, recipients_sent) VALUES (%d,%d,%d,%d,%d,'%s','%s','%s','%s','%s','%s',%d,%d,%d,0)", $vmid, $uid, $nid, $created, $sent, $viewname, $filter, $from_name, $from_mail, $subject, $message, $status, $approved, $count); // Write recipient records foreach ($recipients as $mail=>$value) { $recipient_name = $value['name']; $recipient_nid = $value['nid']; $recipient_mail = $mail; db_query("INSERT INTO {views_mail_schedule} (vmid, recipient_name, recipient_mail, recipient_nid, status, schedule) VALUES (%d,'%s','%s',%d,%d,%d)", $vmid, $recipient_name, $recipient_mail, $recipient_nid, $status, $sent); } $date = date("F j, Y, g:i a", $sent); $log = 'Mailing scheduled for processing on '.$date.'.
Subject: '.$subject.'
Count: '.$count.' recipients.
VMID: '. $vmid .'.'; drupal_set_message($log); watchdog('views_mail', $log); drupal_goto('views_mail'); } /** * Embed a view using a PHP snippet. * This is copied from the original views_embed_view() function. * * Modified here to set the URL to the current URL. * * This function is meant to be called from PHP snippets, should one wish to * embed a view in a node or something. It's meant to provide the simplest * solution and doesn't really offer a lot of options, but breaking the function * apart is pretty easy, and this provides a worthwhile guide to doing so. * * Note that this function does NOT display the title of the view. If you want * to do that, you will need to do what this function does manually, by * loading the view, getting the preview and then getting $view->get_title(). * * @param $name * The name of the view to embed. * @param $display_id * The display id to embed. If unsure, use 'default', as it will always be * valid. But things like 'page' or 'block' should work here. * @param $path * The $path to use for this embedded view. * @param ... * Any additional args you wish to add */ function views_mail_embed_view($name, $display_id = 'default', $path) { $args = func_get_args(); array_shift($args); // remove $name if (count($args)) { array_shift($args); // remove $display_id } if (count($args)) { array_shift($args); // remove $path } if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('path '.$path); // DEBUG } // Set group context if (module_exists('og')) { // If gids[] are present, user is attempting to set the group, so // do that here. Note that the group session is also saved at the top // when the user selects the view. if (isset($_REQUEST['gids'])) { $gids = $_GET['gids']; $gid = intval(current($_REQUEST['gids'])); $_SESSION['views_mail'][$name]['gid'] = $gid; } // If group is set, then apply group context if ($_SESSION['views_mail'][$name]['gid'] > 0) { $gids = $_GET['gids']; $gid = $_SESSION['views_mail'][$name]['gid']; $group_node = node_load($gid); og_set_group_context($group_node); } } $view = views_get_view($name); if (!$view) { return; } // Override path: http://drupal.org/node/402242 // Sending the path when this is called. $view->override_path = $path; // If this is a views_mail processing view, then store the filter in the session. $query = $_SERVER['QUERY_STRING']; // Get the query $pattern = '/q\=views_mail\/view\/'.$name.'[\&]?/'; $replacement = ''; // Replace the Drupal query with the one which contains the // filter arguments (if any) $query = preg_replace($pattern, $replacement, $query); // Write the filter arguments to this users session. $_SESSION['views_mail'][$name]['args'] = $query; return $view->preview($display_id, $args); } /* * Implementation of hook_boot(). * */ function views_mail_boot() { global $user; if ((!function_exists('arg') || !function_exists('node_load'))) { drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // http://drupal.org/node/273068 } // Set group context if (module_exists('og')) { if (isset($_REQUEST['gids'])) { $gids = $_GET['gids']; $gid = intval(current($_REQUEST['gids'])); $group_node = node_load($gid); og_set_group_context($group_node); } } // If the user clicks on /views_mail/config/, then check // here to see if we know the argument chosen from exposed filters. // If we do, then add it to url (if it isn't already there). if (arg(0) == 'views_mail' && arg(1) == 'config') { $views = views_mail_view_list(); foreach ($views as $view => $title) { if (arg(2) == $view) { $path = 'views_mail/config/'.$view; if (isset($_SERVER['QUERY_STRING'])) { //Remove the 'q=' and change the first & into a ? $query = preg_replace('/^q=([^&]*)&(.*)$/', '\1?\2', $_SERVER['QUERY_STRING']); // The query we want is on the other side of the ? $query_array = explode("?", $query); // drupal_set_message('path : '. $query_array[0]); // drupal_set_message('query : '. $query_array[1]); if (empty($query_array[1])) { // drupal_set_message('empty query'); if (isset($_SESSION['views_mail'][$view]['args'])) { $args = $_SESSION['views_mail'][$view]['args']; if (!empty($args)) { drupal_goto($path, $args); } } } } } } } } /** * Implementation of hook_settings(). * * The Views Mail settings form. * * @return array $form */ function views_mail_settings() { if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('Views Mail is running in debug mode.'); // DEBUG } $form['#suffix'] = $explanation; $form['views_mail_email_default_newsletter'] = array( '#type' => 'select', '#title' => t('Default newsletter series'), '#default_value' => variable_get('views_mail_email_default_newsletter', ''), '#options' => views_mail_default_newsletters(), '#description' => t('The default newsletter series which contains the newsletter issues that Views Mail will select from. You must define a newsletter series for use with Views Mail, even if you will always send custom messages.'), '#required' => TRUE, ); $form['views_mail_force_mail_accept'] = array( '#type' => 'checkbox', '#title' => t('Force group e-mail opt-in'), '#default_value' => variable_get('views_mail_force_mail_accept', 1), '#description' => t('When new user signs up, force the group e-mail opt-in to be checked, even if user unchecks it on signup.') ); $form['views_mail_format_subject'] = array( '#type' => 'checkbox', '#title' => t('Format the subject line of e-mails?'), '#default_value' => variable_get('views_mail_format_subject', 1), '#description' => t('When a newsletter is created, the subject line of the resulting e-mail will be prepended with the name of the newsletter group. Uncheck this box if you want the subject of the e-mail to only contain the title of the saved newsletter.') ); $form['view link settings'] = array( '#type' => 'fieldset', '#title' => t('View Link Settings'), '#description' => t('Place a link on Views Mail views?'), '#collapsible' => true, ); $form['view link settings']['views_mail_view_link'] = array( '#type' => 'checkbox', '#title' => t('Create Views Mail View link?'), '#default_value' => variable_get('views_mail_view_link', 0), '#description' => t('When you tag a View as a Views Mail View (views_mail), do you wish to display a link on the bottom of this view which will take you to the Configure Views Mail mailing screen for this view?') ); $form['node link settings'] = array( '#type' => 'fieldset', '#title' => t('Node Link Settings'), '#description' => t('Place a link on Views Mail newsletter nodes?'), '#collapsible' => true, ); $form['node link settings']['views_mail_link'] = array( '#type' => 'checkbox', '#title' => t('Create Views Mail Node link?'), '#default_value' => variable_get('views_mail_link', 0), '#description' => t('When you create a Views Mail newsletter, do you wish to display a link on the bottom of this newsletter which will take you to the Views Mail view you have created?') ); $form['node link settings']['views_mail_link_og'] = array( '#type' => 'checkbox', '#title' => t('Make the link Organic Groups sensitive?'), '#default_value' => variable_get('views_mail_link_og', 0), '#description' => t('If you check the box above, do you want this link to maintain the current group context if the newsletter node is in an Organic Group?') ); $form['node link settings']['views_mail_link_url'] = array( '#type' => 'textfield', '#title' => t('Views Mail link URL'), '#default_value' => variable_get('views_mail_link_url', 'views_mail'), '#description' => t('Enter the URL to the Views Mail view you have created. Do NOT include the ending \'/\'. Ex: views_mail/view/myviewsmailview or views_mail or http://mywebsite.org/views_mail/view/viewsmailview') ); $form['node link settings']['views_mail_link_url_query'] = array( '#type' => 'textfield', '#title' => t('Views Mail link URL query string'), '#default_value' => variable_get('views_mail_link_url_query', ''), '#description' => t('Enter the URL query to the Views Mail view you have created. This is the part that goes after the question mark \'?\' in a URL. Do NOT include the \'?\'. Ex: tids[]=10') ); $form['node link settings']['views_mail_link_title'] = array( '#type' => 'textfield', '#title' => t('Views Mail link title'), '#default_value' => variable_get('views_mail_link_title', 'Views Mail'), '#description' => t('Enter the title of the link.') ); $form['throttle settings'] = array( '#type' => 'fieldset', '#title' => t('Throttle Settings'), '#collapsible' => true, ); $form['throttle settings']['views_mail_interval'] = array( '#type' => 'textfield', '#title' => t('E-mail send interval?'), '#size' => 5, '#default_value' => variable_get('views_mail_interval', 10), '#description' => t('Enter here the number of seconds between the sending of individual e-mail message in a mailing.') ); $form['throttle settings']['views_mail_cron_throttle'] = array( '#type' => 'textfield', '#title' => t('Number of e-mails to send per cron run?'), '#size' => 5, '#default_value' => variable_get('views_mail_cron_throttle', 20), '#description' => t('The e-mails in a Views Mail mailing are only sent during cron runs. Enter here the maximum number of Views Mail e-mails to send during any particular cron run.') ); $form['table settings'] = array( '#type' => 'fieldset', '#title' => t('Node Table Settings'), '#description' => t('By default, the Views Mail recipient e-mail address is left joined to the node mail field. You can enter here another node field to join to. This will allow you to join your custom node e-mail fields to the recipient table e-mail field for reporting of which addresses have received mailings.
If you are not sure what to do here, do not do anything!'), '#collapsible' => true, '#collapsed' => true, ); $form['table settings']['views_mail_table'] = array( '#type' => 'textfield', '#title' => t('Views Mail table'), '#default_value' => variable_get('views_mail_table', 'node'), '#description' => t('Enter name of the table to use for this custom table setting. By default it is set to node.') ); $form['table settings']['views_mail_left_field'] = array( '#type' => 'textfield', '#title' => t('Views Mail left field'), '#default_value' => variable_get('views_mail_left_field', 'mail'), '#description' => t('Enter the name of the field to left join. By default, it is the mail field of the node table.') ); $form['views_mail_counter'] = array( '#type' => 'textfield', '#size' => 10, '#title' => t('Counter for views_mail table'), '#default_value' => variable_get('views_mail_counter', 0), '#description' => t('This is the counter for the views_mail table. You do not need to set this. It will update itself. It should NOT be set lower than the number of records currently in the table.'), ); $form['clear_logs'] = array( '#type' => 'fieldset', '#title' => t('Clear sent logs'), '#description' => t('Clear the logs of sent records. Delete all Views Mail log information for all mailings that have been sent.'), '#collapsible' => true, '#collapsed' => true, ); $form['clear_logs']['clear'] = array( '#type' => 'submit', '#value' => t('Clear sent logs'), '#submit' => array('views_mail_clear_logs_submit'), ); $form['debug settings'] = array( '#type' => 'fieldset', '#title' => t('Debug mode'), '#collapsible' => true, '#collapsed' => true, ); $form['debug settings']['views_mail_debug'] = array( '#type' => 'checkbox', '#title' => t('Run Views Mail in debug mode?'), '#default_value' => variable_get('views_mail_debug', 0), '#description' => t('If you check this on, then debug info will be displayed on certain screens. This is designed to provide the developers with information about the internal workings of your system. You should only check this on if you know what you are doing or asked to do so by this module\'s developer.') ); return system_settings_form($form); } /** * Display views_mail_log views here. */ function views_mail_logs() { $form['#suffix'] = $explanation; $res = db_query("SELECT name,description FROM {views_view} WHERE tag = 'views_mail_log' ORDER BY description"); while ($view = db_fetch_object($res)) { $form[$view->name] = array( '#type' => 'fieldset', '#title' => t($view->name), '#description' => t($view->description), '#collapsible' => true, '#collapsed' => true, ); $form[$view->name]['viewname'] = array( '#type' => 'hidden', '#value' => $view->name, ); $form[$view->name]['view'] = array( '#type' => 'submit', '#value' => $view->name, '#submit' => array('views_mail_logs_submit'), ); } return $form; } function views_mail_logs_submit($form, &$form_state) { if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('
'. print_r($form, TRUE) .'
'); // DEBUG drupal_set_message('
'. print_r($form_state, TRUE) .'
'); // DEBUG drupal_set_message('Clicked button : '. $form_state['clicked_button']['#value']); } $viewname = $form_state['clicked_button']['#value']; drupal_goto('admin/settings/views_mail/logs/view/'.$viewname); } /** * Display views_mail log tables */ function views_mail_logs_view() { $viewname = arg(5); if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('Views Mail is running in debug mode.'); // DEBUG drupal_set_message('viewname : '.$viewname); // DEBUG } // Create the embedded view $view = views_mail_embed_view($viewname, 'default', 'admin/settings/views_mail/logs/view/'.$viewname); return $view; } /** * Submit callback; clear views_mail logs. * * @ingroup forms */ function views_mail_clear_logs_submit(&$form_state, $form) { drupal_goto('admin/settings/views_mail/clear'); } function views_mail_clear_logs_confirm() { $form = array(); $form['#redirect'] = 'admin/settings/views_mail'; return confirm_form($form, t('Confirm clear Views Mail logs?'), 'admin/settings/views_mail', t('This action will delete all Views Mail logs for mailings that have been sent. This action an not be undone.'), t('Clear the logs'), t('Cancel') ); } function views_mail_clear_logs_confirm_submit($form, $form_state) { db_query("DELETE FROM {views_mail} WHERE status = 1"); db_query("DELETE FROM {views_mail_schedule} WHERE status = 1"); watchdog('views_mail', 'Cleared sent logs.'); drupal_set_message(t('Views Mail logs cleared.')); } /** * Prepare a list of newsletter issues for selection. */ function views_mail_newsletters() { global $user; $options = array(); $newsletter = variable_get('views_mail_email_default_newsletter', ''); // get the newsletter term id if (user_access('send own views mail')) { $res = db_query("SELECT node.nid, node.title FROM {node} INNER JOIN {simplenews_newsletters} ON node.nid = simplenews_newsletters.nid WHERE tid = %d AND uid = %d ORDER BY node.title", $newsletter, $user->uid); } if (user_access('send views mail')) { $res = db_query("SELECT node.nid, node.title FROM {node} INNER JOIN {simplenews_newsletters} ON node.nid = simplenews_newsletters.nid WHERE tid = %d ORDER BY node.title", $newsletter); } while ($view = db_fetch_object($res)) { $options[$view->nid] = $view->title; } return $options; } /** * Get the body of the newsletter for this nid. */ function views_mail_get_node_field($nid, $field) { $output = ""; if (!empty($nid)) { $node = node_load($nid); $output = $node->$field; } return $output; } /** * Create a recipient list from the filtered view. * Store it in session if $build = TRUE. * Return the count of actual emails which will be sent. This number could be less * than the number of view records because we check for valid e-mail addresses * and we do not duplicate e-mail addresses. * * @param $name_field * The key for the name field. * @param $email_field * The key for the email field. * @param $nid_field * The key for the node id field. * @param $view * The view. * @param boolean $build * TRUE or FALSE * If TRUE, store recipient list in $_SESSION['views_mail'][$view->name]['recipients']. * @return * Return count of valid e-mails. */ function views_mail_get_recipients($name_field, $email_field, $nid_field, $additional_mails = array(), $view, $build = TRUE) { $count = 0; $recipients = array(); $_SESSION['views_mail'][$view->name]['recipients'] = array(); if (empty($name_field) || empty($email_field)) { return $count; } if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('name_field : '.$name_field); // DEBUG drupal_set_message('email_field : '.$email_field); // DEBUG drupal_set_message('nid_field : '.$nid_field); // DEBUG } foreach ($view->result as $result) { $email = $result->$email_field; $name = $result->$name_field; if ($nid_field) { $nid = $result->$nid_field; // Looks like this might just be nid instead of node_nid if (!$nid) $nid = $result->nid; } else { $nid = 0; } if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('
'. print_r($result, TRUE) .'
'); // DEBUG } if (valid_email_address($email)) { // See if this user has opted out of receiving emails from us. if (views_mail_accept_mail($email) === TRUE) { $recipients[$email]['name'] = $name; $recipients[$email]['nid'] = $nid; } } // Add additional email addresses if they exist // They will use the name field selected in this record if ($additional_mails) { foreach ($additional_mails as $additional_email_field => $checked) { if ($checked) { $additional_email = $result->$additional_email_field; if (valid_email_address($additional_email)) { // See if this user has opted out of receiving emails from us. if (views_mail_accept_mail($additional_email) === TRUE) { $recipients[$additional_email]['name'] = $name; $recipients[$additional_email]['nid'] = $nid; } } } } } } $count = count($recipients); if ($build == TRUE) { $_SESSION['views_mail'][$view->name]['recipients'] = $recipients; } return $count; } /** * Implementation of hook_user(). * * Provide form element to opt in to content mailouts. */ function views_mail_user($type, $edit, &$user, $category = NULL) { if ($type == 'register' || ($type == 'form' && $category == 'account')) { $form['views_mail'] = array( '#type' => 'fieldset', '#title' => t('Group e-mail settings'), '#weight' => 5, '#collapsible' => TRUE, ); // Force checkbox to default on if this is first time registration; if ($type == 'register') { // If force group email setting, then hide group e-mail settings checkbox on registration // because it will default to "on". $type = 'checkbox'; $opt_in = variable_get("views_mail_force_mail_accept", 0); if ($opt_in == 1) $type = 'hidden'; $form['views_mail']['views_mail_accept'] = array( '#type' => $type, '#title' => t('Accept email'), '#default_value' => 1, '#description' => t('Allow yourself to be included in group e-mails from privileged users. Note that your e-mail address is not made public and that site administrators are able to email you even if you choose not to enable this feature.'), ); } else { $form['views_mail']['views_mail_accept'] = array('#type' => 'checkbox', '#title' => t('Accept email'), '#default_value' => $edit['views_mail_accept'], '#description' => t('Allow yourself to be included in group e-mails from privileged users. Note that your e-mail address is not made public and that site administrators are able to email you even if you choose not to enable this feature.'), ); } return $form; } // end register if if ($type == 'validate') { return array('views_mail_accept' => $edit['views_mail_accept']); } // end validate if if ($type == "insert") { // Subscribe this user to the newsletter if it exists $str = variable_get("views_mail_subscribe_newsletter", ''); if (!empty($str)) { $array = preg_split('/\|/', $str, -1, PREG_SPLIT_NO_EMPTY); // split at the | = newsletter | comment if (!empty($array)) { $newsletter = $array[0]; simplenews_subscribe_user($user->mail, $newsletter, $confirm = FALSE); } // end if } // end if } // end insert if } /** * Accept Mail function * * Pass recipient e-mail address through this function to see if the user has opted * out of receiving e-mails from you. * * @param string $email - e-mail address to check * @return boolean $accept - true or false * */ function views_mail_accept_mail($email) { $accept_mail = TRUE; // First check the user's views_mail_accept status (if this is a user email account) $ooresult = db_query("SELECT uid FROM {users} where mail = '" . $email . "'"); while ($oouid = db_fetch_object($ooresult)) { $account = user_load(array('uid' => $oouid->uid, 'status' => 1)); if (!$account->views_mail_accept) { $accept_mail = FALSE; } if (variable_get("views_mail_force_mail_accept", 0) == 1) $accept_mail = TRUE; } // Run through opt-out email list $optout = views_mail_check_optout($email); if ($optout) $accept_mail = FALSE; return $accept_mail; } /** * Make a list of recipients. * * TODO: Sort is really funky. Need to do something about it. * * @param $recipients * The recipients array. * @param $title * (optional) Title to pass on to theme_item_list(). * * @ingroup themeable */ function views_mail_recipients_list($recipients, $title = NULL) { if (!empty($recipients)) { foreach ($recipients as $email=>$name) { $items[] = $name; } } return theme('item_list', $items, $title); } /** * Theme the recipient list as a table. */ function views_mail_recipients_table($recipients, $title = NULL) { $headers = array( array( 'data'=> t('Name'), 'field'=> 'name', 'sort'=> 'asc', ), array( 'data'=> t('Mail'), 'field'=> 'email', ), array( 'data'=> t('Node id'), 'field'=> 'nid', ), ); asort($recipients); if (!empty($recipients)) { foreach ($recipients as $email=>$value) { $items[] = array($value['name'], $email, $value['nid']); } } return '

'.$title.'

' . theme('table', $headers, $items); } /** * Send views_mail scheduled e-mails. * * If sending is succesful, the schedule record is updated with status = 1. * If sending is not successful, the schedule record status is not updated. */ function views_mail_send($views_mail = NULL) { if (!empty($views_mail)) { // Get the e-mail send "interval" throttle setting $sleep = variable_get('views_mail_interval', 10); // Send any pending messages from views_mail_schedule which are scheduled // to be sent. $count = 0; $now = time(); $result = db_query('SELECT * FROM {views_mail_schedule} WHERE schedule <= %d AND status = 0 AND vmid = %d', $now, $views_mail->vmid); while ($schedule = db_fetch_object($result)) { $mail_sent = array(); // Get subscription data for recipient and language $account = new stdClass(); $account->mail = $schedule->recipient_mail; $subscription = simplenews_get_subscription($account); $subscription->name = $schedule->recipient_name; $params['context']['account'] = $subscription; // Get node data for the mail $node = node_load(array('nid' => $views_mail->nid)); // Load subject and message into $node, in case they are different $node->subject = $views_mail->subject; $node->message = $views_mail->message; // I think this is more appropriate $node->title = $views_mail->subject; $node->body = $views_mail->message; // Get from address object $params['from'] = views_mail_format_email($views_mail->from_name, $views_mail->from_mail); $params['context']['node'] = $node; // Send mail if (module_exists('mimemail')) { // If mimemail module is installed ALL emails are send via this module. // drupal_mail() builds the content of the email but does NOT send. $message = drupal_mail('views_mail', 'node', $subscription->mail, $subscription->language, $params, $params['from']['formatted'], FALSE); $plain = $message['params']['context']['node']->simplenews['s_format'] == 'plain'; $message['result'] = mimemail( $message['from'], $message['to'], $message['subject'], $message['body'], $plain, $message['headers'], $plain ? $message['body'] : simplenews_html_to_text($message['body']), isset($message['params']['context']['node']->files) ? $message['params']['context']['node']->files : array(), '' ); } else { $message = drupal_mail('views_mail', 'node', $subscription->mail, $subscription->language, $params, $params['from']['address'], TRUE); } // Log sent message. if (module_exists('mimemail')) { $via_mimemail = t(' | Sent via Mime Mail'); } if ($message['result']) { watchdog('views_mail', 'Outgoing email. VMID: %vmid. Message type: %type
Subject: %subject
Recipient: %to %mimemail', array('%vmid' => $views_mail->vmid, '%type' => 'node', '%to' => $message['to'], '%subject' => $message['subject'], '%mimemail' => $via_mimemail), WATCHDOG_NOTICE); $count++; } else { watchdog('views_mail', 'Outgoing email failed. VMID: %vmid. Message type: %type
Subject: %subject
Recipient: %to %mimemail', array('%vmid' => $views_mail->vmid, '%type' => 'node', '%to' => $message['to'], '%subject' => $message['subject'], '%mimemail' => $via_mimemail), WATCHDOG_ERROR); } // If send is successful, then update the record: // Set status to 1 if successful. if ($message['result']) { db_query("UPDATE {views_mail_schedule} SET status = 1 WHERE vmid = %d AND recipient_mail = '%s'", $schedule->vmid, $schedule->recipient_mail); } // Wait the appropriate number of "interval" seconds before proceeding. sleep($sleep); } // end while // Update the views_mail table indicating these scheduled records have // been sent (or, an attempt was made to send them) with date sent. db_query("UPDATE {views_mail} SET status = 1, sent = %d, recipients_sent = %d WHERE vmid = %d", $now, $count, $views_mail->vmid); } // end if } /** * Implementation of hook_mail(). * * Send views_mail mails using drupal mail API * @see drupal_mail() * * @param $key: node * @param array $message message array * [from] * [headers][From] * [language] : preferred message language * @param array $params parameter array * [context][node] : node object of message to be send * [context][snid] : used for $key = subscribe or unsubscribe * [context][from_name] : name of mail sender or site name (optional) * [context][account] : account details of recipient * [from] : array('address' => 'noreply@example.org', 'formatted' => 'site name ') * [newsletter] : newsletter object (tid, name) * [tokens] : tokens for variable replacement. Defaults to: user_mail_tokens() */ function views_mail_mail($key, &$message, $params) { $context = $params['context']; switch ($key) { case 'node': // Message header, body and mail headers are buffered to increase // perfomance when sending multiple mails. Buffered data only contains // general data, no recipient specific content. Placeholders are used // for recipient data and will later be replaced. // When mailing multiple newsletters in one page call or cron run, // data is once stored and subsequently retreived from the // static $messages variable. // $message buffer is node and language specific. static $messages = array(); static $title; static $body; // By default the the node is send which is supplied in the function call. // When translation is used, the availability of translations is checked // and when available the translation of the preferred language is selected. $nid = $context['node']->nid; // Get the subject and message which is sent in the function call. // Use these in case node has to be re-loaded. $title = $context['node']->title; $body = $context['node']->body; if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('hook_mail title : '.$title); // DEBUG drupal_set_message('hook_mail body : '.$body); // DEBUG } $langcode = $message['language']->language; if (module_exists('translation')) { // If the node has translations and a translation is required // the equivalent of the node in the required langugage is used // or the base node (nid == tnid) is used. if ($tnid = $context['node']->tnid) { if ($langcode != $context['node']->language) { $translations = translation_node_get_translations($tnid); // A translation is available in the preferred language. if ($translation = $translations[$langcode]) { $nid = $translation->nid; $langcode = $translation->language; } else { // No translation found which matches the preferred language. foreach ($translations as $translation) { if ($translation->nid == $tnid) { $nid = $tnid; $langcode = $translation->language; break; } } } } } // If a translation of the node is used and this node is not available in // the message buffer, then load this node. if ($nid != $context['node']->nid && !isset($messages[$nid][$langcode])) { $context['node'] = node_load($nid); // Reset subject and message to those sent in function call. $context['node']->title = $title; $context['node']->body = $body; } } // Check if this node-language pair has been buffered. // If not, build the message and store it for later use. if (!isset($messages[$nid][$langcode])) { $node = $context['node']; // Add simplenews specific header data $headers = array_merge($message['headers'], _simplenews_headers($node, $params['from']['address'])); $headers['From'] = $params['from']['formatted']; $message['headers'] = $messages[$nid][$langcode]['headers'] = $headers; // Build email subject if ($tid = $node->simplenews['tid']) { $term = taxonomy_get_term($tid); // Translate the newsletter term name if simplenews vocabulary uses Localized terms. if (module_exists('i18ntaxonomy') && i18ntaxonomy_vocabulary(variable_get('simplenews_vid', '')) == I18N_TAXONOMY_LOCALIZE) { $name = check_plain(tt('taxonomy:term:'. $tid .':name', $term->name, $langcode)); } else { $name = check_plain($term->name); } } else { $name = t('Unassigned newsletter'); } // Theme newsletter subject $subject = theme('simplenews_newsletter_subject', $name, check_plain($node->title), $message['language']); $subject = str_replace(array("\r", "\n"), '', $subject); $message['subject'] = $messages[$nid][$langcode]['subject'] = $subject; // Unformat subject line if settings require. if (variable_get('views_mail_format_subject', 1) == 0) { $message['subject'] = $messages[$nid][$langcode]['subject'] = check_plain($node->title); } // Build message body // Processing node body mimics node_view() with full node view $node = node_build_content($node, FALSE, TRUE); $content = drupal_render($node->content); $node->body = $content; unset($node->teaser); node_invoke_nodeapi($node, 'alter', FALSE, TRUE); $body = theme('simplenews_newsletter_body', $node->body, check_plain($node->title), $message['language']); // Buffer body text node and language specific $messages[$nid][$langcode]['body'] = $body; } else { // Get message data from buffer $message['headers'] = $messages[$nid][$langcode]['headers']; $message['subject'] = $messages[$nid][$langcode]['subject']; $body = $messages[$nid][$langcode]['body']; } // Build message body. // The placeholders are replaced with user specific data // before conversion to plain text. $variables = user_mail_tokens($context['account'], $context['account']->language); $body = strtr($body, $variables); if ($context['node']->simplenews['s_format'] == 'plain') { $body = simplenews_html_to_text($body); } $message['body']['body'] = $body; // Build message footer. if ($key == 'node' && isset($context['account']->snid)) { $hash = _views_mail_generate_hash($context['account']->mail, $context['node']->nid); // $hash = _simplenews_generate_hash($context['account']->mail, $context['account']->snid, $context['node']->simplenews['tid']); } else { $hash = ''; } $message['body']['footer'] = views_mail_newsletter_footer($context['node']->simplenews['s_format'], $hash, $message['language']); // $message['body']['footer'] = theme('simplenews_newsletter_footer', $context['node']->simplenews['s_format'], $hash, $key == 'test', $message['language']); // Add user specific header data. $message['headers']['List-Unsubscribe'] = '<'. url('views_mail/user/remove/'. $hash, array('absolute' => TRUE)) .'>'; break; } } /** * Build formatted from-name and email for a mail object. * * @param string: $name Name * * @param string: $address E-mail address * * @return array [address] = from address; [formatted] = formatted from name and address */ function views_mail_format_email($name = NULL, $address) { return array( 'address' => $address, 'formatted' => '"'. mime_header_encode(check_plain($name)) .'" <'. $address .'>', ); } /** * Implementation of hook_cron(). * This is used to send the schedule e-mails and update the views_mail log. */ function views_mail_cron() { $clear_cache = FALSE; $count = 0; $result = db_query("SELECT * FROM {views_mail} WHERE status = 0"); while ($views_mail = db_fetch_object($result)) { $count++; // Throttle check if ($count > variable_get('views_mail_cron_throttle', 20)) { break; } else { views_mail_send($views_mail); $clear_cache = TRUE; } } if ($clear_cache) { // clear the cache so an anonymous poster can see any changes cache_clear_all(); } } /** * Helper function to generate the hash key used for subscribe/unsubscribe link * in e-mail footer. */ function _views_mail_generate_hash($mail, $nid) { return drupal_substr(md5($mail . views_mail_private_key()), 0, 10) . $nid .'t'. $mail; } function views_mail_private_key() { $key = variable_get('views_mail_private_key', FALSE); if (!$key) { // This will create a 32 character identifier (a 128 bit hex number) that is extremely difficult to predict $key = md5(uniqid(rand())); variable_set('views_mail_private_key', $key); } return $key; } /** * Theme the newsletter message footer. */ function views_mail_newsletter_footer($format, $hash, $language) { if ($format == 'html') { $output = ''; } else { $output = "\n\n-- \n". t('Unsubscribe from this newsletter: !url', array('!url' => url('views_mail/user/remove/'. $hash, array('absolute' => TRUE, 'language' => $language))), $language->language); } return $output; } /** * Menu callback; confirm the user's unsubscription request when they click * on the confirm link in the e-mail footer. */ function views_mail_remove($op1 = NULL, $op2 = NULL) { $md5 = drupal_substr($op2, 0, 10); list($nid, $mail) = explode('t', drupal_substr($op2, 10)); $result = db_query('SELECT nid FROM {node} WHERE nid = %d', $nid); if (!($newsletter = db_fetch_object($result))) { drupal_not_found(); return; } // If this user has already been placed on optout list, ignore $optout = views_mail_check_optout($mail); if ($optout) { drupal_set_message(t('Email : ') . $mail . t(' already unsubscribed from Views Mail.')); drupal_not_found(); return; } if ($md5 == drupal_substr(md5($mail . views_mail_private_key()), 0, 10)) { if ($op1 == 'remove') { return drupal_get_form('views_mail_confirm_removal_form', $mail, $nid); } } // If md5 didn't match, do a not found. drupal_not_found(); return; } /** * Generate the confirm remove form. */ function views_mail_confirm_removal_form(&$form_state, $mail, $nid) { $form = array(); $form['question'] = array('#value' => '

'. t('Are you sure you want to remove %user from the Views Mail subscription list?', array('%user' => $mail)) ."

\n"); $form['mail'] = array('#type' => 'value', '#value' => $mail); $form['nid'] = array('#type' => 'value', '#value' => $nid); $form['#redirect'] = ''; return confirm_form($form, t('Confirm unsubscription'), '', t('This action will only remove you from the Views Mail subscription list. If you are registered at our site, your account information will remain unchanged.'), t('Unsubscribe'), t('Cancel') ); } /** * Forms API callback; handles form submission for a user confirming unsubscribe * request. */ function views_mail_confirm_removal_form_submit($form_id, &$form_state) { views_mail_unsubscribe_user($form_state['values']['mail'], $form_state['values']['nid'], FALSE); drupal_set_message(t('%user was successfully removed from the Views Mail subscription list.', array('%user' => $form_state['values']['mail']))); return ''; } /** * API function; unsubscribes a user from Views Mail. * * @param $mail * The e-mail address to unsubscribe. * @param $nid * The nodeID of the newsletter where the user clicked on unsubscribe. * @param $confirm * Whether we should send a confirmation e-mail and hold off removing this * user from the newsletter until he clicks the confirm link in the e-mail. */ function views_mail_unsubscribe_user($mail, $nid, $confirm = TRUE) { //Prevent mismatches from accidental capitals in mail address $mail = strtolower($mail); db_query("INSERT INTO {views_mail_optout} (email, nid) VALUES ('%s', %d)", $mail, $nid); return TRUE; } /** * API function; checks to see if user is in opt out table. * * @param $mail * The e-mail address to unsubscribe. * * @return * Return TRUE if email found. * */ function views_mail_check_optout($mail_in) { // Get email address only. $pattern = '/.+\<(.+)\>/i'; $replacement = '${1}'; $mail = preg_replace($pattern, $replacement, $mail_in); // Prevent mismatches from accidental capitals in mail address $mail = strtolower($mail); $count = db_result(db_query("SELECT COUNT(email) FROM {views_mail_optout} WHERE email = '%s'", $mail)); if ($count == 0) { return FALSE; } else { return TRUE; } } /** * Implementation of hook_theme. */ function views_mail_theme() { return array( 'views_mail_newsletter_footer' => array( 'arguments' => array('format' => NULL, 'hash' => NULL, 'language' => NULL), ), ); } /** * Implementation of hook_link(). */ function views_mail_link($type, $node = NULL, $teaser = FALSE) { $links = array(); // If this is a newsletter node in the Views Mail newsletter group // and views_mail_link is clicked on if ($type == 'node' && $node->type == 'simplenews') { $count = db_result(db_query('SELECT COUNT(nid) FROM {simplenews_newsletters} WHERE nid = %d AND tid = %d', $node->nid, variable_get('views_mail_email_default_newsletter', 0))); if ($count > 0 && variable_get('views_mail_link', 0) == 1) { if (user_access('send views mail') || user_access('send own views mail')) { // If we are in a group context, then use that group context in the link if (module_exists('og')) { // Get the group context $group_node = og_get_group_context(); if (isset($group_node->nid) && variable_get('views_mail_link_og', 0) == 1) { if (variable_get('views_mail_link_url_query', '')) { $query = 'gids[]='.$group_node->nid.'&'.variable_get('views_mail_link_url_query', ''); } else { $query = 'gids[]='.$group_node->nid; } } else { $query = variable_get('views_mail_link_url_query', ''); } $links['views_mail_newsletter'] = array( 'title' => t(variable_get('views_mail_link_title', 'Views Mail')), 'href' => variable_get('views_mail_link_url', 'views_mail'), 'query' => $query, ); } else { $links['views_mail_newsletter'] = array( 'title' => t(variable_get('views_mail_link_title', 'Views Mail')), 'href' => variable_get('views_mail_link_url', 'views_mail'), 'query' => variable_get('views_mail_link_url_query', ''), ); } // end og if } // end user_access if } // end views_mail_link if } // end simplenews node if return $links; } /** * Get gid from referrer */ function views_mail_gid_from_referrer() { $gid = 0; // Need to use the referrer to get OG group in some cases; $ref = $_SERVER["HTTP_REFERER"]; $ref_url = parse_url($ref); $ref_path = $ref_url[path]; $ref_query = $ref_url[query]; $ref_arg = explode('/', $ref_path); if ($ref_arg[1] == 'views_mail' && $ref_arg[2] == 'view') { parse_str($ref_query); $gid = $gids[0]; } drupal_set_message('referrer gid '.$gid); return $gid; } // --------- Table views_mail function views_mail_views_data() { $data['views_mail']['table']['group'] = t('Views Mail'); $data['views_mail']['table']['base'] = array( 'field' => 'vmid', 'title' => t('Views Mail log'), 'help' => t('Views Mail mailings.'), ); $data['views_mail']['table']['join'] = array( 'node' => array( 'left_table' => 'views_mail_schedule', 'left_field' => 'vmid', 'field' => 'vmid', ), 'users' => array( 'left_field' => 'uid', 'field' => 'uid', ), ); $data['views_mail']['vmid'] = array( 'title' => t('Mailing id'), 'help' => t('Id of the Views Mail mailing.'), 'field' => array( 'handler' => 'views_handler_field', ), ); $data['views_mail']['nid'] = array( 'title' => t('Newsletter node id'), 'help' => t('Node id of the newsletter used for this mailing.'), 'relationship' => array( 'title' => t('Views Mail: Newsletter node'), 'help' => t("Bring in information about the Views Mail newsletter node."), 'base' => 'node', 'field' => 'nid', 'handler' => 'views_handler_relationship', 'label' => t('Newsletter node'), ), 'field' => array( 'handler' => 'views_handler_field_node', ), ); $data['views_mail']['uid'] = array( 'title' => t('User'), 'help' => t('Id of user who creates Views Mail mailing.'), 'field' => array( 'handler' => 'views_handler_field_user_name', 'click sortable' => TRUE, ), 'argument' => array( 'handler' => 'views_handler_argument_user_uid', 'name field' => 'name', // display this field in the summary ), 'filter' => array( 'title' => t('Name'), 'handler' => 'views_handler_filter_user_name', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); // created field $data['views_mail']['created'] = array( 'title' => t('Post date'), // The item it appears as on the UI, 'help' => t('The date the Views Mail mailing was posted.'), // The help that appears on the UI, 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort_date', ), 'filter' => array( 'handler' => 'views_handler_filter_date', ), ); // created field $data['views_mail']['sent'] = array( 'title' => t('Send date'), 'help' => t('The date the Views Mail mailing was sent (if the mailing has been sent). Otherwise, it is the date the mailing is scheduled to be sent.'), 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort_date', ), 'filter' => array( 'handler' => 'views_handler_filter_date', ), ); $data['views_mail']['view'] = array( 'title' => t('View name'), 'help' => t('The name of the view used in this Views Mail mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail']['filter'] = array( 'title' => t('Filter'), 'help' => t('The exposed view filter used for this mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail']['from_name'] = array( 'title' => t('Sender name'), 'help' => t('The name of the sender used in this mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail']['from_mail'] = array( 'title' => t('Sender e-mail'), 'help' => t('The sender e-mail address used in this mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail']['subject'] = array( 'title' => t('Subject'), 'help' => t('The subject line of the e-mails sent in this mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail']['status'] = array( 'title' => t('Sent'), 'help' => t('Whether or not the mailing has been sent.'), 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', 'label' => t('Sent'), 'type' => 'yes-no', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['views_mail']['approved'] = array( 'title' => t('Approved'), 'help' => t('Whether or not the mailing has been approved. Currently not used.'), 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', 'label' => t('Sent'), 'type' => 'yes-no', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['views_mail']['recipients_scheduled'] = array( 'title' => t('Recipients scheduled.'), 'help' => t('The number of recipients scheduled to receive this mailing.'), 'field' => array( 'handler' => 'views_handler_field_numeric', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_numeric', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['views_mail']['recipients_sent'] = array( 'title' => t('Recipients sent.'), 'help' => t('The number of recipients who were actually sent e-mails in this mailing.'), 'field' => array( 'handler' => 'views_handler_field_numeric', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_numeric', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); // Join our custom table to the node table; $table = variable_get('views_mail_table', 'node'); $left_field = variable_get('views_mail_left_field', 'mail'); $data['views_mail_schedule']['table']['group'] = t('Views Mail scheduled recipients'); $data['views_mail_schedule']['table']['join'] = array( 'views_mail' => array( 'left_field' => 'vmid', 'field' => 'vmid', ), 'users' => array( 'left_field' => 'mail', 'field' => 'recipient_mail', ), 'node' => array( 'left_field' => 'nid', 'field' => 'recipient_nid', ), ); $data['views_mail_schedule']['vmid'] = array( 'title' => t('Mailing id'), 'help' => t('Id of the Views Mail mailing.'), 'field' => array( 'handler' => 'views_handler_field', ), ); $data['views_mail_schedule']['recipient_name'] = array( 'title' => t('Recipient name'), 'help' => t('The name of the recipient for this mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail_schedule']['recipient_mail'] = array( 'title' => t('Recipient e-mail'), 'help' => t('The e-mail address of recipient for this mailing.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); $data['views_mail_schedule']['status'] = array( 'title' => t('Sent'), 'help' => t('Whether or not the mailing has been sent to this recipient.'), 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', 'label' => t('Sent'), 'type' => 'yes-no', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['views_mail_schedule']['schedule'] = array( 'title' => t('Scheduled send date'), 'help' => t('The date the Views Mail mailing is scheduled to be sent. Or, if the mailing has been sent, the date it was sent.'), 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort_date', ), 'filter' => array( 'handler' => 'views_handler_filter_date', ), ); $data['views_mail_optout']['table']['group'] = t('Views Mail opt-out'); $data['views_mail_optout']['table']['join'] = array( 'views_mail' => array( 'left_field' => 'nid', 'field' => 'nid', ), 'users' => array( 'left_field' => 'mail', 'field' => 'email', ), ); $data['views_mail_optout']['nid'] = array( 'title' => t('Newsletter node id'), 'help' => t('Node id of the newsletter from which this user opted out.'), 'relationship' => array( 'title' => t('Opt-out Newsletter node'), 'help' => t("Bring in information about the Views Mail opted-out newsletter node."), 'base' => 'node', 'field' => 'nid', 'handler' => 'views_handler_relationship', 'label' => t('Opt-out Newsletter node'), ), 'field' => array( 'handler' => 'views_handler_field_node', ), ); $data['views_mail_optout']['email'] = array( 'title' => t('E-mail address'), 'help' => t('E-mail address of individual who has opted out of Views Mail mailings.'), // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), // Information for accepting a title as a filter 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); return $data; } /** * Implementation of hook_views_handlers() to register all of the basic handlers * views uses. */ function views_mail_views_handlers() { return array( 'info' => array( 'path' => drupal_get_path('module', 'views_mail') . '/views/handlers', ), 'handlers' => array( 'views_mail_handler_field_numeric' => array( 'parent' => 'views_handler_field', ), ), ); } /** * Implementation of hook_views_pre_render() */ function views_mail_views_pre_render(&$view) { if (variable_get("views_mail_debug", 0) == 1) { drupal_set_message('pre_render tag : '. $view->tag); // DEBUG drupal_set_message('

'. print_r($view, TRUE) .'
'); // DEBUG } // If set, display link on view if (variable_get('views_mail_view_link', 0) == 1) { if ($view->tag == 'views_mail') { $view->display_handler->set_option('footer', 'name; $link = views_mail_create_link($viewname); drupal_set_message($link); ?>'); $view->display_handler->set_option('footer_format', '3'); $view->display_handler->set_option('footer_empty', 0); } } } /** * Build link to views_mail configure view. * * @param string: $viewname Name of the view * * @return link to views_mail configure view */ function views_mail_create_link($viewname) { // We got the view name. Now, get the $query (exposed filters). // We only need to return a $query if there is a '&' present. $query = $_SERVER['QUERY_STRING']; if (preg_match('/\&/', $query)) { //Remove the 'q=' and only return what's after the & $args = preg_replace('/^q=([^&]*)&(.*)$/', '\2', $query); } else { $args = ""; } // If og is installed and this has a group context if (module_exists('og')) { if ($group = og_get_group_context()) { if ($args) { $args = $args.'&gids[]='.$group->gid; } else { $args = $args.'?gids[]='.$group->gid; } } } $link = l(t('Configure Views Mail mailing'), "views_mail/config/$viewname", array('query' => "$args")); return $link; }