Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
IceCreamYou committed Jul 27, 2011
0 parents commit b4a5013
Show file tree
Hide file tree
Showing 8 changed files with 4,448 additions and 0 deletions.
53 changes: 53 additions & 0 deletions digests-email.tpl.php
@@ -0,0 +1,53 @@
<?php
/**
* @file
* Renders a digest email.
*
* See http://drupal.org/node/226776 for a list of default variables.
*
* Other variables available:
* - $account: The user account object of the user receiving the message
* - $messages: An array of activity message objects
* - $stream: The themed (HTML) list of activity messages
* - $name: The name of the user being sent the message
* - $name_link: The name of the user being sent the message, linked to their profile
* - $date_small: The small formatted date per the site's settings
* - $date_medium: The medium formatted date per the site's settings
* - $date_large: The large formatted date per the site's settings
* - $logo: HTML for the logo image
* - $header: The email header set by the administrator
* - $footer: The email footer set by the administrator
* - $unsubscribe: Instructions on how to unsubscribe from digest emails
*
* NOTE:
* HTML and CSS do not work the same way in emails as they do in web pages.
* The most consistent way to style emails is to use tables for the structure.
* Additionally, only inline styles will have any effect in some clients (most
* notably Gmail).
*/
?>
<div id="digests">
<?php if ($logo) {
print $logo;
} ?>
<?php if ($header): ?>
<div id="digests-header">
<?php print $header; ?>
</div>
<?php endif; ?>
<table id="digests-stream" style="border: 1px solid #CCCCCC; margin: 12px 24px; max-width: 800px; min-width: 480px; padding: 18px 30px">
<tbody>
<?php print $stream; ?>
</tbody>
</table>
<?php if ($footer): ?>
<div id="digests-footer">
<?php print $footer; ?>
</div>
<?php endif; ?>
<?php if ($unsubscribe): ?>
<div id="digests-unsubscribe">
<?php print $unsubscribe; ?>
</div>
<?php endif; ?>
</div>
116 changes: 116 additions & 0 deletions digests.admin.inc
@@ -0,0 +1,116 @@
<?php

/**
* @file
* Administrative settings for the Activity Digests module.
*/

/**
* Administrative options.
*/
function digests_admin($form_state) {
$form = array();
$form['digests_send_time'] = array(
'#type' => 'select',
'#title' => t('Send digests after'),
'#description' => t('Select an hour of the day'),
'#options' => _digests_get_hours(),
'#default_value' => variable_get('digests_send_time', 18),
'#required' => TRUE,
);
$form['digests_local'] = array(
'#type' => 'radios',
'#title' => t('Send digests'),
'#default_value' => variable_get('digests_local', 'local'),
'#options' => array(
'local' => t("using users' local timezones"),
'site' => t("using the site's timezone"),
),
'#required' => TRUE,
);
$form['digests_limit'] = array(
'#type' => 'textfield',
'#title' => t('The maximum number of users to which to send digests each time cron runs'),
'#description' => t('Leave this field blank or enter 0 to process all users.'),
'#default_value' => variable_get('digests_limit', 250),
'#size' => 11,
'#maxlength' => 15,
);
$form['digests_logo'] = array(
'#type' => 'textfield',
'#title' => t('Logo image'),
'#description' => t('The path to your logo image from your Drupal root.') .' '.
t('If you use this, the logo will appear at the top of digest emails.'),
'#default_value' => variable_get('digests_logo', ''),
);
if (module_exists('token')) {
$form['token_help'] = array(
'#title' => t('Replacement patterns'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['token_help']['global'] = array(
'#title' => t('Global'),
'#description' => t('You can use these tokens in the email header or footer.'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['token_help']['global']['help'] = array(
'#value' => theme('token_help', 'global'),
);
$form['token_help']['user'] = array(
'#title' => t('Recipient user'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['token_help']['user']['help'] = array(
'#value' => theme('token_help', 'user'),
);
}
$form['digests_header'] = array(
'#type' => 'textarea',
'#title' => t('Email header'),
'#rows' => 2,
'#default_value' => variable_get('digests_header', ''),
);
$form['digests_footer'] = array(
'#type' => 'textarea',
'#title' => t('Email footer'),
'#rows' => 2,
'#default_value' => variable_get('digests_footer', ''),
);
return system_settings_form($form);
}

/**
* Validates the administrative options.
*/
function digests_admin_validate($form, $form_state) {
$v = $form_state['values']['digests_limit'];
if (!empty($v) && (!is_numeric($v) || $v < 0)) {
form_set_error('digests_limit', t('The maximum number of users to which to send digests per cron run must be a positive integer.'));
}
}

/**
* Returns a list of the hours of the day formatted by the site's preference.
*/
function _digests_get_hours() {
$range = range(0, 23);
$date_format = variable_get('date_format_long', 'l, F j, Y - H:i');
$hour_format = 'H'; // e.g. 00
foreach (array('a', 'A', 'g', 'h') as $c) {
if (strpos($date_format, $c) !== FALSE) {
$hour_format = 'ga'; // e.g. 12am
break;
}
}
$options = array();
foreach ($range as $num) {
$options[$num] = date($hour_format, mktime($num, 0, 0));
}
return $options;
}
197 changes: 197 additions & 0 deletions digests.cron.inc
@@ -0,0 +1,197 @@
<?php

/**
* @file
* Cron tasks for the Activity Log Digests module.
*/

//============
// PROCESSING
//============

/**
* Send digest emails.
*/
function _digests_cron() {
$default_tz = variable_get('date_default_timezone', 0);
$now = time();
$send_time = mktime(variable_get('digests_send_time', 18), 0, 0);

// Step 1: Get users for whom it is after 6PM in their timezone but who have not had a digest sent for this interval.
$default = $now > $send_time + $default_tz || $now < $send_time + $default_tz - 43200; // whether it's past send_time in the site's default timezone
$query = "
SELECT *
FROM {users} u
LEFT JOIN {digests} d
ON u.uid = d.uid
WHERE
status = 1 AND ( /* user is not blocked */
send_interval IS NULL OR /* user has not set their interval */
send_interval = 86400". /* user's interval is daily */
(date('w') == 0 ? ' OR send_interval = 604800' : '') ." /* user's interval is weekly, and it's Sunday */
) AND (
%d > last_sent + (COALESCE(send_interval, 86400) - 43200) OR /* it's been at least (interval - 12 hours) since the last digest email */
last_sent IS NULL /* the user has never been sent a digest email */
)";
if (variable_get('digests_local', 'local') == 'local') {
$query .= " AND (
%d /* NOW */ > %d /* SEND */ + timezone OR /* it's after send_time today */
%d /* NOW */ < %d /* SEND */ + timezone - 43200 /* it's more than 12hrs before send_time today, i.e. less than 12hrs since send_time yesterday */
";
if ($default) {
$query .= " OR timezone IS NULL /* the user has not set a timezone, fall back to the site default */";
}
$query .= "\n )";
if (variable_get('digests_limit', 250)) {
$result = db_query_range($query, $now, $now, $send_time, $now, $send_time, 0, variable_get('digests_limit', 250));
}
else {
$result = db_query($query, $now, $now, $send_time, $now, $send_time);
}
}
elseif ($default) {
if (variable_get('digests_limit', 250)) {
$result = db_query_range($query, 0, variable_get('digests_limit', 250));
}
else {
$result = db_query($query);
}
}

// Step 2: For each selected user, collect all activity that has been updated between 6PM 2 days ago and 6PM yesterday
while ($account = db_fetch_object($result)) {
if (empty($account) || empty($account->uid) || !valid_email_address($account->mail)) {
continue;
}
$account = drupal_unpack($account);
$account->roles = array();
$user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
$rresult = db_query('SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d', $account->uid);
while ($role = db_fetch_object($rresult)) {
$account->roles[$role->rid] = $role->name;
}
if (!user_access('receive digests', $account)) {
continue;
}
$account_tz = $default_tz;
if (isset($account->timezone) && !is_null($account->timezone)) {
$account_tz = $account->timezone;
}
$interval = 86400;
if (isset($account->send_interval) && !is_null($account->send_interval)) {
$interval = $account->send_interval;
}
$send_time_account = $send_time + $account_tz;
$send_time_two_days_ago = $send_time_account - (86400 + $interval);
$send_time_one_day_ago = $send_time_account - 86400;
$mresult = db_query("
SELECT *
FROM {activity_log_messages} m
LEFT JOIN {activity_log_templates} t
ON m.tid = t.tid
WHERE
display_type = 'email' AND
stream_owner_type = 'user' AND
stream_owner_id = %d AND
last_updated > %d /* 2 days ago */ AND
last_updated < %d /* 1 day ago */ AND (
viewer_id = %d /* account */ OR
viewer_id = 0 /* everyone */ OR
(viewer_id < 0 AND viewer_id <> -%d) /* everyone except account */
) AND
t.pid NOT IN (
SELECT pid FROM {activity_log_disabled_types} WHERE uid = %d
)
ORDER BY last_updated DESC
", $account->uid, $send_time_two_days_ago, $send_time_one_day_ago, $account->uid, $account->uid, $account->uid);

// Step 3: Render the collected activity messages as HTML
$messages = array();
while ($record = db_fetch_object($mresult)) {
$messages[] = $record;
}
if (empty($messages)) {
continue;
}
$output = theme('digests_email', $account, $messages, $now);

// Step 4: Pass the rendered activity stream to the Mime Mail module for delivery
if ($interval == 86400) {
$subject = t('Your @site activity for @date', array(
'@site' => variable_get('site_name', 'Drupal'),
'@date' => date('l, F j'),
));
}
elseif ($interval == 604800) {
$subject = t('Your @site activity for the week of @date', array(
'@site' => variable_get('site_name', 'Drupal'),
'@date' => date('F j'),
));
}
mimemail(
variable_get('site_mail', ini_get('sendmail_from')), //sender
$account, // recipient
$subject, // subject
$output, // HTML for body
NULL, // force plaintext only
array(), // headers
NULL, // custom plaintext version
array(), // attachments
'digests' // mailkey
);

// Step 5: Update the "last sent" time for each processed user
db_query("UPDATE {digests} SET last_sent = %d WHERE uid = %d", $now, $account->uid);
if (db_affected_rows() <= 0) {
$insert = (object) array(
'uid' => $account->uid,
'last_sent' => $now,
'send_interval' => 86400,
);
drupal_write_record('digests', $insert);
}
}
}

/**
* Preprocess the digest email template variables.
*/
function template_preprocess_digests_email(&$vars) {
$output = '';
$count = 0;
foreach ($vars['messages'] as $message) {
$count++;
activity_log_record_unpack($message);
$html_message = theme('activity_log_item', $message);
$output .= '<tr><td class="digests-message" style="border-bottom: 1px solid #EEEEEE;'. ($count === 1 ? ' border-top: 1px solid #EEEEEE; ' : ' ') .'padding: 12px 0;">'. $html_message ."</td></tr>\n";
}
$vars['stream'] = $output;
$account = $vars['account'];
$vars['name'] = check_plain($account->name);
$vars['name_link'] = l(check_plain($account->name), 'user/'. $account->uid);
$now = $vars['now'];
$vars['date_small'] = format_date($now, 'small');
$vars['date_medium'] = format_date($now, 'medium');
$vars['date_large'] = format_date($now, 'large');
$vars['logo'] = variable_get('digests_logo', '') ? '' : theme(
'image',
url(variable_get('digests_logo', ''), array('absolute' => TRUE)),
variable_get('site_name', 'Drupal'),
variable_get('site_name', 'Drupal'),
NULL,
FALSE
);
$header = variable_get('digests_header', '');
$footer = variable_get('digests_footer', '');
if (module_exists('token')) {
$types = array('global' => NULL, 'user' => $account);
$header = token_replace_multiple($header, $types);
$footer = token_replace_multiple($footer, $types);
}
$vars['header'] = filter_xss_admin($header);
$vars['footer'] = filter_xss_admin($footer);
$vars['unsubscribe'] = t('<a href="!unsub">Edit your settings</a> to unsubscribe from activity emails from @site.', array(
'!unsub' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)),
'@site' => variable_get('site_name', 'Drupal'),
));
}
6 changes: 6 additions & 0 deletions digests.info
@@ -0,0 +1,6 @@
name = Activity Log Digests
description = "Sends users regularly-scheduled email digests of recent, relevant site activity in multi-part HTML."
dependencies[] = activity_log
dependencies[] = mimemail
package = Activity Log
core = 6.x

0 comments on commit b4a5013

Please sign in to comment.