$message['headers']['From'] = $params['from']['formatted'];
$variables = simplenews_mail_tokens($context['account'], $context, is_object($context['account']->language) ? $context['account']->language : language_default());
$message['subject'] = _simplenews_subscription_confirmation_text('subscribe_subject', $context['account']->language, $variables);
if (simplenews_user_is_subscribed($context['account']->mail, $context['newsletter']->tid)) {
$message['body'] = _simplenews_subscription_confirmation_text('unsubscribe_subscribed', $context['account']->language, $variables);
}
else {
$message['body'] = _simplenews_subscription_confirmation_text('unsubscribe_unsubscribed', $context['account']->language, $variables);
}
break;
}
// Debug message to check for outgoing emails messages.
// Debug message of node and test emails is set in simplenews_mail_mail().
if (variable_get('simplenews_debug', FALSE) && $key != 'node' && $key != 'test') {
watchdog('simplenews', 'Outgoing email. Message type: %type
Subject: %subject
Recipient: %to', array('%type' => $key, '%to' => $message['to'], '%subject' => $message['subject']), WATCHDOG_DEBUG);
}
}
/**
* Send a node to an email address.
*
* @param $nid node id of newsletter node
* @param $vid revision id of newsletter node
* @param $mail target email address
* @param $key email key [node|test]
*
* @return TRUE if email is succesfully delivered by php mail()
*/
function simplenews_mail_mail($nid, $vid, $mail, $key = 'node') {
// Get subscription data for recipient and language
$account = new stdClass();
$account->mail = $mail;
$subscription = simplenews_get_subscription($account);
$params['context']['account'] = $subscription;
// Get node data for the mail
$node = node_load($nid, $vid);
if (is_object($node)) {
$params['from'] = _simplenews_set_from($node);
$params['context']['newsletter'] = taxonomy_get_term($node->simplenews['tid']);
$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('simplenews', $key, $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'], TRUE),
isset($message['params']['context']['node']->files) ? $message['params']['context']['node']->files : array(),
''
);
}
else {
$message = drupal_mail('simplenews', $key, $subscription->mail, $subscription->language, $params, $params['from']['address'], TRUE);
}
// Log sent message.
if (variable_get('simplenews_debug', FALSE)) {
if (module_exists('mimemail')) {
$via_mimemail = t('Sent via Mime Mail');
}
//TODO Add line break before %mimemail.
if ($message['result']) {
watchdog('simplenews', 'Outgoing email. Message type: %type
Subject: %subject
Recipient: %to %mimemail', array('%type' => $key, '%to' => $message['to'], '%subject' => $message['subject'], '%mimemail' => $via_mimemail), WATCHDOG_DEBUG);
}
else {
watchdog('simplenews', 'Outgoing email failed. Message type: %type
Subject: %subject
Recipient: %to %mimemail', array('%type' => $key, '%to' => $message['to'], '%subject' => $message['subject'], '%mimemail' => $via_mimemail), WATCHDOG_ERROR);
}
}
}
else {
watchdog('simplenews', 'Newsletter not send: node does not exist (nid = @nid; vid = @vid).', array('@nid' => $message['nid'], '@vid' => $message['vid']), WATCHDOG_ERROR);
}
return isset($message['result']) ? $message['result'] : FALSE;
}
/**
* Send simplenews newsletters from the spool.
*
* Iindividual newsletter emails are stored in database spool.
* Sending is triggered by cron or immediately when the node is saved.
* Mail data is retreived from the spool, rendered and send one by one
* If sending is succesful the message is marked as send in the spool.
*/
function simplenews_mail_spool($nid = NULL, $vid = NULL, $limit = NULL) {
// Send pending messages from database cache
// A limited number of mails is retrieved from the spool
$limit = isset($limit) ? $limit : variable_get('simplenews_throttle', 20);
if ($messages = simplenews_get_spool(SIMPLENEWS_SPOOL_PENDING, $nid, $vid, $limit)) {
$mail_sent = array();
// Get PHP maximum execution time. 30 seconds default.
$max_execution_time = ini_get('max_execution_time') ? ini_get('max_execution_time') : SIMPLENEWS_MAX_EXECUTION_TIME;
_simplenews_measure_usec(TRUE);
foreach ($messages as $key => $message) {
$result = simplenews_mail_mail($message['nid'], $message['vid'], $message['mail']);
// Update spool status if mail is sent succesfully.
// This is not optimal for performance but prevents duplicate emails
// in case of PHP execution time overrun.
if ($result) {
simplenews_update_spool(array($key), SIMPLENEWS_SPOOL_SEND);
$mail_sent[] = $key;
}
// Check every n emails if we exceed the limit.
// When PHP maximum execution time is almost elapsed we interrupt
// sending. The remainder will be send during the next cron run.
if (++$check_counter >= SIMPLENEWS_SEND_CHECK_INTERVAL) {
$check_counter = 0;
// Break the sending if a percentage of max execution time was exceeded.
$elapsed = _simplenews_measure_usec();
if ($elapsed > SIMPLENEWS_SEND_TIME_LIMIT * $max_execution_time) {
watchdog('simplenews', 'Sending interrupted: PHP maximum execution time almost exceeded. Remaining newsletters will be send during the next cron run. If this warning occurs regularly you should reduce the !cron_throttle_setting.', array('!cron_throttle_setting' => l(t('Cron throttle setting'), 'admin/settings/simplenews/mail')), WATCHDOG_WARNING);
break;
}
}
}
// Update sent status for newsletter admin panel.
simplenews_send_status_update();
// Report sent result and elapsed time. On Windows systems retrusage() is
// not implemented and hence no elapsed time is available.
if (function_exists('getrusage')) {
watchdog('simplenews', '%count emails sent in %sec seconds.', array('%count' => count($mail_sent), '%sec' => round(_simplenews_measure_usec(), 1)));
}
else {
watchdog('simplenews', '%count emails sent.', array('%count' => count($mail_sent)));
}
}
}
/**
* Save mail message in mail cache table.
*
* @param array $message data array to be stored
* $message['mail']
* $message['nid']
* $message['vid']
* $message['tid']
* $message['status'] (Default: 1 = pending)
* $message['time'] (default: current unix timestamp)
* @param array $message Mail message array
*/
function simplenews_save_spool($message) {
$status = isset($message['status']) ? $message['status'] : SIMPLENEWS_SPOOL_PENDING;
$time = isset($message['time']) ? $message['time'] : time();
db_query("INSERT INTO {simplenews_mail_spool} (mail, nid, vid, tid, status, timestamp)
VALUES ('%s', %d, %d, %d, %d, %d)", $message['mail'], $message['nid'], $message['vid'], $message['tid'], $status, $time);
}
/**
* Retreive data from mail spool
*
* @param string $status Status of data to be retreived (0 = hold, 1 = pending, 2 = send)
* @param integer $nid node id
* @param integer $vid node version id
* @param integer $limit The maximum number of mails to load from the spool
*
* @return array Mail message array
* $message['msid']
* $message['mail']
* $message['nid']
* $message['vid']
* $message['tid']
* $message['status']
* $message['time']
*/
function simplenews_get_spool($status, $nid = NULL, $vid = NULL, $limit = 999999) {
$messages = array();
$result = db_query_range("SELECT * FROM {simplenews_mail_spool} s WHERE s.status = %d ORDER BY s.timestamp ASC", $status, 0, $limit);
while ($data = db_fetch_array($result)) {
$message = array();
foreach ($data as $key => $value) {
$message[$key] = $value;
}
$messages[$data['msid']] = $message;
}
return $messages;
}
/**
* Update status of mail data in spool table.
*
* Time stamp is set to current time.
*
* @param array $msids Mail spool id of record to be updated
* @param string $status New status (0 = hold, 1 = pending, 2 = send)
*/
function simplenews_update_spool($msids, $status) {
$params[] = $status;
$params[] = time();
$params = array_merge($params, $msids);
db_query("UPDATE {simplenews_mail_spool} SET status = %d, timestamp = %d WHERE msid IN(". db_placeholders($msids, 'int') .")", $params);
}
/**
* Count data in mail spool table.
*
* @param integer $nid newsletter node id
* @param integer $vid newsletter revision id
* @param string $status email send status
*
* @return array Mail message array
*/
function simplenews_count_spool($nid, $vid, $status = SIMPLENEWS_SPOOL_PENDING) {
return db_result(db_query("SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE nid = %d AND vid = %d AND status = %d", $nid, $vid, $status));
}
/**
* Remove records from mail spool table.
*
* All records with status 'send' and time stamp before the expiration date
* are removed from the spool.
*/
function simplenews_clear_spool() {
$expiration_time = time() - variable_get('simplenews_spool_expire', 0) * 86400;
db_query("DELETE FROM {simplenews_mail_spool} WHERE status = %d AND timestamp <= %d", SIMPLENEWS_SPOOL_SEND, $expiration_time);
}
/**
* Update newsletter send status.
*
* Set newsletter send status based on email send status in spool table.
* Translated and untranslated nodes get a different treatment.
*
* The spool table holds data for emails to be send and (optionally)
* already send emails. The simplenews_newsletters table contains the overall
* send status of each newsletter issue (node).
* Newsletter issues get the status pending when sending is innitiated. As
* long as unsend emails exist in the spool, the status of the newsletter remains
* unsend. When no pending emails are found the newsletter status is set 'send'.
*
* Translated newsletters are a group of nodes that share the same tnid ({node}.tnid).
* Only one node of the group is found in the spool, but all nodes should share
* the same state. Therefore they are checked for the combined number of emails
* in the spool.
*/
function simplenews_send_status_update() {
$counts = array(); // number pending of emails in the spool
$sum = array(); // sum of emails in the spool per tnid (translation id)
$send = array(); // nodes with the status 'send'
// For each pending newsletter count the number of pending emails in the spool.
$result = db_query("SELECT s.nid, s.vid, s.tid, n.tnid FROM {simplenews_newsletters} s JOIN {node} n ON s.nid = n.nid AND s.vid = n.vid WHERE s.s_status = %d", SIMPLENEWS_STATUS_SEND_PENDING);
while ($newsletter = db_fetch_object($result)) {
// nid-vid are combined in one unique key.
$counts[$newsletter->tnid][$newsletter->nid .'-'. $newsletter->vid] = simplenews_count_spool($newsletter->nid, $newsletter->vid);
}
// Determine which nodes are send per translation group and per individual node.
foreach ($counts as $tnid => $node_count) {
// The sum of emails per tnid is the combined status result for the group of translated nodes.
// Untranslated nodes have tnid == 0 which will be ignored later.
$sum[$tnid] = array_sum($node_count);
foreach ($node_count as $nidvid => $count) {
// Translated nodes (tnid != 0)
if ($tnid != '0' && $sum[$tnid] == '0') {
$send[] = $nidvid;
}
// Untranslated nodes (tnid == 0)
elseif ($tnid == '0' && $count == '0') {
$send[] = $nidvid;
}
}
}
// Update overall newsletter status
if (!empty($send)) {
foreach ($send as $nidvid) {
// Split the combined key 'nid-vid'
$nid = strtok($nidvid, '-');
$vid = strtok('-');
db_query("UPDATE {simplenews_newsletters} SET s_status = '%s' WHERE nid = %d AND vid = %d", SIMPLENEWS_STATUS_SEND_READY, $nid, $vid);
}
}
}
/**
* Implementation of hook_views_api().
*/
function simplenews_views_api() {
return array(
'api' => 2,
);
}
/**
* Call simplenews actions.
*/
function simplenews_call_actions($op, $subscription) {
// Only call actions when the simplenews_action module is enabled.
if (!module_exists('simplenews_action')) {
return;
}
$aids = _trigger_get_hook_aids('simplenews', $op);
$context = array(
'hook' => 'simplenews',
'op' => $op,
'account' => $subscription,
);
foreach ($aids as $aid => $action_info) {
actions_do($aid, $subscription, $context);
}
}
/**
* Build formatted from-name and email for a mail object.
*
* Each newsletter (serie; tid) can have a different from address.
* The from name and address depend on the newsletter term tid which is included in the $node object
*
* @param object $node Node object of a simplenews newsletter
*
* @return array [address] = from address; [formatted] = formatted from name and address
*/
function _simplenews_set_from($node = NULL) {
$address_default = variable_get('site_mail', ini_get('sendmail_from'));
$name_default = variable_get('site_name', 'Drupal');
if (isset($node->simplenews['tid'])) {
$address = variable_get('simplenews_from_address_'. $node->simplenews['tid'], variable_get('simplenews_from_address', $address_default));
$name = variable_get('simplenews_from_name_'. $node->simplenews['tid'], variable_get('simplenews_from_name', $name_default));
}
else {
$address = variable_get('simplenews_from_address', $address_default);
$name = variable_get('simplenews_from_name', $name_default);
}
// Windows based PHP systems don't accept formatted emails.
$formatted_address = substr(PHP_OS, 0, 3) == 'WIN' ? $address : '"'. mime_header_encode($name) .'" <'. $address .'>';
return array(
'address' => $address,
'formatted' => $formatted_address,
);
}
/**
* Build header array with priority and receipt confirmation settings.
*
* @param $node: node object
* @param $from: from email address
*
* @return Header array with priority and receipt confirmation info
*/
function _simplenews_headers($node, $from) {
$headers = array();
// If receipt is requested, add headers.
if ($node->simplenews['receipt']) {
$headers['Disposition-Notification-To'] = $from;
$headers['X-Confirm-Reading-To'] = $from;
}
// Add priority if set.
switch ($node->simplenews['priority']) {
case SIMPLENEWS_PRIORITY_HIGHEST:
$headers['Priority'] = 'High';
$headers['X-Priority'] = '1';
$headers['X-MSMail-Priority'] = 'Highest';
break;
case SIMPLENEWS_PRIORITY_HIGH:
$headers['Priority'] = 'urgent';
$headers['X-Priority'] = '2';
$headers['X-MSMail-Priority'] = 'High';
break;
case SIMPLENEWS_PRIORITY_NORMAL:
$headers['Priority'] = 'normal';
$headers['X-Priority'] = '3';
$headers['X-MSMail-Priority'] = 'Normal';
break;
case SIMPLENEWS_PRIORITY_LOW:
$headers['Priority'] = 'non-urgent';
$headers['X-Priority'] = '4';
$headers['X-MSMail-Priority'] = 'Low';
break;
case SIMPLENEWS_PRIORITY_LOWEST:
$headers['Priority'] = 'non-urgent';
$headers['X-Priority'] = '5';
$headers['X-MSMail-Priority'] = 'Lowest';
break;
}
// Add general headers
$headers['Precedence'] = 'bulk';
return $headers;
}
/**
* HTML to text conversion for HTML and special characters.
*
* Converts some special HTMLcharacters in addition to drupal_html_to_text()
*
* @param string $text Source text with HTML and special characters
* @param boolean $inline_hyperlinks
* TRUE: URLs will be placed inline.
* FALSE: URLs will be converted to numbered reference list.
* @return string Target text with HTML and special characters replaced
*/
function simplenews_html_to_text($text, $inline_hyperlinks = TRUE) {
// By replacing tag by only its URL the URLs will be placed inline
// in the email body and are not converted to a numbered reference list
// by drupal_html_to_text().
// URL are converted to abolute URL as drupal_html_to_text() would have.
if ($inline_hyperlinks) {
$pattern = '@]+?href="([^"]*)"[^>]*?>(.+?)@is';
$text = preg_replace_callback($pattern, '_simplenews_absolute_mail_urls', $text);
}
// Replace some special characters before performing the drupal standard conversion.
$preg = _simplenews_html_replace();
$text = preg_replace(array_keys($preg), array_values($preg), $text);
// Perform standard drupal html to text conversion.
return drupal_html_to_text($text);
}
/**
* Helper function for simplenews_html_to_text().
*
* Replaces URLs with abolute URLs.
*/
function _simplenews_absolute_mail_urls($match) {
global $base_url, $base_path;
static $regexp;
$url = $label = '';
if ($match) {
if (empty($regexp)) {
$regexp = '@^'. preg_quote($base_path, '@') .'@';
}
list(, $url, $label) = $match;
$url = strpos($url, '://') ? $url : preg_replace($regexp, $base_url .'/', $url);
// If the link is formed by Drupal's URL filter, we only return the URL.
// The URL filter generates a label out of the original URL.
if (strpos($label, '...') == strlen($label) - 3) {
// Remove ellipsis from end of label.
$label = substr($label, 0, strlen($label) - 3);
}
if (strpos($url, $label) !== FALSE) {
return $url;
}
return $label .' '. $url;
}
}
/**
* Helper function for simplenews_html_to_text().
*
* List of preg* regular expression patterns to search for and replace with
*/
function _simplenews_html_replace() {
return array(
'/"/i' => '"',
'/>/i' => '>',
'/</i' => '<',
'/&/i' => '&',
'/©/i' => '(c)',
'/™/i' => '(tm)',
'/“/' => '"',
'/”/' => '"',
'/–/' => '-',
'/’/' => "'",
'/&/' => '&',
'/©/' => '(c)',
'/™/' => '(tm)',
'//' => '--',
'//' => '"',
'//' => '"',
'//' => '*',
'/®/i' => '(R)',
'/•/i' => '*',
'/€/i' => 'Euro ',
);
}
/**
* Build array of mail tokens.
*
* Depending on the context in which this function is called, some tokens
* may return an empty value. e.g. !newsletter_url is empty when called
* while building a confirmation email.
*
* @param $subscription
* Subscription or user object
* @param $context
* [newsletter] newsletter term object
* [node] node object
* @param $language
* Language object
*
* @return array of tokens and token values.
*/
function simplenews_mail_tokens($subscription, $context, $language) {
// Build hash for (un)subscription confirmation link for subscribed user.
$hash = '';
if (isset($subscription->snid) && isset($context['newsletter']->tid)) {
$hash = _simplenews_generate_hash($subscription->mail, $subscription->snid, $context['newsletter']->tid);
}
// Get newsletter name if not in newsletter object.
$name = isset($context['newsletter']->name) ? $context['newsletter']->name : '';
if (!$name) {
if (isset($context['node']->simplenews['tid'])) {
if ($term = taxonomy_get_term($context['node']->simplenews['tid'])) {
// Translate newsletter name if required.
$name = $term->name;
if (module_exists('i18ntaxonomy') && i18ntaxonomy_vocabulary(variable_get('simplenews_vid', '')) == I18N_TAXONOMY_LOCALIZE) {
$name = tt('taxonomy:term:'. $context['node']->simplenews['tid'] .':name', $name, $language->language);
}
}
}
}
// Get tokens from user_mail_tokens() and add simplenews variables.
if($subscription->uid) {
$vars = user_mail_tokens($subscription, $language);
}
else {
$vars = array();
$vars['!site'] = variable_get('site_name', 'Drupal');
$vars['!mailto'] = $subscription->mail;
$vars['!date'] = format_date(time(), 'medium', '', NULL, $language->language);
$vars['!login_uri'] = url('user', array('absolute' => TRUE, 'language' => $language));
}
// Replace existing uri and uri_brief to cope with multilingual sites.
$vars['!uri'] = url('', array('absolute' => TRUE, 'language' => $language));
$vars['!uri_brief'] = preg_replace('!^https?://!', '', $vars['!uri']);
$vars['!confirm_subscribe_url'] = url('newsletter/confirm/add/'. $hash, array('absolute' => TRUE, 'language' => $language));
$vars['!confirm_unsubscribe_url'] = url('newsletter/confirm/remove/'. $hash, array('absolute' => TRUE, 'language' => $language));
$vars['!newsletter_url'] = isset($context['node']->nid) ? url('node/'. $context['node']->nid, array('absolute' => TRUE, 'language' => $language)) : '';
$vars['!newsletter_name'] = $name;
return $vars;
}
/**
* Create a 32 character identifier.
*/
function simplenews_private_key() {
$key = variable_get('simplenews_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('simplenews_private_key', $key);
}
return $key;
}
/**
* Implementation of hook_help().
*/
function simplenews_help($path, $arg) {
switch ($path) {
case 'admin/help#simplenews':
$help = "". t('Simplenews publishes and sends newsletters to lists of subscribers. Both anonymous and authenticated users can opt-in to different mailing lists.') ."
\n";
$help .= "". t('Simplenews uses nodes for newsletter issues. Newsletter issues are grouped by a newsletter taxonomy term. Node type and vocabulary are selectable. A newsletter is send to all email addresses which are subscribed to the newsletter. Newsletter issues can be sent only once. Large mailings should be sent by cron to balance the mailserver load.') ."
\n";
$help .= "". t('Simplenews adds elements to the newsletter node add/edit form to manage newsletter format and sending of the newsletter issue. A newsletter issue can be sent for test before sending officially.') ."
\n";
$help .= "". t('Both anonymous and authenticated users can opt-in and opt-out to a newsletter. A confirmation message is sent to anonymous users at subscription and unsubscription. Users can (un)subscribe using a form and a block. A subscription block is available for each newsletter offering a subscription form, a link to recent newsletters and RSS feed. Email addresses can also be imported and exported via the subscription administration pages.') ."
\n";
$help .= "". t('Configuration') ."\n";
$help .= "";
if (user_access('administer permissions')) {
$help .= "- ". l(t('Configure permissions'), 'admin/user/permissions', array('fragment' => 'module-simplenews')) ."
\n";
}
if (user_access('administer simplenews settings')) {
$help .= "- ". l(t('Configure Simplenews'), 'admin/settings/simplenews') ."
\n";
}
if (user_access('administer blocks')) {
$help .= "- ". t('Enable a newsletter subscription block.', array('@admin_blocks' => url('admin/build/block'))) ."
\n";
}
if (user_access('administer simplenews settings')) {
$help .= "- ". t('Manage your newsletters, sent newsletters and subscriptions.', array('@newsletters' => url('admin/content/simplenews/types'), '@sent' => url('admin/content/simplenews'), '@subscriptions' => url('admin/content/simplenews/users'))) ."
\n";
}
$help .= "
";
$help .= "
". t('For more information, see the online handbook entry for Simplenews.', array('@handbook', 'http://drupal.org/node/197057')) ."
\n";
return $help;
case 'node/add/simplenews':
$help = '';
$help .= "- ". t('Add this newsletter issue to a newsletter by selecting a newsletter from the select list. Send a newsletter or a test newsletter by selecting the appropriate radio button and submitting the node.') ."
\n";
if (user_access('administer simplenews settings')) {
$help .= "- ". t('Set default send options at Administer > Site configuration > Simplenews > Newsletter.', array('@configuration' => url('admin/settings/simplenews/newsletter'))) ."
\n";
}
if (user_access('administer newsletters')) {
$help .= "- ". t('Set newsletter specific options at Administer > Content management > Newsletters > Newsletters.', array('@configuration' => url('admin/content/simplenews/types'))) ."
\n";
}
$help .= "
";
return $help;
case 'admin/settings/simplenews/newsletter':
$help = '';
$help .= '- '. t('These settings are default to all newsletters. Newsletter specific settings can be found at the newsletter\'s settings page.', array('@page' => url('admin/content/simplenews/types'))) ."
\n";
if (!module_exists('mimemail')) {
$help .= "- ". t('Install Mime Mail to send HTML emails or emails with attachments (both plain text and HTML).', array('@mime_mail_url' => 'http://drupal.org/project/mimemail')) ."
\n";
}
$help .= "
";
return $help;
case 'admin/content/simplenews/types/add':
$help = ''. t('You can create different newsletters (or subjects) to categorize your news (e.g. Cats news, Dogs news, ...).') ."
\n";
return $help;
case 'admin/content/node-type/simplenews/display/simplenews':
$help = ''. t("'Plain' display settings apply to the content of emails send in plain text format. 'HTML' display settings apply to both HTML and plain text alternative content of emails send in HTML format.") ."
\n";
return $help;
}
}
/**
* Flatten a nested array
*/
function _simplenews_flatten_array($array) {
$return = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$return += _simplenews_flatten_array($value);
}
else {
$return[$key] = $value;
}
}
return $return;
}
/**
* Generate the hash key used for subscribe/unsubscribe link.
*/
function _simplenews_generate_hash($mail, $snid, $tid) {
return drupal_substr(md5($mail . simplenews_private_key()), 0, 10) . $snid .'t'. $tid;
}
/**
* Determine possible mail format options.
*
* The mime_mail module must be installed to send HTML mails.
*/
function _simplenews_format_options() {
$options = array('plain' => t('plain'));
if (module_exists('mimemail') || module_exists('htmlmail')) {
$options['html'] = t('html');
}
return $options;
}
/**
* Generate default and custom subscription confirmation email text.
*
* @param string $key text identification key
* @param object $language language object
* @param array $variables array of variables as used by t()
*/
function _simplenews_subscription_confirmation_text($key, $language = NULL, $variables = array()) {
$langcode = isset($language) ? $language->language : NULL;
if ($admin_setting = variable_get('simplenews_confirm_'. $key, FALSE)) {
// An admin setting overrides the default string.
return t($admin_setting, $variables, $langcode);
}
else {
// No override, return default string.
switch ($key) {
case 'subscribe_unsubscribed':
return t("We have received a request for subscription of !mailto to the !newsletter_name on !site website at !uri. To confirm this subscription please use the link below.\n\n!confirm_subscribe_url", $variables, $langcode);
case 'subscribe_subscribed':
return t("We have received a request for subscription of !mailto to the !newsletter_name on !site website at !uri. However, this email is already subscribed to this newsletter. If you intended to unsubscribe please visit our site: !uri", $variables, $langcode);
case 'unsubscribe_subscribed':
return t("We have received a request to unsubscribe !mailto from the !newsletter_name on !site website at !uri. To confirm this unsubscription please use the link below.\n\n!confirm_unsubscribe_url", $variables, $langcode);
case 'unsubscribe_unsubscribed':
return t("We have received a request to unsubscribe !mailto from the !newsletter_name on !site website at !uri. However, this email is not subscribed to this newsletter. If you intended to subscribe please visit our site: !uri", $variables, $langcode);
case 'subscribe_subject':
return t("Confirmation for !newsletter_name from !site", $variables, $langcode);
}
}
}
/**
* Helper function to measure PHP execution time in microseconds.
*
* @param bool $start TRUE reset the time and start counting.
* @return float: elapsed PHP execution time since start.
*/
function _simplenews_measure_usec($start = FALSE) {
// Windows systems don't implement getrusage(). There is no alternative.
if (!function_exists('getrusage')) {
return 0;
}
static $start_time;
$usage = getrusage();
$now = (float)($dat["ru_stime.tv_sec"] .'.'. $dat["ru_stime.tv_usec"]) + (float)($usage["ru_utime.tv_sec"] .'.'. $usage["ru_utime.tv_usec"]);
if ($start) {
$start_time = $now;
return 0;
}
return $now - $start_time;
}
/**
* Implementation of hook_content_build_modes().
*/
function simplenews_content_build_modes() {
return array(
'simplenews' => array(
'title' => t('Simplenews'),
'build modes' => array(
'email_plain' => array(
'title' => t('Email: Plain'),
'views style' => FALSE,
),
'email_html' => array(
'title' => t('Email: HTML'),
'views style' => FALSE,
),
),
),
);
}
/**
* Implementation of hook_theme().
*/
function simplenews_theme() {
return array(
'simplenews_block' => array(
'template' => 'simplenews-block',
'arguments' => array('tid' => NULL),
'pattern' => 'simplenews_block__',
),
'simplenews_status' => array(
'template' => 'simplenews-status',
'file' => 'simplenews.admin.inc',
'arguments' => array('status' => NULL, 'source' => NULL),
),
'simplenews_newsletter_subject' => array(
'arguments' => array('name' => NULL, 'title' => NULL, 'language' => NULL),
),
'simplenews_newsletter_body' => array(
'template' => 'simplenews-newsletter-body',
'arguments' => array('node' => NULL, 'language' => NULL),
'pattern' => 'simplenews_newsletter_body__',
),
'simplenews_newsletter_footer' => array(
'template' => 'simplenews-newsletter-footer',
'arguments' => array('node' => NULL, 'key' => NULL, 'language' => NULL),
'pattern' => 'simplenews_newsletter_footer__',
),
'simplenews_subscription_list' => array(
'file' => 'simplenews.admin.inc',
'arguments' => array('form' => NULL),
),
);
}
/**
* Process variables to format the simplenews block.
*
* Collect data and apply access restrictions.
*
* $variables contains:
* - $tid
*
* @see simplenews-block.tpl.php
* @see theme_simplenews-block()
*/
function template_preprocess_simplenews_block(&$variables) {
global $user;
$tid = $variables['tid'];
// Set default values in case of missing permission.
$variables['form'] = '';
$variables['subscription_link'] = '';
$variables['newsletter_link'] = '';
$variables['issue_list'] = '';
$variables['rssfeed'] = '';
// Block content variables
$variables['message'] = check_plain(variable_get('simplenews_block_m_'. $tid, t('Stay informed on our latest news!')));
if (user_access('subscribe to newsletters')) {
$variables['form'] = drupal_get_form('simplenews_block_form_'. $tid);
$variables['subscription_link'] = l(t('Manage my subscriptions'), 'newsletter/subscriptions');
}
$variables['newsletter_link'] = l(t('Previous issues'), 'taxonomy/term/'. $tid);
$recent = simplenews_recent_newsletters($tid, variable_get('simplenews_block_i_'. $tid, 5));
$variables['issue_list'] = theme('item_list', $recent, t('Previous issues'), 'ul');
$term = taxonomy_get_term($tid);
$variables['rssfeed'] = theme('feed_icon', url('taxonomy/term/'. $tid .'/0/feed'), t('@newsletter feed', array('@newsletter' => $term->name)));
// Block content control variables
$variables['use_form'] = variable_get('simplenews_block_f_'. $tid, 1);
$variables['use_issue_link'] = variable_get('simplenews_block_l_'. $tid, 1);
$variables['use_issue_list'] = variable_get('simplenews_block_i_status_'. $tid, 0);
$variables['use_rss'] = variable_get('simplenews_block_r_'. $tid, 1);
// Additional variables
$variables['subscribed'] = empty($user->uid) ? FALSE : (simplenews_user_is_subscribed($user->mail, $tid) == TRUE);
$variables['user'] = !empty($user->uid);
}
/**
* Theme the newsletter email subject.
*/
function theme_simplenews_newsletter_subject($name, $title, $language) {
return '['. $name .'] '. $title;
}
/**
* Process variables to format the simplenews newsletter body.
*
* $variables contains:
* - $node
* - $language
*
* @see simplenews-newsletter-body.tpl.php
*/
function template_preprocess_simplenews_newsletter_body(&$variables) {
$variables['title'] = check_plain($variables['node']->title);
$variables['body'] = $variables['node']->body;
}
/**
* Process variables to format the simplenews newsletter footer.
*
* $variables contains:
* - $node
* - $key
* - $language
*
* @see simplenews-newsletter-footer.tpl.php
*/
function template_preprocess_simplenews_newsletter_footer(&$variables) {
$variables['format'] = $variables['node']->simplenews['s_format'];
$variables['unsubscribe_text'] = t('Unsubscribe from this newsletter', array(), $variables['language']->language);
$variables['test_message'] = t('This is a test version of the newsletter.', array(), $variables['language']->language);
}