View source
<?php
define('SIMPLENEWS_COMMAND_SEND_SCHEDULE', 3);
define('SIMPLENEWS_COMMAND_SEND_NONE', 4);
function simplenews_scheduler_perm() {
return array(
'overview scheduled newsletters',
'send scheduled newsletters',
'use PHP for scheduling newsletters',
);
}
function simplenews_scheduler_menu() {
$items = array();
$items["node/%node/editions"] = array(
'title' => 'Newsletter Editions',
'type' => MENU_LOCAL_TASK,
'weight' => 2,
'page callback' => 'simplenews_scheduler_node_page',
'page arguments' => array(
1,
),
'access callback' => '_simplenews_scheduler_tab_permission',
'access arguments' => array(
1,
),
);
return $items;
}
function simplenews_scheduler_form_simplenews_node_tab_send_form_alter(&$form, &$form_state) {
global $user;
if (user_access('send scheduled newsletters') && !isset($node->simplenews_scheduler_edition)) {
drupal_add_js(drupal_get_path('module', 'simplenews_scheduler') . '/simplenews_scheduler.js', 'module', 'header', FALSE, FALSE, TRUE);
$form['#submit'][] = "simplenews_scheduler_submit";
$scheduler = array();
$result = db_query("SELECT * FROM {simplenews_scheduler} WHERE nid = %d", arg(1));
$row = db_fetch_array($result);
if ($row) {
$scheduler = $row;
}
else {
$scheduler['activated'] = 0;
}
$form['#simplenews_scheduler'] = $scheduler;
$form['simplenews']['send']['#options'][SIMPLENEWS_COMMAND_SEND_SCHEDULE] = t('Send newsletter according to schedule');
$form['simplenews']['send']['#options'][SIMPLENEWS_COMMAND_SEND_NONE] = t("Don't send now or stop sending");
$form['simplenews']['send']['#default_value'] = $scheduler['activated'] == 1 ? SIMPLENEWS_COMMAND_SEND_SCHEDULE : variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_NONE);
$form['simplenews']['scheduler'] = array(
'#type' => 'fieldset',
'#title' => t('Schedule details'),
'#attributes' => array(
'class' => 'schedule_info',
),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#tree' => TRUE,
);
if (!isset($form['#node']->simplenews_scheduler_edition)) {
$form['simplenews']['scheduler']['send_interval'] = array(
'#type' => 'select',
'#title' => t('Send once per'),
'#options' => array(
'hour' => t('Hour'),
'day' => t('Day'),
'week' => t('Week'),
'month' => t('Month'),
),
'#description' => t('Interval to send at'),
'#default_value' => isset($scheduler['send_interval']) ? $scheduler['send_interval'] : 'week',
);
$date_start = isset($scheduler['start_date']) ? $scheduler['start_date'] : $_SERVER['REQUEST_TIME'];
$date_stop = isset($scheduler['stop_date']) ? $scheduler['stop_date'] : $_SERVER['REQUEST_TIME'] + 2 * 365 * 24 * 60 * 60;
$form_date = false;
if (isset($form['#node'])) {
if ($form['#node']->build_mode == 1) {
$date_start = date_make_date($date_start, NULL, DATE_DATETIME);
$date_stop = date_make_date($date_stop, NULL, DATE_DATETIME);
$form_date = true;
}
}
if (!$form_date) {
$date_start = date_make_date($date_start, date_default_timezone_name(), DATE_UNIX);
$date_stop = date_make_date($date_stop, date_default_timezone_name(), DATE_UNIX);
}
$date_str_start = date_format_date($date_start, 'custom', 'Y-m-d H:i');
$date_str_stop = date_format_date($date_stop, 'custom', 'Y-m-d H:i');
$form['simplenews']['scheduler']['start_date'] = array(
'#type' => 'date_select',
'#title' => t('Start sending on'),
'#default_value' => $date_str_start,
'#date_type' => DATE_DATETIME,
'#date_format' => 'm-d-Y - H:i',
'#date_timezone' => date_default_timezone_name(),
'#date_label_position' => 'none',
'#date_increment' => 1,
'#date_year_range' => '0:+3',
'#required' => TRUE,
'#description' => t('Intervals work by creating a new node at the
desired time and marking this to be sent, ensure
you have your <a href="@site">site timezones</a>
configured and <a href="@user">user timezone</a>
configured.', array(
'@site' => url('admin/settings/date-time'),
'@user' => url('user/' . $user->uid . '/edit'),
)),
);
$form['simplenews']['scheduler']['stop_type'] = array(
'#type' => 'radios',
'#title' => t('Stop sending'),
'#default_value' => isset($scheduler['stop_type']) ? $scheduler['stop_type'] : 0,
'#options' => array(
t('Never'),
t('On a given date'),
t('After a maximum number of editions'),
),
'#attributes' => array(
'class' => 'simplenews-command-stop',
),
);
$form['simplenews']['scheduler']['stop_date'] = array(
'#type' => 'date_select',
'#default_value' => $date_str_stop,
'#date_type' => DATE_DATETIME,
'#date_format' => 'm-d-Y - H:i',
'#date_timezone' => date_default_timezone_name(),
'#date_label_position' => 'none',
'#date_increment' => 1,
'#date_year_range' => '2010:+3',
'#required' => TRUE,
);
$form['simplenews']['scheduler']['stop_edition'] = array(
'#type' => 'textfield',
'#default_value' => isset($scheduler['stop_edition']) ? $scheduler['stop_edition'] : 0,
'#size' => 5,
'#maxlength' => 5,
'#required' => TRUE,
'#description' => t('The maximum number of editions which should be sent.'),
);
$form['simplenews']['scheduler']['php_eval'] = array(
'#type' => 'textarea',
'#title' => t('Additionally only create newsletter edition if the following code returns true'),
'#default_value' => isset($scheduler['php_eval']) ? $scheduler['php_eval'] : '',
'#required' => FALSE,
'#description' => t('Additionally evaluate the following PHP code and only issue the newsletter edition if it returns true. Do not include <?php ?> tags.'),
'#access' => user_access('use PHP for scheduling newsletters'),
);
$form['simplenews']['scheduler']['title'] = array(
'#type' => 'textfield',
'#title' => t('Title pattern for new edition nodes'),
'#description' => t('New edition nodes will have their title set to the above string, with tokens replaced.'),
'#required' => TRUE,
'#default_value' => isset($scheduler['title']) ? $scheduler['title'] : '[title]',
);
$form['simplenews']['scheduler']['token_help'] = array(
'#title' => t('Replacement patterns'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['simplenews']['scheduler']['token_help']['help'] = array(
'#value' => theme('token_help', array(
'node',
'global',
)),
);
$form['simplenews']['scheduler']['activated'] = array(
'#type' => 'hidden',
'#value' => $scheduler['activated'],
);
}
else {
$title .= t('This node is part of a scheduled newsletter configuration. View the original newsletter <a href="@parent">here</a>.', array(
'@parent' => url('node/' . $form['#node']->simplenews_scheduler_edition['pid']),
));
$form['simplenews']['none']['#title'] = $title;
if (count($form['attachments']['wrapper']['files']) && user_access('upload files')) {
$form['attachments']['#description'] = t('Attachments cannot be changed, this is a newsletter edition created by Simplenews Scheduler.');
$form['attachments']['wrapper']['new']['upload']['#disabled'] = TRUE;
$form['attachments']['wrapper']['new']['attach']['#disabled'] = TRUE;
foreach ($form['attachments']['wrapper']['files'] as $key => $file) {
if (is_numeric($key)) {
$form['attachments']['wrapper']['files'][$key]['description']['#disabled'] = TRUE;
$form['attachments']['wrapper']['files'][$key]['remove']['#disabled'] = TRUE;
$form['attachments']['wrapper']['files'][$key]['list']['#disabled'] = TRUE;
$form['attachments']['wrapper']['files'][$key]['weight']['#disabled'] = TRUE;
$form['buttons']['delete']['#disabled'] = TRUE;
}
}
}
}
}
}
function simplenews_scheduler_submit($form, &$form_state) {
$scheduler = $form['#simplenews_scheduler'];
$nid = $form_state['values']['nid'];
$node = node_load($nid);
$send = $form_state['values']['simplenews']['send'];
switch ($send) {
case SIMPLENEWS_COMMAND_SEND_TEST:
case SIMPLENEWS_COMMAND_SEND_NOW:
$activated = 0;
break;
case SIMPLENEWS_COMMAND_SEND_SCHEDULE:
$activated = 1;
break;
}
$start_date = $form_state['values']['simplenews']['scheduler']['start_date'];
$stop_date = $form_state['values']['simplenews']['scheduler']['stop_date'];
$start_date = date_convert($start_date, DATE_DATETIME, DATE_UNIX, date_default_timezone_name());
$stop_date = date_convert($stop_date, DATE_DATETIME, DATE_UNIX, date_default_timezone_name());
$record = array(
'nid' => $nid,
'activated' => $activated,
'send_interval' => $form_state['values']['simplenews']['scheduler']['send_interval'],
'start_date' => $start_date,
'stop_type' => $form_state['values']['simplenews']['scheduler']['stop_type'],
'stop_date' => $stop_date,
'stop_edition' => $form_state['values']['simplenews']['scheduler']['stop_edition'],
'php_eval' => $form_state['values']['simplenews']['scheduler']['php_eval'],
'title' => $form_state['values']['simplenews']['scheduler']['title'],
);
$record += $scheduler;
if (!isset($scheduler['next_run'])) {
$record['next_run'] = $start_date;
}
db_query("DELETE FROM {simplenews_scheduler} WHERE nid = %d", $nid);
$result = drupal_write_record('simplenews_scheduler', $record);
if (!$result) {
drupal_set_message(t('Saving or updating schedule settings for <em>@title</em> has been unsuccessful.', array(
'@title' => $node->title,
)), 'error');
}
else {
drupal_set_message(t('Newsletter Schedule preferences saved'));
}
}
function simplenews_scheduler_nodeapi(&$node, $op) {
if (in_array($node->type, variable_get('simplenews_content_types', array(
'simplenews',
)))) {
switch ($op) {
case 'load':
if (isset($node->nid)) {
$result = db_query("SELECT * FROM {simplenews_scheduler} WHERE nid = %d", $node->nid);
$row = db_fetch_array($result);
if ($row) {
$node->simplenews_scheduler = $row;
}
else {
$result = db_query("SELECT * FROM {simplenews_scheduler_editions} WHERE eid = %d", $node->nid);
$row = db_fetch_array($result);
if ($row) {
$node->simplenews_scheduler_edition = $row;
}
}
}
break;
case 'delete':
db_query("DELETE FROM {simplenews_scheduler} WHERE nid = %d", $node->nid);
break;
case 'view':
break;
}
}
}
function simplenews_scheduler_cron() {
$now_time = $_SERVER['REQUEST_TIME'];
$newsletters_to_send = simplenews_scheduler_get_newsletters_due($now_time);
foreach ($newsletters_to_send as $newsletter_parent_data) {
$pid = $newsletter_parent_data->nid;
$edition_time = simplenews_scheduler_calculate_edition_time($newsletter_parent_data, $now_time);
$eid = _simplenews_scheduler_new_edition($pid, $edition_time);
simplenews_scheduler_scheduler_update($newsletter_parent_data, $now_time);
_simplenews_scheduler_send_new_edition($edition_time, $newsletter_parent_data, $eid);
}
}
function simplenews_scheduler_scheduler_update($newsletter_parent_data, $now_time) {
$newsletter_parent_data->next_run = simplenews_scheduler_calculate_next_run_time($newsletter_parent_data, $now_time);
drupal_write_record('simplenews_scheduler', $newsletter_parent_data, 'nid');
}
function simplenews_scheduler_calculate_edition_time($newsletter_parent_data, $now_time) {
$offset_string = _simplenews_scheduler_make_time_offset($newsletter_parent_data->send_interval, 1);
if ($newsletter_parent_data->last_run) {
$start_date = date('Y-m-d H:i:s', $newsletter_parent_data->last_run);
}
else {
$start_date = date('Y-m-d H:i:s', $newsletter_parent_data->start_date);
}
$pointer_date = new DateTime($start_date);
while ($pointer_date
->getTimestamp() <= $now_time) {
$timestamp_old = $pointer_date
->getTimestamp();
$pointer_date
->modify($offset_string);
if ($pointer_date
->getTimestamp() > $now_time) {
return $timestamp_old;
}
}
}
function simplenews_scheduler_calculate_next_run_time($newsletter_parent_data, $now_time) {
$offset_string = _simplenews_scheduler_make_time_offset($newsletter_parent_data->send_interval, 1);
if ($newsletter_parent_data->last_run) {
$start_date = date('Y-m-d H:i:s', $newsletter_parent_data->last_run);
}
else {
$start_date = date('Y-m-d H:i:s', $newsletter_parent_data->start_date);
}
$pointer_date = new DateTime($start_date);
while ($pointer_date
->getTimestamp() <= $now_time) {
$pointer_date
->modify($offset_string);
}
return $pointer_date
->getTimestamp();
}
function _simplenews_scheduler_make_time_offset($interval, $frequency) {
$offset_string = "+{$frequency} {$interval}";
return $offset_string;
}
function simplenews_scheduler_get_newsletters_due($timestamp) {
$result = db_query("SELECT * FROM {simplenews_scheduler} WHERE activated = 1 AND next_run <= %d AND (stop_date > %d OR stop_date = 0)", $timestamp);
$newsletters = array();
while ($newsletter_parent_data = db_fetch_object($result)) {
$stop = $newsletter_parent_data->stop_type;
$stop_edition = $newsletter_parent_data->stop_edition;
if ($stop == 2 && $serial >= $stop_edition) {
continue;
}
if (strlen($newsletter_parent_data->php_eval)) {
$eval_result = eval($newsletter_parent_data->php_eval);
if (!$eval_result) {
continue;
}
}
$nid = $newsletter_parent_data->nid;
$newsletters[$nid] = $newsletter_parent_data;
}
return $newsletters;
}
function _simplenews_scheduler_send_new_edition($edition_time, $newsletter_parent_data, $eid) {
$pid = $newsletter_parent_data->nid;
db_query("UPDATE {simplenews_scheduler} SET last_run = %d WHERE nid = %d", $edition_time, $pid);
$node = node_load($eid);
$tid = db_result(db_query("SELECT tid from {simplenews_newsletters} WHERE nid = %d", $node->nid));
$accounts = simplenews_scheduler_get_newsletter_accounts($tid);
module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
simplenews_send_node($node, $accounts);
}
function simplenews_scheduler_get_newsletter_accounts($newsletter_tid) {
$query = '
SELECT DISTINCT ss.snid, ss.*, u.name
FROM {simplenews_subscriptions} ss
LEFT JOIN {users} u
ON ss.uid = u.uid
INNER JOIN {simplenews_snid_tid} s
ON ss.snid = s.snid
AND s.tid = %d AND s.status = 1';
$result = db_query($query, $newsletter_tid);
$accounts = array();
while ($account = db_fetch_object($result)) {
$account->tids = array(
$newsletter_tid,
);
$accounts[] = $account;
}
return $accounts;
}
function simplenews_scheduler_node_page($node) {
drupal_set_title(t('Scheduled newsletter editions'));
$nid = _simplenews_scheduler_get_pid($node);
if ($nid == $node->nid) {
$output .= '<p>' . t('This is the original newsletter of which all editions are based on.') . '</p>';
}
else {
$output .= '<p>' . t('This node is part of a scheduled newsletter configuration. View the original newsletter <a href="@parent">here</a>.', array(
'@parent' => url('node/' . $nid),
)) . '</p>';
}
$result = pager_query("SELECT * FROM {simplenews_scheduler_editions} sse LEFT JOIN {node} n ON n.nid = sse.pid WHERE sse.pid = %d", 20, 0, NULL, $nid);
while ($row = db_fetch_object($result)) {
$node = node_load($row->eid);
$rows[] = array(
format_date($row->date_issued, 'custom', 'Y-m-d H:i'),
l($node->title, 'node/' . $row->eid),
);
}
if (!empty($rows)) {
$output .= theme('table', array(
t('Date sent'),
t('Node'),
), $rows, array(
'class' => 'schedule_history',
));
$output .= theme('pager', 20);
}
else {
$output .= '<p>' . t('No scheduled newsletters have been sent.') . '</p>';
}
return $output;
}
function _simplenews_scheduler_tab_permission($node) {
if (in_array($node->type, variable_get('simplenews_content_types', array(
'simplenews',
))) && user_access('overview scheduled newsletters')) {
$pid = _simplenews_scheduler_get_pid($node);
return !empty($pid);
}
else {
return FALSE;
}
}
function _simplenews_scheduler_get_full_html_format() {
$formats = filter_formats();
foreach ($formats as $index => $format) {
if (stristr($format->name, 'Full HTML')) {
return $index;
}
}
return false;
}
function _simplenews_scheduler_new_edition($nid, $edition_time) {
$node = node_load($nid);
if (module_exists('upload')) {
$files = upload_load($node);
}
global $user;
if ($user->uid) {
$original_user = $user;
$old_state = session_save_session();
session_save_session(FALSE);
$user = user_load(0);
}
$node = node_build_content($node, FALSE, FALSE);
$content = drupal_render($node->content);
$node->teaser = node_teaser($node->body, isset($node->format) ? $node->format : NULL);
if (isset($original_user)) {
$user = $original_user;
session_save_session($old_state);
}
$terms = $node->taxonomy;
if ($format_id = _simplenews_scheduler_get_full_html_format()) {
$node->format = $format_id;
}
$node->simplenews['send'] = 1;
unset($node->nid, $node->created, $node->path);
$node->is_edition = TRUE;
$node->created = $edition_time;
$title_pattern = $node->simplenews_scheduler['title'];
$node->title = token_replace($title_pattern, 'node', $node);
drupal_alter('simplenews_scheduler_edition_node', $node);
node_save($node);
taxonomy_node_save($node, $terms);
watchdog('simplenews_sched', 'Saved new node ready to be sent. Node ID: !nid', array(
'!nid' => $node->nid,
));
if (isset($files) && count($files)) {
foreach ($files as $file) {
db_query_range("INSERT INTO {files} (uid, filename, filepath, filemime, filesize, status, timestamp) (SELECT uid, filename, filepath, filemime, filesize, status, timestamp FROM {files} WHERE filename = '%s')", $file->filename, 0, 1);
db_query("INSERT INTO {upload} (fid, nid, vid, list, description, weight) VALUES ((SELECT MAX(fid) AS fid FROM files WHERE filename = '%s'), %d, %d, %d, '%s', %d)", $file->filename, $node->nid, $node->vid, $file->list, $file->description, $file->weight);
}
}
db_query("UPDATE {simplenews_newsletters} SET s_status=1 WHERE nid=%d", $node->nid);
if ($newsletter = db_fetch_array(db_query("SELECT * from {simplenews_newsletters} WHERE nid = %d", $nid))) {
db_query("UPDATE {simplenews_newsletters} SET s_status = 1, tid = %d, s_format = '%s', priority = %d, receipt = %d WHERE nid=%d", $newsletter['tid'], $newsletter['s_format'], $newsletter['priority'], $newsletter['receipt'], $node->nid);
}
db_query("INSERT INTO {simplenews_scheduler_editions} (eid, pid, date_issued) VALUES (%d, %d, %d)", $node->nid, $nid, $edition_time);
return $node->nid;
}
function _simplenews_scheduler_get_pid($node) {
$nid = FALSE;
if (isset($node->simplenews_scheduler_edition)) {
$nid = $node->simplenews_scheduler_edition['pid'];
}
elseif (isset($node->simplenews_scheduler)) {
$nid = $node->nid;
}
return $nid;
}