View source
<?php
define('SIMPLENEWS_COMMAND_SEND_SCHEDULE', 4);
define('SIMPLENEWS_COMMAND_SEND_NONE', 5);
function simplenews_scheduler_permission() {
return array(
'overview scheduled newsletters' => array(
'title' => t('View scheduled newsletters'),
'description' => t('Access overview page for scheduled newsletters.'),
),
'send scheduled newsletters' => array(
'title' => t('Send scheduled newsletters'),
'description' => t('Allows users to use scheduled newsletter sending option.'),
),
);
}
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')) {
$node = node_load($form['nid']['#value']);
if (isset($form['simplenews']['send']) && !isset($node->simplenews_scheduler_edition)) {
$form['#submit'][] = "simplenews_scheduler_submit";
$scheduler = array();
$record = db_select('simplenews_scheduler', 's')
->fields('s')
->condition('nid', $node->nid)
->execute()
->fetchAssoc();
if (!empty($record)) {
$scheduler = $record;
}
else {
$scheduler['activated'] = 0;
}
$form_state['simplenews_scheduler'] = $scheduler;
if ($scheduler['activated'] == 0) {
$form['simplenews']['send']['#options'] += array(
SIMPLENEWS_COMMAND_SEND_SCHEDULE => t('Send newsletter according to schedule'),
);
}
else {
$form['simplenews']['send']['#options'] += array(
SIMPLENEWS_COMMAND_SEND_NONE => t("Stop newsletter schedule"),
);
drupal_set_message(t('Newsletter Schedule will send again on @next_run', array(
'@next_run' => format_date($record['next_run']),
)));
}
$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' => array(
'schedule-info',
),
),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#states' => array(
'visible' => array(
':input[name="simplenews[send]"]' => array(
'value' => (string) SIMPLENEWS_COMMAND_SEND_SCHEDULE,
),
),
),
);
$start_date = !empty($scheduler['start_date']) ? $scheduler['start_date'] : REQUEST_TIME;
$stop_date = !empty($scheduler['stop_date']) ? $scheduler['stop_date'] : REQUEST_TIME + 2 * 365 * 24 * 60 * 60;
$form['simplenews']['scheduler']['start_date'] = array(
'#type' => 'date_select',
'#title' => t('Start sending on'),
'#default_value' => date('Y-m-d H:i', $start_date),
'#required' => TRUE,
'#date_format' => 'Y-m-d H:i',
'#date_label_position' => 'within',
'#date_year_range' => '-0:+3',
'#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/config/date-time'),
'@user' => url('user/' . $user->uid . '/edit'),
)),
);
$intervals = array(
'hour' => t('Hour'),
'day' => t('Day'),
'week' => t('Week'),
'month' => t('Month'),
);
$form['simplenews']['scheduler']['interval'] = array(
'#type' => 'select',
'#title' => t('Sending interval'),
'#options' => $intervals,
'#description' => t('Interval to send at'),
'#default_value' => !empty($scheduler['send_interval']) ? $scheduler['send_interval'] : 'week',
);
$form['simplenews']['scheduler']['frequency'] = array(
'#type' => 'textfield',
'#title' => t('Interval frequency'),
'#size' => 5,
'#default_value' => !empty($scheduler['interval_frequency']) ? $scheduler['interval_frequency'] : 1,
'#description' => t('Set the number of Intervals between newsletter transmission.'),
);
$stoptypes = array(
t('Never'),
t('On a given date'),
t('After a maximum number of editions'),
);
$form['simplenews']['scheduler']['stoptype'] = array(
'#type' => 'radios',
'#title' => t('Stop sending'),
'#options' => $stoptypes,
'#default_value' => !empty($scheduler['stop_type']) ? $scheduler['stop_type'] : 0,
'#attributes' => array(
'class' => array(
'simplenews-command-stop',
),
),
);
$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.'),
'#states' => array(
'visible' => array(
':input[name="simplenews[scheduler][stoptype]"]' => array(
'value' => (string) 2,
),
),
),
);
$form['simplenews']['scheduler']['stop_date'] = array(
'#type' => 'date_select',
'#title' => t('Stop sending on'),
'#default_value' => date('Y-m-d H:i', $stop_date),
'#required' => TRUE,
'#date_format' => 'Y-m-d H:i',
'#date_label_position' => 'within',
'#date_year_range' => '-0:+3',
'#description' => t('The date when the last sent newsletter will be sent.'),
'#states' => array(
'visible' => array(
':input[name="simplenews[scheduler][stoptype]"]' => array(
'value' => (string) 1,
),
),
),
);
$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 settings'),
);
$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'] : '[node:title]',
);
$form['simplenews']['scheduler']['token_help'] = array(
'#title' => t('Replacement patterns'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['simplenews']['scheduler']['token_help']['help'] = array(
'#theme' => 'token_tree',
'#token_types' => array(
'node',
),
);
$form['simplenews']['scheduler']['activated'] = array(
'#type' => 'value',
'#value' => $scheduler['activated'],
);
}
elseif (isset($node->simplenews_scheduler_edition)) {
$form['simplenews']['none']['#title'] = t('This node is part of a scheduled newsletter configuration. View the original newsletter <a href="@parent">here</a>.', array(
'@parent' => url('node/' . $node->simplenews_scheduler_edition->pid),
));
}
}
}
function simplenews_scheduler_submit($form, &$form_state) {
$scheduler = $form_state['simplenews_scheduler'];
$nid = $form_state['values']['nid'];
$node = node_load($nid);
$send = $form_state['values']['simplenews']['send'];
$stoptype = $form_state['values']['simplenews']['scheduler']['stoptype'];
$start_date = strtotime($form_state['values']['simplenews']['scheduler']['start_date']);
$stop_date = $stoptype == 1 ? strtotime($form_state['values']['simplenews']['scheduler']['stop_date']) : 0;
$record = array(
'nid' => $nid,
'activated' => $send == SIMPLENEWS_COMMAND_SEND_SCHEDULE ? 1 : 0,
'send_interval' => $form_state['values']['simplenews']['scheduler']['interval'],
'interval_frequency' => $form_state['values']['simplenews']['scheduler']['frequency'],
'start_date' => $start_date,
'stop_type' => $stoptype,
'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'],
);
if (!isset($scheduler['next_run']) || isset($scheduler['activated']) && $scheduler['activated'] == 0) {
$record['next_run'] = $start_date;
$record['last_run'] = 0;
}
db_merge('simplenews_scheduler')
->key(array(
'nid' => $nid,
))
->fields($record)
->execute();
drupal_set_message(t('Newsletter Schedule preferences have been saved.'));
}
function simplenews_scheduler_node_load($nodes, $types) {
$nids = array_keys($nodes);
$result = db_select('simplenews_scheduler', 's')
->fields('s')
->condition('nid', $nids, 'IN')
->execute()
->fetchAll();
foreach ($result as $key => $record) {
$nodes[$record->nid]->simplenews_scheduler = $record;
}
$result = db_select('simplenews_scheduler_editions', 's')
->fields('s')
->condition('eid', $nids, 'IN')
->execute()
->fetchAll();
foreach ($result as $key => $record) {
$nodes[$record->eid]->simplenews_scheduler_edition = $record;
$nodes[$record->eid]->is_edition = TRUE;
$nodes[$record->eid]->simplenews_edition_parent = $record->pid;
}
}
function simplenews_scheduler_node_delete($node) {
db_delete('simplenews_scheduler')
->condition('nid', $node->nid)
->execute();
db_delete('simplenews_scheduler_editions')
->condition('eid', $node->nid)
->execute();
}
function simplenews_scheduler_node_view($node) {
if (isset($node->simplenews_scheduler_edition) && user_access('send scheduled newsletters')) {
drupal_set_message(t('This is a newsletter edition. View the the master template of this newsletter <a href="!master_url">here</a>', array(
'!master_url' => url('node/' . $node->simplenews_edition_parent),
)));
}
}
function simplenews_scheduler_cron() {
$now_time = REQUEST_TIME;
$newsletters_to_send = simplenews_scheduler_get_newsletters_due($now_time);
foreach ($newsletters_to_send as $newsletter_parent_data) {
$edition_time = simplenews_scheduler_calculate_edition_time($newsletter_parent_data, $now_time);
$eid = _simplenews_scheduler_new_edition($newsletter_parent_data->nid, $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, $newsletter_parent_data->interval_frequency);
$date_interval = DateInterval::createFromDateString($offset_string);
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
->add($date_interval);
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, $newsletter_parent_data->interval_frequency);
$date_interval = DateInterval::createFromDateString($offset_string);
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
->add($date_interval);
}
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 <= :now AND (stop_date > :now OR stop_date = 0)", array(
':now' => $timestamp,
));
$newsletters = array();
foreach ($result as $newsletter_parent_data) {
$pid = $newsletter_parent_data->nid;
$stop = $newsletter_parent_data->stop_type;
$stop_edition = $newsletter_parent_data->stop_edition;
$edition_count = db_query('SELECT COUNT(*) FROM {simplenews_scheduler_editions} WHERE pid = :pid', array(
':pid' => $pid,
))
->fetchField();
if ($stop == 2 && $edition_count >= $stop_edition) {
continue;
}
if (strlen($newsletter_parent_data->php_eval)) {
$eval_result = eval($newsletter_parent_data->php_eval);
if (!$eval_result) {
continue;
}
}
$newsletters[$pid] = $newsletter_parent_data;
}
return $newsletters;
}
function _simplenews_scheduler_send_new_edition($edition_time, $newsletter_parent_data, $eid) {
$pid = $newsletter_parent_data->nid;
db_update('simplenews_scheduler')
->fields(array(
'last_run' => $edition_time,
))
->condition('nid', $pid)
->execute();
$node = node_load($eid);
module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
simplenews_add_node_to_spool($node);
}
function simplenews_scheduler_clone_node($node) {
if (isset($node->nid)) {
$clone = clone $node;
$clone->nid = NULL;
$clone->vid = NULL;
$clone->tnid = NULL;
$clone->created = NULL;
$clone->book['mlid'] = NULL;
$clone->path = NULL;
$clone->clone_from_original_nid = $node->nid;
node_save($clone);
return $clone;
}
}
function simplenews_scheduler_node_page($node) {
drupal_set_title(t('Scheduled newsletter editions'));
$nid = _simplenews_scheduler_get_pid($node);
$output = '';
$rows = array();
if ($nid == $node->nid) {
$output .= '<p>' . t('This is a newsletter template node of which all corresponding editions nodes 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 = db_select('simplenews_scheduler_editions', 's')
->extend('PagerDefault')
->limit(20)
->fields('s')
->condition('s.pid', $nid)
->execute()
->fetchAll();
foreach ($result as $row) {
$node = node_load($row->eid);
$rows[] = array(
l($node->title, 'node/' . $row->eid),
format_date($row->date_issued, 'custom', 'Y-m-d H:i'),
);
}
$tablecontent = array(
'header' => array(
t('Edition Node'),
t('Date sent'),
),
'rows' => $rows,
'attributes' => array(
'class' => array(
'schedule-history',
),
),
'empty' => '<p>' . t('No scheduled newsletter editions have been sent.') . '</p>',
);
$output .= theme('table', $tablecontent);
$output .= theme('pager', array(
'tags' => 20,
));
return $output;
}
function _simplenews_scheduler_tab_permission($node) {
if (simplenews_check_node_types($node->type) && user_access('overview scheduled newsletters')) {
return !empty($node->simplenews_scheduler) || !empty($node->is_edition);
}
}
function _simplenews_scheduler_get_full_html_format() {
global $user;
$formats = filter_formats($user);
foreach ($formats as $index => $format) {
if (stristr($format->name, 'Full HTML')) {
return $index;
}
}
return false;
}
function _simplenews_scheduler_new_edition($nid, $edition_time) {
$template_node = node_load($nid);
$edition_node = simplenews_scheduler_clone_node($template_node);
$edition_node->created = $edition_time;
$schedrecord = db_select('simplenews_scheduler', 's')
->fields('s')
->condition('nid', $template_node->nid)
->execute()
->fetchAssoc();
$edition_node->title = token_replace($schedrecord['title'], array(
'node' => $template_node,
));
drupal_alter('simplenews_scheduler_edition_node', $edition_node, $template_node);
node_save($edition_node);
$values = array(
'eid' => $edition_node->nid,
'pid' => $template_node->nid,
'date_issued' => $edition_time,
);
db_insert('simplenews_scheduler_editions')
->fields($values)
->execute();
$variables = array(
'%title' => entity_label('node', $edition_node),
);
$uri = entity_uri('node', $edition_node);
$link = l(t('view'), $uri['path'], $uri['options']);
watchdog('simplenews_sched', 'Created a new newsletter edition %title', $variables, WATCHDOG_NOTICE, $link);
simplenews_newsletter_update_sent_status($edition_node);
return $edition_node->nid;
}
function _simplenews_scheduler_get_pid($node) {
if (isset($node->simplenews_scheduler_edition)) {
return $node->simplenews_scheduler_edition->pid;
}
elseif (isset($node->simplenews_scheduler)) {
return $node->nid;
}
return FALSE;
}