View source
<?php
define("SCHEDULER_DATE_FORMAT", 'Y-m-d H:i:s');
function scheduler_help($section) {
if ($section == 'admin/modules#description') {
return t('A module to schedule when nodes are (un)published.');
}
}
function scheduler_perm() {
return array(
'schedule (un)publishing of nodes',
'administer scheduler',
);
}
function scheduler_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'scheduler/cron',
'type' => MENU_CALLBACK,
'callback' => '_scheduler_run_cron',
'access' => TRUE,
);
$items[] = array(
'path' => 'scheduler/timecheck',
'type' => MENU_CALLBACK,
'callback' => '_scheduler_timecheck',
'access' => user_access('schedule (un)publishing of nodes'),
);
}
$items[] = array(
'path' => 'admin/settings/scheduler',
'title' => t('Scheduler module settings'),
'callback' => 'drupal_get_form',
'callback arguments' => 'scheduler_admin',
'access' => user_access('administer scheduler'),
'type' => MENU_NORMAL_ITEM,
);
$items[] = array(
'path' => 'admin/content/node/scheduler',
'type' => MENU_LOCAL_TASK,
'title' => t('Scheduled'),
'callback' => 'scheduler_list',
'access' => user_access('administer nodes') && user_access('schedule (un)publishing of nodes'),
'weight' => 10,
);
return $items;
}
function scheduler_admin() {
$form['scheduler_date_format'] = array(
'#type' => 'textfield',
'#title' => t('Date format'),
'#default_value' => variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT),
'#size' => 20,
'#maxlength' => 100,
'#description' => t('The input format for the (un)scheduling time/date. See the date() function for formatting options: http://www.php.net/manual/en/function.date.php'),
);
return system_settings_form($form);
}
function scheduler_form_alter($form_id, &$form) {
if ('node_type_form' == $form_id) {
$form['workflow']['scheduler'] = array(
'#type' => 'checkbox',
'#title' => t('Enable scheduled (un)publishing'),
'#default_value' => variable_get('scheduler_' . $form['#node_type']->type, 0),
'#description' => t('Check this box to enable scheduled (un)publishing for this node type.'),
);
$form['workflow']['scheduler_touch'] = array(
'#type' => 'checkbox',
'#title' => t('Alter published on time'),
'#default_value' => variable_get('scheduler_touch_' . $form['#node_type']->type, 0),
'#description' => t('Check this box to alter the published on time to match the scheduled time ("touch feature").'),
);
}
else {
if (isset($form['type']['#value']) && $form['type']['#value'] . '_node_form' == $form_id) {
if (user_access('schedule (un)publishing of nodes')) {
if (variable_get('scheduler_' . $form['type']['#value'], 0) == 1) {
$form['#validate']['_scheduler_form_validate'] = array();
$jscalendar = FALSE;
if (module_exists('jscalendar')) {
$jscalendar = TRUE;
}
$node = $form['#node'];
if ($node->nid > 0) {
$defaults = db_fetch_object(db_query('SELECT publish_on, unpublish_on FROM {scheduler} WHERE nid = %d', $node->nid));
}
else {
$defaults = new StdClass();
$defaults->publish_on = $defaults->unpublish_on = NULL;
}
$form['scheduler_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Scheduling options'),
'#collapsible' => TRUE,
'#collapsed' => $defaults->publish_on != 0 || $defaults->unpublish_on != 0 ? FALSE : TRUE,
'#weight' => 35,
);
$date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT);
$form['scheduler_settings']['publish_on'] = array(
'#type' => 'textfield',
'#title' => t('Publish on'),
'#maxlength' => 25,
'#default_value' => $defaults->publish_on ? format_date($defaults->publish_on, 'custom', $date_format) : '',
'#description' => t('Format: %time. Leave blank to disable scheduled publishing.', array(
'%time' => format_date(time(), 'custom', $date_format),
)),
'#attributes' => $jscalendar ? array(
'class' => 'jscalendar',
) : array(),
'#jscalendar_timeFormat' => _scheduler_get_jscalendar_time_format(),
'#jscalendar_ifFormat' => _scheduler_date_format_in_strftime_syntax(),
);
$form['scheduler_settings']['unpublish_on'] = array(
'#type' => 'textfield',
'#title' => t('Unpublish on'),
'#maxlength' => 25,
'#default_value' => $defaults->unpublish_on ? format_date($defaults->unpublish_on, 'custom', $date_format) : '',
'#description' => t('Format: %time. Leave blank to disable scheduled unpublishing.', array(
'%time' => format_date(time(), 'custom', $date_format),
)),
'#attributes' => $jscalendar ? array(
'class' => 'jscalendar',
) : array(),
'#jscalendar_timeFormat' => _scheduler_get_jscalendar_time_format(),
'#jscalendar_ifFormat' => _scheduler_date_format_in_strftime_syntax(),
);
}
}
}
}
}
function scheduler_list() {
$header = array(
array(
'data' => t('Title'),
'field' => 'n.title',
),
array(
'data' => t('Author'),
'field' => 'u.name',
),
array(
'data' => t('Publish on'),
'field' => 's.publish_on',
),
array(
'data' => t('Unpublish on'),
'field' => 's.unpublish_on',
),
array(
'data' => t('Operations'),
),
);
if (!isset($_GET['order']) && !isset($_GET['sort'])) {
$_GET['order'] = t('Publish on');
$_GET['sort'] = 'ASC';
}
$sql = 'SELECT n.nid, n.uid, n.status, u.name, n.title, s.publish_on, s.unpublish_on FROM {scheduler} s LEFT JOIN {node} n ON s.nid = n.nid LEFT JOIN {users} u ON n.uid = u.uid' . tablesort_sql($header);
$result = pager_query($sql, 50);
while ($node = db_fetch_object($result)) {
$rows[] = array(
l($node->title, "node/{$node->nid}"),
theme('username', $node),
$node->publish_on ? format_date($node->publish_on) : ' ',
$node->unpublish_on ? format_date($node->unpublish_on) : ' ',
l(t('edit'), 'node/' . $node->nid . '/edit', array(), 'destination=admin/content/node/scheduler'),
);
}
if (count($rows)) {
if ($pager = theme('pager', NULL, 50, 0)) {
$rows[] = array(
array(
'data' => $pager,
'colspan' => 6,
),
);
}
print theme('page', theme('table', $header, $rows));
}
else {
print theme('page', t('There are no scheduled nodes.'));
}
}
function _scheduler_date_format_in_strftime_syntax() {
$date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT);
$date_entities = array(
'd',
'H',
'h',
'm',
'i',
'a',
'A',
's',
'y',
'Y',
);
$strftime_replacements = array(
'%d',
'%H',
'%I',
'%m',
'%M',
'%p',
'%p',
'%S',
'%y',
'%Y',
);
return str_replace($date_entities, $strftime_replacements, $date_format);
}
function _scheduler_get_jscalendar_time_format() {
$date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT);
$result = strpos($date_format, stristr($date_format, "a"));
return $result !== FALSE ? '12' : '24';
}
function _scheduler_strtotime($str) {
if ($str && trim($str) != "") {
$time = _scheduler_strptime(trim($str), variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT));
if ($time !== FALSE) {
$time -= _scheduler_get_user_timezone();
}
}
else {
$time = NULL;
}
return $time;
}
function _scheduler_strptime($date, $format) {
$date_entities = array(
'd',
'H',
'h',
'm',
'i',
'a',
'A',
's',
'y',
'Y',
);
$date_regex_replacements = array(
'(\\d{2})',
'(\\d{2})',
'(\\d{2})',
'(\\d{2})',
'(\\d{2})',
'([ap]m)',
'([AP]M)',
'(\\d{2})',
'(\\d{2})',
'(\\d{4})',
);
$custom_pattern = str_replace($date_entities, $date_regex_replacements, $format);
if (!preg_match("#{$custom_pattern}#", $date, $value_matches)) {
return FALSE;
}
if (!preg_match_all("/(\\w)/", $format, $entity_matches)) {
return FALSE;
}
$results = array(
'day' => 0,
'hour' => 0,
'month' => 0,
'minute' => 0,
'meridiem' => NULL,
'second' => 0,
'year' => 0,
);
$index = 1;
foreach ($entity_matches[1] as $entity) {
$value = intval($value_matches[$index]);
switch ($entity) {
case 'd':
$results['day'] = $value;
break;
case 'H':
case 'h':
$results['hour'] = $value;
break;
case 'm':
$results['month'] = $value;
break;
case 'i':
$results['minute'] = $value;
break;
case 'a':
case 'A':
$results['meridiem'] = $value_matches[$index];
break;
case 's':
$results['second'] = $value;
break;
case 'y':
case 'Y':
$results['year'] = $value;
break;
}
$index++;
}
if (strncasecmp($results['meridiem'], "pm", 2) == 0 && $results['hour'] <= 12) {
$results['hour'] += 12;
}
$time = gmmktime($results['hour'], $results['minute'], $results['second'], $results['month'], $results['day'], $results['year']);
return $time;
}
function _scheduler_get_user_timezone() {
global $user;
$timezone = variable_get('date_default_timezone', 0);
if (variable_get('configurable_timezones', 1) == 1 && strlen($user->timezone)) {
$timezone = $user->timezone;
}
return $timezone;
}
function _scheduler_form_validate($form_id, $form) {
$publishtime = NULL;
$unpublishtime = NULL;
if (isset($form['publish_on'])) {
$publishtime = _scheduler_strtotime($form['publish_on']);
if ($publishtime === FALSE) {
form_set_error('publish_on', t('The entered publication date is invalid.'));
}
}
if (isset($form['unpublish_on'])) {
$unpublishtime = _scheduler_strtotime($form['unpublish_on']);
if ($unpublishtime === FALSE) {
form_set_error('unpublish_on', t('The entered expiration date is invalid.'));
}
}
if (is_integer($publishtime) && is_integer($unpublishtime) && $unpublishtime < $publishtime) {
form_set_error('unpublish_on', t("The expiration date is before publication date."));
}
}
function scheduler_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if ($op == 'load') {
if (isset($node->nid) && $node->nid && variable_get('scheduler_' . $node->type, 0) == 1) {
$result = db_query('SELECT * FROM {scheduler} WHERE nid = %d', $node->nid);
if ($result) {
$row = db_fetch_array($result);
if (isset($row['nid'])) {
unset($row['nid']);
$node->publish_on = $row['publish_on'];
$node->unpublish_on = $row['unpublish_on'];
$date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT);
$row['published'] = $row['publish_on'] ? format_date($row['publish_on'], 'custom', $date_format) : NULL;
$row['unpublished'] = $row['unpublish_on'] ? format_date($row['unpublish_on'], 'custom', $date_format) : NULL;
$node->scheduler = $row;
}
}
}
}
elseif (user_access('schedule (un)publishing of nodes')) {
switch ($op) {
case 'view':
if ($page && $node->unpublish_on) {
$unavailable_after = date("d-M-Y H:i:s T", $node->unpublish_on);
drupal_set_html_head('<meta name="googlebot" content="unavailable_after: ' . $unavailable_after . '">');
}
break;
case 'submit':
$node->publish_on = _scheduler_strtotime($node->publish_on);
$node->unpublish_on = _scheduler_strtotime($node->unpublish_on);
if ($node->publish_on != '' && is_numeric($node->publish_on) && $node->publish_on > time()) {
$node->status = 0;
}
break;
case 'insert':
if (isset($node->nid) && $node->nid && $node->publish_on != NULL || $node->unpublish_on != NULL) {
db_query('INSERT INTO {scheduler} (nid, publish_on, unpublish_on) VALUES (%d, %d, %d)', $node->nid, $node->publish_on, $node->unpublish_on);
}
break;
case 'update':
if (isset($node->nid) && $node->nid) {
$exists = db_result(db_query('SELECT nid FROM {scheduler} WHERE nid = %d', $node->nid));
if ($exists) {
if ($node->publish_on != NULL || $node->unpublish_on != NULL) {
db_query('UPDATE {scheduler} SET publish_on = %d, unpublish_on = %d WHERE nid = %d', $node->publish_on, $node->unpublish_on, $node->nid);
}
else {
db_query('DELETE FROM {scheduler} WHERE nid = %d', $node->nid);
}
}
else {
if ($node->publish_on != NULL || $node->unpublish_on != NULL) {
db_query('INSERT INTO {scheduler} (nid, publish_on, unpublish_on) VALUES (%d, %d, %d)', $node->nid, $node->publish_on, $node->unpublish_on);
}
}
}
break;
case 'delete':
if (isset($node->nid) && $node->nid) {
db_query('DELETE FROM {scheduler} WHERE nid = %d', $node->nid);
}
break;
}
}
}
function scheduler_cron() {
$clear_cache = FALSE;
$nodes = db_query('SELECT * FROM {scheduler} s LEFT JOIN {node} n ON s.nid = n.nid WHERE n.status = 0 AND s.publish_on > 0 AND s.publish_on < %d', time());
while ($node = db_fetch_object($nodes)) {
$n = node_load($node->nid);
$n->changed = $node->publish_on;
if (variable_get('scheduler_touch_' . $n->type, 0) == 1) {
$n->created = $node->publish_on;
}
$n->status = 1;
node_save($n);
if ($n->unpublish_on == 0) {
db_query('DELETE FROM {scheduler} WHERE nid = %d', $n->nid);
}
else {
db_query('UPDATE {scheduler} SET publish_on = 0 WHERE nid = %d', $n->nid);
}
_scheduler_scheduler_api($n, 'publish');
watchdog('content', t('@type: scheduled publishing of %title.', array(
'@type' => $n->type,
'%title' => $n->title,
)), WATCHDOG_NOTICE, l(t('view'), 'node/' . $n->nid));
$clear_cache = TRUE;
}
$nodes = db_query('SELECT * FROM {scheduler} s LEFT JOIN {node} n ON s.nid = n.nid WHERE n.status = 1 AND s.unpublish_on > 0 AND s.unpublish_on < %d', time());
while ($node = db_fetch_object($nodes)) {
$n = node_load($node->nid);
$n->changed = $node->unpublish_on;
$n->status = 0;
node_save($n);
db_query('DELETE FROM {scheduler} WHERE nid = %d', $n->nid);
_scheduler_scheduler_api($n, 'unpublish');
watchdog('content', t('@type: scheduled unpublishing of %title.', array(
'@type' => $n->type,
'%title' => $n->title,
)), WATCHDOG_NOTICE, l(t('view'), 'node/' . $n->nid));
$clear_cache = TRUE;
}
if ($clear_cache) {
cache_clear_all();
}
}
function _scheduler_run_cron() {
scheduler_cron();
if (ob_get_level() > 0) {
ob_clean();
}
exit;
}
function _scheduler_scheduler_api($node, $action) {
foreach (module_implements('scheduler_api') as $module) {
$function = $module . '_scheduler_api';
$function($node, $action);
}
}
function _scheduler_timecheck() {
$now = time();
return theme('scheduler_timecheck', $now);
}
function theme_scheduler_timecheck($now) {
drupal_set_title(t('Scheduler OS time check'));
$t_options = array(
'%time' => gmdate("Y-m-d H:i:s", $now),
'%lt' => date("Y-m-d H:i:s P", $now),
);
return t('Your server reports the UTC time as %time and "localtime" as %lt.', $t_options) . '<p />' . t('If all is well with your server\'s time configuration UTC should match <a target="_blank" href="http://wwp.greenwichmeantime.com/">UTC London Time</a> and the localtime should be the time where you are.') . '<p />' . t('If this is not the case please have your Unix System Administrator fix your servers time/date configuration.');
}
function scheduler_views_tables() {
$tables['scheduler'] = array(
'name' => 'scheduler',
'join' => array(
'left' => array(
'table' => 'node',
'field' => 'nid',
),
'right' => array(
'field' => 'nid',
),
),
'fields' => array(
'publish_on' => array(
'name' => t('Scheduler: publish on'),
'help' => t('Date/time on which the article will be automatically published'),
'sortable' => TRUE,
'handler' => views_handler_field_dates(),
'option' => 'string',
),
'unpublish_on' => array(
'name' => t('Scheduler: unpublish on'),
'help' => t('Date/time on which the article will be automatically un-published'),
'sortable' => TRUE,
'handler' => views_handler_field_dates(),
'option' => 'string',
),
),
'sorts' => array(
'publish_on' => array(
'name' => t('Scheduler: publish on'),
'help' => t('Sort by the date the article will be automatically published.'),
),
'unpublish_on' => array(
'name' => t('Scheduler: unpublish on'),
'help' => t('Sort by the date/time on which the article will be automatically un-published.'),
),
),
'filters' => array(
'publish_on' => array(
'name' => t('Scheduler: publish on'),
'help' => t('This filter allows nodes to be filtered by the date they will be automatically published.') . ' ' . views_t_strings('filter date'),
'operator' => 'views_handler_operator_gtlt',
'value' => views_handler_filter_date_value_form(),
'handler' => 'views_handler_filter_timestamp',
'option' => 'string',
),
'unpublish_on' => array(
'name' => t('Scheduler: unpublish on'),
'help' => t('This filter allows nodes to be filtered by the date they will be automatically un-published.') . ' ' . views_t_strings('filter date'),
'operator' => 'views_handler_operator_gtlt',
'value' => views_handler_filter_date_value_form(),
'handler' => 'views_handler_filter_timestamp',
'option' => 'string',
),
),
);
return $tables;
}