Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b4a5013
Showing
8 changed files
with
4,448 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'), | ||
)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.