Drupal: Update module scheduler
This commit is contained in:
parent
43997f948c
commit
ad462cc943
@ -9,7 +9,9 @@
|
||||
* Form constructor for the main admin form for configuring Scheduler.
|
||||
*/
|
||||
function scheduler_admin() {
|
||||
$now = t('Example: %date', array('%date' => format_date(REQUEST_TIME, 'custom', variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT))));
|
||||
$now = t('Example: %date', array(
|
||||
'%date' => format_date(REQUEST_TIME, 'custom', variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT)),
|
||||
));
|
||||
$form['scheduler_date_format'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Date format'),
|
||||
@ -21,7 +23,7 @@ function scheduler_admin() {
|
||||
'#description' => t('The format for entering scheduled dates and times. For the date use the letters !date_letters and for the time use !time_letters. See !url for more details.', array(
|
||||
'!date_letters' => SCHEDULER_DATE_LETTERS,
|
||||
'!time_letters' => SCHEDULER_TIME_LETTERS,
|
||||
'!url' => l(t('the PHP date() function'), 'http://www.php.net/manual/en/function.date.php')
|
||||
'!url' => l(t('the PHP date() function'), 'http://www.php.net/manual/en/function.date.php'),
|
||||
)),
|
||||
);
|
||||
|
||||
@ -45,14 +47,14 @@ function scheduler_admin() {
|
||||
// Variable 'date_popup_timepicker' holds the type of timepicker selected.
|
||||
$timepicker_enabled = (variable_get('date_popup_timepicker', '') != 'none');
|
||||
$options = array('@date_popup_config' => url('admin/config/date/date_popup'));
|
||||
$description = t('Restrict the time entry to specific minute increments.') . ' '
|
||||
. ($timepicker_enabled
|
||||
$description[] = t('Restrict the time entry to specific minute increments.');
|
||||
$description[] = ($timepicker_enabled
|
||||
? t('The timepicker type can be selected via the <a href="@date_popup_config">Date Popup configuration page</a>.', $options)
|
||||
: t('The timepicker is not enabled - turn it on via the <a href="@date_popup_config">Date Popup configuration page</a>.', $options));
|
||||
$form['scheduler_date_popup_minute_increment'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Date Popup minute increment'),
|
||||
'#description' => $description,
|
||||
'#description' => implode(' ', $description),
|
||||
'#field_suffix' => t('minutes'),
|
||||
'#size' => 2,
|
||||
'#maxlength' => 2,
|
||||
@ -99,6 +101,14 @@ function scheduler_admin() {
|
||||
'#description' => t('The text entered into this field will be displayed above the scheduling fields in the node edit form.'),
|
||||
);
|
||||
|
||||
$form['scheduler_cache_clear_all'] = array(
|
||||
'#prefix' => '<label>' . t('Cache') . '</label>',
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Clear all expired block and page caches after publishing or unpublishing via cron.'),
|
||||
'#default_value' => variable_get('scheduler_cache_clear_all', 0),
|
||||
'#description' => t('If a node has been published or unpublished by Scheduler during a cron run, this option will clear the caches instead of relying on the Drupal core system cron task. Warning: This may have a detrimental effect on performance for large sites.'),
|
||||
);
|
||||
|
||||
// Add a submit handler function.
|
||||
$form['#submit'][] = 'scheduler_admin_submit';
|
||||
|
||||
@ -131,8 +141,12 @@ function scheduler_admin_validate($form, &$form_state) {
|
||||
// The Date Popup function date_popup_time_formats() only returns the values
|
||||
// 'H:i:s' and 'h:i:sA' but Scheduler can accept more variations than just
|
||||
// these. Firstly, we add the lowercase 'a' alternative. Secondly timepicker
|
||||
// always requires hours and minutes, but seconds are optional.
|
||||
$acceptable = array('H:i:s', 'h:i:sA', 'h:i:sa', 'H:i', 'h:iA', 'h:ia');
|
||||
// always requires hours and minutes, but seconds are optional. Spaces are
|
||||
// allowed before the 'A' or 'a'.
|
||||
$acceptable = array(
|
||||
'H:i:s', 'h:i:sA', 'h:i:s A', 'h:i:sa', 'h:i:s a',
|
||||
'H:i', 'h:iA', 'h:i A', 'h:ia', 'h:i a',
|
||||
);
|
||||
|
||||
if ($time_format && !in_array($time_format, $acceptable)) {
|
||||
form_set_error('scheduler_date_format', t('When using the Date Popup module, the allowed time formats are: !formats', array('!formats' => implode(', ', $acceptable))));
|
||||
@ -237,7 +251,7 @@ function _scheduler_form_node_type_form_alter(&$form, $form_state) {
|
||||
'#group' => 'additional_settings',
|
||||
'#attached' => array(
|
||||
'js' => array(
|
||||
'vertical-tabs' => drupal_get_path('module', 'scheduler') . "/scheduler_vertical_tabs.js",
|
||||
'vertical-tabs' => _scheduler_get_vertical_tabs_js(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -386,9 +400,10 @@ function _scheduler_form_node_type_form_alter(&$form, $form_state) {
|
||||
*/
|
||||
function _scheduler_lightweight_cron($form, &$form_state) {
|
||||
$form = array();
|
||||
$prefix_text = t("You can test Scheduler's lightweight cron process interactively");
|
||||
$form['scheduler_cron'] = array(
|
||||
'#type' => 'submit',
|
||||
'#prefix' => '<div class="container-inline">' . t("You can test Scheduler's lightweight cron process interactively") . ': ',
|
||||
'#prefix' => '<div class="container-inline">' . $prefix_text . ': ',
|
||||
'#value' => t("Run Scheduler's lightweight cron now"),
|
||||
'#submit' => array('_scheduler_lightweight_cron_submit'),
|
||||
'#suffix' => "</div>\n",
|
||||
@ -403,12 +418,6 @@ function _scheduler_lightweight_cron($form, &$form_state) {
|
||||
'#default_value' => variable_get('scheduler_lightweight_log', 1),
|
||||
'#description' => t("When this option is checked, Scheduler will write an entry to the log every time the lightweight cron process is started and completed. This is useful during set up and testing, but can result in a large number of log entries. Any actions performed during the lightweight cron run will always be logged regardless of this setting."),
|
||||
);
|
||||
$form['scheduler_cron_settings']['scheduler_cache_clear_all'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Clear all expired block and page caches after publishing or unpublishing via cron.'),
|
||||
'#default_value' => variable_get('scheduler_cache_clear_all', 0),
|
||||
'#description' => t('If a node has been published or unpublished by Scheduler during a cron run, this option will clear the caches instead of relying on the Drupal core system cron task. Warning: This may have a detrimental effect on performance for large sites.'),
|
||||
);
|
||||
$form['scheduler_cron_settings']['scheduler_lightweight_access_key'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Lightweight cron access key'),
|
||||
@ -418,7 +427,12 @@ function _scheduler_lightweight_cron($form, &$form_state) {
|
||||
);
|
||||
if (isset($form_state['scheduler_generate_new_key'])) {
|
||||
$new_access_key = substr(md5(rand()), 0, 20);
|
||||
// @codingStandardsIgnoreStart
|
||||
// We have to use $form_state['input'] here as storing the new key in
|
||||
// $form_state['values'] does not work. It is acceptable to use it on the
|
||||
// left of an assignment even if PHPCS does not think so.
|
||||
$form_state['input']['scheduler_lightweight_access_key'] = $new_access_key;
|
||||
// @codingStandardsIgnoreEnd
|
||||
drupal_set_message(t('A new random key has been generated but not saved. If you wish to use this, first "Save Configuration" to store the value, then modify your crontab job.'), 'warning');
|
||||
}
|
||||
$form['scheduler_cron_settings']['create_key'] = array(
|
||||
@ -466,7 +480,7 @@ function _scheduler_timecheck() {
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_scheduler_timecheck($variables) {
|
||||
function theme_scheduler_timecheck(array $variables) {
|
||||
global $user;
|
||||
|
||||
$now = $variables['now'];
|
||||
@ -487,9 +501,10 @@ function theme_scheduler_timecheck($variables) {
|
||||
'@admin_regional_settings' => url('admin/config/regional/settings'),
|
||||
);
|
||||
|
||||
$output = '<h4>' . t('Time check') . '</h4>'
|
||||
. '<p>' . t('Your server\'s time is @utc. In most cases this should match <a href="https://www.google.com/search?q=Greenwich%20Mean%20Time">Greenwich Mean Time (GMT) / Coordinated Universal Time (UTC)</a>', $t_options) . '</p>'
|
||||
. '<p>' . t('The website default timezone is @date_default_timezone (@date_default_code) which is offset from GMT by @date_default_offset hours. This timezone can be <a href="@admin_regional_settings">changed by admin users</a> with the appropriate access.', $t_options) . '</p>';
|
||||
$output = '<h4>' . t('Time check')
|
||||
. '</h4><p>' . t('Your server\'s time is @utc. In most cases this should match <a href="https://www.google.com/search?q=Greenwich%20Mean%20Time">Greenwich Mean Time (GMT) / Coordinated Universal Time (UTC)</a>', $t_options)
|
||||
. '</p><p>' . t('The website default timezone is @date_default_timezone (@date_default_code) which is offset from GMT by @date_default_offset hours. This timezone can be <a href="@admin_regional_settings">changed by admin users</a> with the appropriate access.', $t_options)
|
||||
. '</p>';
|
||||
|
||||
if (variable_get('configurable_timezones', 1)) {
|
||||
$output .= '<p>' . t('Your local time is @localtime (@daylight_saving). You can change this via your <a href="@user_account">user account</a>.', $t_options) . '</p>';
|
||||
@ -512,16 +527,15 @@ function theme_scheduler_timecheck($variables) {
|
||||
* admin/content/scheduler. It is also shown on the 'My account' page
|
||||
* user/{uid}/scheduler if the user has permission to schedule content.
|
||||
*
|
||||
* @param string
|
||||
* @param string $show
|
||||
* 'user_only' if viewing a user page, NULL otherwise.
|
||||
*
|
||||
* @param int
|
||||
* @param int $uid
|
||||
* The uid when viewing a user page, NULL otherwise.
|
||||
*
|
||||
* @return array
|
||||
* A render array for a page containing a list of nodes.
|
||||
*/
|
||||
function scheduler_list() {
|
||||
function scheduler_list($show, $uid) {
|
||||
$header = array(
|
||||
array(
|
||||
'data' => t('Title'),
|
||||
@ -570,11 +584,10 @@ function scheduler_list() {
|
||||
// the nodes owned by that user. If the current user is viewing another users'
|
||||
// profile and they do not have 'administer nodes' permission then it won't
|
||||
// even get this far, as the tab will not be accessible.
|
||||
$args = func_get_args();
|
||||
if ($args[0] == 'user_only') {
|
||||
$query->condition('n.uid', $args[1], '=');
|
||||
if ($show == 'user_only') {
|
||||
$query->condition('n.uid', $uid, '=');
|
||||
// Get user account for use later.
|
||||
$user = user_load($args[1]);
|
||||
$user = user_load($uid);
|
||||
}
|
||||
$query = $query->extend('TableSort')->orderByHeader($header);
|
||||
$result = $query->execute();
|
||||
@ -627,7 +640,7 @@ function scheduler_list() {
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => ($args[0] == 'user_only') ? t('There are no scheduled nodes for @username.', array('@username' => $user->name)) : t('There are no scheduled nodes.'),
|
||||
'#empty' => ($show == 'user_only') ? t('There are no scheduled nodes for @username.', array('@username' => $user->name)) : t('There are no scheduled nodes.'),
|
||||
);
|
||||
return $build;
|
||||
}
|
||||
|
@ -11,13 +11,15 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modules can implement hook_scheduler_api() to react to the Scheduler
|
||||
* operation being done on a node. The hook is invoked during cron processing
|
||||
* and also from scheduler_node_presave().
|
||||
* Allow modules to react to Scheduler node operations.
|
||||
*
|
||||
* Modules can implement hook_scheduler_api() to react to the Scheduler action
|
||||
* being performed on a node. This hook is invoked during cron processing for
|
||||
* 'pre_publish', 'publish', 'pre_unpublish' and 'unpublish' and from
|
||||
* scheduler_node_presave() for 'publish_immediately'.
|
||||
*
|
||||
* @param object $node
|
||||
* The scheduled node object that is being processed.
|
||||
*
|
||||
* @param string $action
|
||||
* $action determines what is being done to the node. The value will be
|
||||
* 'pre_publish', 'publish', 'publish_immediately', 'pre_unpublish'
|
||||
@ -25,27 +27,35 @@
|
||||
*/
|
||||
function hook_scheduler_api($node, $action) {
|
||||
switch ($action) {
|
||||
case 'pre_publish' :
|
||||
case 'pre_publish':
|
||||
break;
|
||||
case 'publish' :
|
||||
|
||||
case 'publish':
|
||||
break;
|
||||
case 'publish_immediately' :
|
||||
|
||||
case 'publish_immediately':
|
||||
break;
|
||||
case 'pre_unpublish' :
|
||||
|
||||
case 'pre_unpublish':
|
||||
break;
|
||||
case 'unpublish' :
|
||||
|
||||
case 'unpublish':
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modules to add node ids to the list being processed.
|
||||
*
|
||||
* Modules can implement hook_scheduler_nid_list() to add more node ids into the
|
||||
* list to be processed in the current cron run. This hook is invoked during
|
||||
* cron runs only.
|
||||
* cron runs only. It is maintained for backwards compatibility but has been
|
||||
* superceded by hook_scheduler_nid_list_alter(), which has more functionality.
|
||||
*
|
||||
* @param string $action
|
||||
* $action determines what is being done to the node.
|
||||
* Indicates what is being done to the node.
|
||||
* The value will be 'publish' or 'unpublish'.
|
||||
*
|
||||
* @return array
|
||||
@ -58,32 +68,35 @@ function hook_scheduler_nid_list($action) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows modules to add or remove node ids from the list to be processed.
|
||||
*
|
||||
* Modules can implement hook_scheduler_nid_list_alter() to add or remove node
|
||||
* ids from the list to be processed in the current cron run. This hook is
|
||||
* invoked during cron runs only.
|
||||
*
|
||||
* @param array $nids
|
||||
* $nids is an array of node ids being processed.
|
||||
*
|
||||
* Array of node ids being processed.
|
||||
* @param string $action
|
||||
* $action determines what is being done to the node.
|
||||
* Indicates what is being done to the node.
|
||||
* The value will be 'publish' or 'unpublish'.
|
||||
*
|
||||
* @return array
|
||||
* The full array of node ids to process, adjusted as required.
|
||||
*/
|
||||
function hook_scheduler_nid_list_alter(&$nids, $action) {
|
||||
function hook_scheduler_nid_list_alter(array &$nids, $action) {
|
||||
// Do some processing to add or removed node ids from the $nids array.
|
||||
return $nids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules can implement hook_scheduler_allow_publishing() to prevent
|
||||
* publication of a scheduled node.
|
||||
* Allows modules to prevent publication of a scheduled node.
|
||||
*
|
||||
* The node can be scheduled, and an attempt to publish it will be made during
|
||||
* the first cron run after the publishing time. If this hook returns FALSE the
|
||||
* node will not be published. Attempts at publishing will continue on each
|
||||
* subsequent cron run until this hook returns TRUE.
|
||||
* Modules can implement hook_scheduler_allow_publishing() to prevent publishing
|
||||
* of a scheduled node. The node can be scheduled for publishing as usual, and
|
||||
* an attempt to publish it will be made during the first cron run after the
|
||||
* publishing time. If this hook returns FALSE the node will not be published.
|
||||
* Attempts at publishing will continue on each subsequent cron run until this
|
||||
* hook returns TRUE.
|
||||
*
|
||||
* @param object $node
|
||||
* The scheduled node that is about to be published.
|
||||
@ -110,13 +123,14 @@ function hook_scheduler_allow_publishing($node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules can implement hook_scheduler_allow_unpublishing() to prevent
|
||||
* unpublication of a scheduled node.
|
||||
* Allows modules to prevent unpublication of a scheduled node.
|
||||
*
|
||||
* The node can be scheduled, and an attempt to unpublish it will be made during
|
||||
* the first cron run after the unpublishing time. If this hook returns FALSE
|
||||
* the node will not be unpublished. Attempts at unpublishing will continue on
|
||||
* each subsequent cron run until this hook returns TRUE.
|
||||
* Modules can implement hook_scheduler_allow_unpublishing() to prevent
|
||||
* unpublishing of a scheduled node. The node can be scheduled for unpublishing
|
||||
* as usual, and an attempt to unpublish it will be made during the first cron
|
||||
* run after the unpublishing time. If this hook returns FALSE the node will not
|
||||
* be unpublished. Attempts at unpublishing will continue on each subsequent
|
||||
* cron run until this hook returns TRUE.
|
||||
*
|
||||
* @param object $node
|
||||
* The scheduled node that is about to be unpublished.
|
||||
|
@ -42,15 +42,16 @@ function _scheduler_publish() {
|
||||
foreach ($nids as $nid) {
|
||||
$n = node_load($nid);
|
||||
|
||||
// Check that scheduled publishing is (still) enabled for this type.
|
||||
if (!variable_get('scheduler_publish_enable_' . $n->type, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check that other modules allow the action on this node.
|
||||
if (!_scheduler_allow($n, $action)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Invoke Scheduler API for modules to react before the node is published.
|
||||
// @todo For D8 move the 'pre' call to here.
|
||||
// See https://www.drupal.org/node/2311273
|
||||
|
||||
// Update timestamps.
|
||||
$n->changed = $n->publish_on;
|
||||
$old_creation_date = $n->created;
|
||||
@ -74,7 +75,8 @@ function _scheduler_publish() {
|
||||
|
||||
// Invoke scheduler API to allow modules to alter the node before it is
|
||||
// saved.
|
||||
// @todo For D8, remove this from here.
|
||||
// For 8.x this 'pre' call is moved up to just before 'Update timestamps'.
|
||||
// See https://www.drupal.org/node/2311273
|
||||
_scheduler_scheduler_api($n, 'pre_' . $action);
|
||||
|
||||
// Use the actions system to publish the node.
|
||||
@ -131,6 +133,11 @@ function _scheduler_unpublish() {
|
||||
foreach ($nids as $nid) {
|
||||
$n = node_load($nid);
|
||||
|
||||
// Check that scheduled publishing is (still) enabled for this type.
|
||||
if (!variable_get('scheduler_unpublish_enable_' . $n->type, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check that other modules allow the action on this node.
|
||||
if (!_scheduler_allow($n, $action)) {
|
||||
continue;
|
||||
@ -143,10 +150,6 @@ function _scheduler_unpublish() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Invoke scheduler API for modules to react before the node is unpublished.
|
||||
// @todo For D8, move the 'pre' call to here.
|
||||
// See https://www.drupal.org/node/2311273
|
||||
|
||||
// Update timestamps.
|
||||
$old_change_date = $n->changed;
|
||||
$n->changed = $n->unpublish_on;
|
||||
@ -167,7 +170,8 @@ function _scheduler_unpublish() {
|
||||
|
||||
// Invoke scheduler API to allow modules to alter the node before it is
|
||||
// saved.
|
||||
// @todo For D8, remove this from here.
|
||||
// For 8.x this 'pre' call is moved up to just before 'Update timestamps'.
|
||||
// See https://www.drupal.org/node/2311273
|
||||
_scheduler_scheduler_api($n, 'pre_' . $action);
|
||||
|
||||
// Use the actions system to unpublish the node.
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Drush commands for Scheduler.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_drush_command().
|
||||
*/
|
||||
function scheduler_drush_command() {
|
||||
$items = array();
|
||||
|
||||
$items['scheduler-cron'] = array(
|
||||
'description' => 'Lighweight cron to process the Scheduler module tasks.',
|
||||
'core' => array('7'),
|
||||
'aliases' => array('sch-cron'),
|
||||
'category' => 'scheduler',
|
||||
'options' => array(
|
||||
'nomsg' => 'to avoid the "cron completed" message being written to the terminal.',
|
||||
),
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run lighweight scheduler cron.
|
||||
*/
|
||||
function drush_scheduler_cron() {
|
||||
// Load the cron functions file then run scheduler cron.
|
||||
module_load_include('inc', 'scheduler', 'scheduler.cron');
|
||||
// Running the lightweight cron function _scheduler_run_cron() gives the dblog
|
||||
// rows but also kills drush. If we wanted to use that function, we can check
|
||||
// function_exists('drush_main') to do conditional code.
|
||||
scheduler_cron();
|
||||
$nomsg = drush_get_option('nomsg', NULL);
|
||||
$nomsg ? NULL : drupal_set_message(t('Scheduler lightweight cron completed.'));
|
||||
}
|
@ -27,7 +27,7 @@ function _scheduler_form_alter(&$form, $form_state) {
|
||||
// If this is a preview then get the values from the form, not the
|
||||
// database.
|
||||
if (isset($form_state['values']['op']) && $form_state['values']['op'] == t('Preview')) {
|
||||
$defaults = new StdClass;
|
||||
$defaults = new stdClass();
|
||||
$defaults->publish_on = $publishing_enabled ? $form_state['values']['publish_on'] : NULL;
|
||||
$defaults->unpublish_on = $unpublishing_enabled ? $form_state['values']['unpublish_on'] : NULL;
|
||||
}
|
||||
@ -40,7 +40,7 @@ function _scheduler_form_alter(&$form, $form_state) {
|
||||
}
|
||||
else {
|
||||
// Initialise standard values.
|
||||
$defaults = new StdClass;
|
||||
$defaults = new stdClass();
|
||||
// Respect presets added by functions like
|
||||
// scheduler_field_attach_prepare_translation_alter().
|
||||
$defaults->publish_on = isset($node->publish_on) ? $node->publish_on : NULL;
|
||||
@ -86,7 +86,7 @@ function _scheduler_form_alter(&$form, $form_state) {
|
||||
// Add Scheduler settings to Vertical Tabs group and attach the javascript.
|
||||
if ($use_vertical_tabs) {
|
||||
$form['scheduler_settings']['#group'] = 'additional_settings';
|
||||
$form['scheduler_settings']['#attached']['js'][] = drupal_get_path('module', 'scheduler') . '/scheduler_vertical_tabs.js';
|
||||
$form['scheduler_settings']['#attached']['js'][] = _scheduler_get_vertical_tabs_js();
|
||||
}
|
||||
|
||||
$extra_info = variable_get('scheduler_extra_info', '');
|
||||
@ -178,12 +178,18 @@ function _scheduler_form_alter(&$form, $form_state) {
|
||||
/**
|
||||
* Callback function for the Scheduler date entry elements.
|
||||
*/
|
||||
function scheduler_date_value_callback(&$element, $input = FALSE, &$form_state) {
|
||||
function scheduler_date_value_callback(&$element, $input, &$form_state) {
|
||||
// When processing a delete operation the user should not be forced to enter a
|
||||
// date. Hence set the scheduler date element's #required attribute to FALSE.
|
||||
// Test the input operation against $form_state['values']['delete'] as this
|
||||
// will match the value of the Delete button even if translated.
|
||||
if (isset($form_state['input']['op']) && isset($form_state['values']['delete']) && $form_state['input']['op'] == $form_state['values']['delete']) {
|
||||
// Test the 'triggering_element' value against $form_state['values']['delete']
|
||||
// as this will match Delete button even if the text is translated.
|
||||
// @see https://www.drupal.org/node/1614880
|
||||
if (isset($form_state['triggering_element']['#value']) && isset($form_state['values']['delete']) && $form_state['triggering_element']['#value'] == $form_state['values']['delete']) {
|
||||
// At some point between October 2013 and August 2017 this code became
|
||||
// unnecessary. Nodes can now be deleted when 'required' is set and when no
|
||||
// date is entered, even without setting #required to FALSE here. It may be
|
||||
// due to a core change between 7.23 and 7.56? Leave this line as-is just
|
||||
// for safety.
|
||||
$element['#required'] = FALSE;
|
||||
}
|
||||
// If using date popup then process the callback that would have been done had
|
||||
|
@ -2,17 +2,14 @@ name = Scheduler
|
||||
description = This module allows nodes to be published and unpublished on specified dates and time.
|
||||
core = 7.x
|
||||
configure = admin/config/content/scheduler
|
||||
files[] = scheduler.install
|
||||
files[] = scheduler.module
|
||||
files[] = scheduler.test
|
||||
files[] = scheduler.views.inc
|
||||
files[] = scheduler_handler_field_scheduler_countdown.inc
|
||||
files[] = tests/scheduler.test
|
||||
files[] = tests/scheduler_api.test
|
||||
test_dependencies[] = date
|
||||
test_dependencies[] = rules
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-07-24
|
||||
version = "7.x-1.5"
|
||||
; Information added by Drupal.org packaging script on 2020-09-15
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "scheduler"
|
||||
datestamp = "1469372941"
|
||||
|
||||
datestamp = "1600171819"
|
||||
|
@ -106,7 +106,7 @@ function scheduler_update_7100() {
|
||||
|
||||
// Grant these roles the 'view scheduled content' permission.
|
||||
if ($roles_to_update = $query->execute()->fetchCol()) {
|
||||
foreach ($roles_to_update as $rid ) {
|
||||
foreach ($roles_to_update as $rid) {
|
||||
// Use db_merge not db_insert in case the role already has the permission.
|
||||
$query = db_merge('role_permission');
|
||||
$query->key(array(
|
||||
@ -123,7 +123,7 @@ function scheduler_update_7100() {
|
||||
}
|
||||
}
|
||||
|
||||
return format_plural(sizeof($roles_to_update), '1 role updated with view scheduled content permission.', '@count roles updated with view scheduled content permission.');
|
||||
return format_plural(count($roles_to_update), '1 role updated with view scheduled content permission.', '@count roles updated with view scheduled content permission.');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,11 +145,12 @@ function scheduler_update_7101() {
|
||||
if ($nids_to_delete = $query->execute()->fetchCol()) {
|
||||
db_delete('scheduler')->condition('nid', $nids_to_delete, 'IN')->execute();
|
||||
}
|
||||
return format_plural(sizeof($nids_to_delete), '1 obsolete row deleted from scheduler table.', '@count obsolete rows deleted from scheduler table.');
|
||||
return format_plural(count($nids_to_delete), '1 obsolete row deleted from scheduler table.', '@count obsolete rows deleted from scheduler table.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Function scheduler_update_7102() removed and replaced by 7103.
|
||||
*
|
||||
* @see http://www.drupal.org/node/2706119
|
||||
*/
|
||||
|
||||
@ -158,9 +159,9 @@ function scheduler_update_7101() {
|
||||
*/
|
||||
function scheduler_update_7103() {
|
||||
// Change all values of 'schedule (un)publishing of nodes' to the cleaner
|
||||
// 'schedule publishing of nodes'
|
||||
// 'schedule publishing of nodes'.
|
||||
// @see http://www.drupal.org/node/2538002
|
||||
|
||||
//
|
||||
// Updates done in two stages to avoid integrity constraint violation. First
|
||||
// select all role ids which already have the new permission value.
|
||||
$query = db_select('role_permission', 'rp')
|
||||
|
@ -232,16 +232,16 @@ function scheduler_form_alter(&$form, $form_state) {
|
||||
* unpublishing, by implementing hook_scheduler_allow_publishing() or
|
||||
* hook_scheduler_allow_unpublishing().
|
||||
*
|
||||
* @see hook_scheduler_allow_publishing()
|
||||
* @see hook_scheduler_allow_unpublishing()
|
||||
*
|
||||
* @param stdClass $node
|
||||
* @param object $node
|
||||
* The node object on which the action is to be performed.
|
||||
* @param string $action
|
||||
* The action that needs to be checked. Can be 'publish' or 'unpublish'.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the action is allowed, FALSE if not.
|
||||
*
|
||||
* @see hook_scheduler_allow_publishing()
|
||||
* @see hook_scheduler_allow_unpublishing()
|
||||
*/
|
||||
function _scheduler_allow($node, $action) {
|
||||
// Default to TRUE.
|
||||
@ -282,7 +282,8 @@ function _scheduler_strtotime($str) {
|
||||
// date_limit_format() to derive the format of the returned string value.
|
||||
$granularity = date_format_order($date_format);
|
||||
$date_format = date_limit_format(DATE_FORMAT_DATETIME, $granularity);
|
||||
$date_only_format = date_limit_format(DATE_FORMAT_DATETIME, array('day', 'month', 'year'));
|
||||
$granularity = array('day', 'month', 'year');
|
||||
$date_only_format = date_limit_format(DATE_FORMAT_DATETIME, $granularity);
|
||||
}
|
||||
$str = trim(preg_replace('/\s+/', ' ', $str));
|
||||
$time = _scheduler_strptime($str, $date_format);
|
||||
@ -340,6 +341,8 @@ function _scheduler_strptime($date, $format) {
|
||||
// Build a regex pattern for each element allowed in the date and time format.
|
||||
$date_entities_and_replacements = array(
|
||||
// Date elements, one for each character in SCHEDULER_DATE_LETTERS.
|
||||
// Inline comments on each row are useful here, so 'ignore' for standards.
|
||||
// @codingStandardsIgnoreStart
|
||||
'd' => '(\d{2})', // Day of the month with leading zero.
|
||||
'j' => '(\d{1,2})', // Day of the month without leading zero.
|
||||
'm' => '(\d{2})', // Month number with leading zero.
|
||||
@ -358,6 +361,7 @@ function _scheduler_strptime($date, $format) {
|
||||
's' => '(\d{2})', // Seconds with leading zero.
|
||||
'a' => '([ap]m)', // Lower case meridian.
|
||||
'A' => '([AP]M)', // Upper case meridian.
|
||||
// @codingStandardsIgnoreEnd
|
||||
);
|
||||
$date_entities = array_keys($date_entities_and_replacements);
|
||||
$date_regex_replacements = array_values($date_entities_and_replacements);
|
||||
@ -370,7 +374,15 @@ function _scheduler_strptime($date, $format) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$results = array('day' => 0, 'month' => 0, 'year' => 0, 'hour' => 0, 'minute' => 0, 'second' => 0, 'meridiem' => NULL);
|
||||
$results = array(
|
||||
'day' => 0,
|
||||
'month' => 0,
|
||||
'year' => 0,
|
||||
'hour' => 0,
|
||||
'minute' => 0,
|
||||
'second' => 0,
|
||||
'meridiem' => NULL,
|
||||
);
|
||||
$index = 1;
|
||||
foreach ($entity_matches[1] as $entity) {
|
||||
$value = intval($value_matches[$index]);
|
||||
@ -467,7 +479,7 @@ function scheduler_node_load($nodes, $types) {
|
||||
/**
|
||||
* Implements hook_node_view().
|
||||
*/
|
||||
function scheduler_node_view($node, $view_mode = 'full', $langcode) {
|
||||
function scheduler_node_view($node, $view_mode, $langcode) {
|
||||
// If the node is going to be unpublished, then add this information to the
|
||||
// header for search engines. Only do this when the current page is the
|
||||
// full-page view of the node.
|
||||
@ -487,7 +499,7 @@ function scheduler_node_validate($node, $form, &$form_state) {
|
||||
// Use !== FALSE because the key returned will be 0.
|
||||
// @see https://www.drupal.org/node/2723929
|
||||
if (!empty($form_state['triggering_element']['#submit']) && array_search('node_form_delete_submit', $form_state['triggering_element']['#submit']) !== FALSE) {
|
||||
if ($errors = form_get_errors()) {
|
||||
if (form_get_errors()) {
|
||||
// If there are already errors (from date_popup) remove them to allow
|
||||
// deletion to proceed.
|
||||
form_clear_error();
|
||||
@ -504,13 +516,13 @@ function scheduler_node_validate($node, $form, &$form_state) {
|
||||
// passed as an array this means we are using the Date Popup module and a
|
||||
// validation error has occurred. In this case we should skip validation as
|
||||
// it is being handled by Date Popup.
|
||||
|
||||
$date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT);
|
||||
$args = array('%time' => format_date(REQUEST_TIME, 'custom', $date_format));
|
||||
|
||||
if (!empty($node->publish_on) && !is_numeric($node->publish_on) && !is_array($node->publish_on)) {
|
||||
$publishtime = _scheduler_strtotime($node->publish_on);
|
||||
if ($publishtime === FALSE) {
|
||||
form_set_error('publish_on', t("The 'publish on' value does not match the expected format of %time", array('%time' => format_date(REQUEST_TIME, 'custom', $date_format))));
|
||||
form_set_error('publish_on', t("The 'publish on' value does not match the expected format of %time", $args));
|
||||
}
|
||||
elseif ($publishtime && variable_get('scheduler_publish_past_date_' . $node->type, 'error') == 'error' && $publishtime < REQUEST_TIME) {
|
||||
form_set_error('publish_on', t("The 'publish on' date must be in the future"));
|
||||
@ -520,7 +532,7 @@ function scheduler_node_validate($node, $form, &$form_state) {
|
||||
if (!empty($node->unpublish_on) && !is_numeric($node->unpublish_on) && !is_array($node->unpublish_on)) {
|
||||
$unpublishtime = _scheduler_strtotime($node->unpublish_on);
|
||||
if ($unpublishtime === FALSE) {
|
||||
form_set_error('unpublish_on', t("The 'unpublish on' value does not match the expected format of %time", array('%time' => format_date(REQUEST_TIME, 'custom', $date_format))));
|
||||
form_set_error('unpublish_on', t("The 'unpublish on' value does not match the expected format of %time", $args));
|
||||
}
|
||||
elseif ($unpublishtime && $unpublishtime < REQUEST_TIME) {
|
||||
form_set_error('unpublish_on', t("The 'unpublish on' date must be in the future"));
|
||||
@ -533,7 +545,10 @@ function scheduler_node_validate($node, $form, &$form_state) {
|
||||
|
||||
// The unpublish-on 'required' form attribute may not be set, but in some
|
||||
// cases a value must still be entered.
|
||||
if (variable_get('scheduler_unpublish_required_' . $node->type) && empty($node->unpublish_on)) {
|
||||
if (variable_get('scheduler_unpublish_enable_' . $node->type)
|
||||
&& variable_get('scheduler_unpublish_required_' . $node->type)
|
||||
&& empty($node->unpublish_on)
|
||||
) {
|
||||
// ... when also setting a publish-on date.
|
||||
if (!empty($node->publish_on)) {
|
||||
form_set_error('unpublish_on', t("If you set a 'publish-on' date then you must also set an 'unpublish-on' date."));
|
||||
@ -585,7 +600,9 @@ function scheduler_node_presave($node) {
|
||||
// message themselves explaining why publication is denied.
|
||||
if ($publication_allowed) {
|
||||
$date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT);
|
||||
drupal_set_message(t('This post is unpublished and will be published @publish_time.', array('@publish_time' => format_date($node->publish_on, 'custom', $date_format))), 'status', FALSE);
|
||||
drupal_set_message(t('This post is unpublished and will be published @publish_time.', array(
|
||||
'@publish_time' => format_date($node->publish_on, 'custom', $date_format),
|
||||
)), 'status', FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -704,6 +721,7 @@ function scheduler_cron() {
|
||||
if (variable_get('scheduler_cache_clear_all', 0) && ($nodes_published || $nodes_unpublished)) {
|
||||
// Clear the page and block caches.
|
||||
cache_clear_all();
|
||||
watchdog('scheduler', 'Page and block caches cleared.', array(), WATCHDOG_NOTICE, l(t('settings'), 'admin/config/content/scheduler'));
|
||||
}
|
||||
|
||||
// Reset the static scheduler_cron flag.
|
||||
@ -882,8 +900,8 @@ function scheduler_feeds_set_target($source, $entity, $target, $value, $mapping)
|
||||
* Implements hook_ctools_plugin_directory().
|
||||
*/
|
||||
function scheduler_ctools_plugin_directory($owner, $plugin_type) {
|
||||
// Declare a form pane (panels content type) for use in ctools and page
|
||||
// manager. This allows the Scheduler fieldset to be placed in a panel.
|
||||
// Declare a form pane (panels content type) for use in ctools and page
|
||||
// manager. This allows the Scheduler fieldset to be placed in a panel.
|
||||
if ($owner == 'ctools' && $plugin_type == 'content_types') {
|
||||
return 'plugins/content_types';
|
||||
}
|
||||
@ -942,3 +960,12 @@ function scheduler_date_popup_pre_validate_alter($element, $form_state, &$input)
|
||||
$input['time'] = format_date($default_time, 'custom', variable_get('scheduler_time_only_format', SCHEDULER_TIME_ONLY_FORMAT));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to add js 'theme' setting and return the js filename.
|
||||
*/
|
||||
function _scheduler_get_vertical_tabs_js() {
|
||||
global $theme;
|
||||
drupal_add_js(array('scheduler_vertical_tabs' => array('theme' => $theme)), array('type' => 'setting'));
|
||||
return drupal_get_path('module', 'scheduler') . "/scheduler_vertical_tabs.js";
|
||||
}
|
||||
|
@ -7,11 +7,11 @@
|
||||
|
||||
/**
|
||||
* Implements hook_rules_event_info().
|
||||
*
|
||||
* This hook function defines four Scheduler events which can be used by Rules
|
||||
* to trigger other actions.
|
||||
*/
|
||||
function scheduler_rules_event_info() {
|
||||
// This hook function defines four Scheduler events which can be used by Rules
|
||||
// to trigger other actions.
|
||||
|
||||
// Create an array of variables, as these are the same for each of the events.
|
||||
$variables = array(
|
||||
'node' => array(
|
||||
@ -118,9 +118,9 @@ function scheduler_rules_action_info() {
|
||||
/**
|
||||
* Set the publish_on date for the node.
|
||||
*
|
||||
* @param $node
|
||||
* @param object $node
|
||||
* The node object to be scheduled for publishing.
|
||||
* @param $date
|
||||
* @param int $date
|
||||
* The date for publishing, a unix timestamp integer.
|
||||
*/
|
||||
function scheduler_set_publish_date_action($node, $date) {
|
||||
@ -142,9 +142,9 @@ function scheduler_set_publish_date_action($node, $date) {
|
||||
/**
|
||||
* Set the unpublish_on date for the node.
|
||||
*
|
||||
* @param $node
|
||||
* @param object $node
|
||||
* The node object to be scheduled for unpublishing.
|
||||
* @param $date
|
||||
* @param int $date
|
||||
* The date for unpublishing, a unix timestamp integer.
|
||||
*/
|
||||
function scheduler_set_unpublish_date_action($node, $date) {
|
||||
@ -162,7 +162,7 @@ function scheduler_set_unpublish_date_action($node, $date) {
|
||||
/**
|
||||
* Remove the publish_on date for the node.
|
||||
*
|
||||
* @param $node
|
||||
* @param object $node
|
||||
* The node object from which to remove the publish_on date.
|
||||
*/
|
||||
function scheduler_remove_publish_date_action($node) {
|
||||
@ -180,7 +180,7 @@ function scheduler_remove_publish_date_action($node) {
|
||||
/**
|
||||
* Remove the unpublish_on date for the node.
|
||||
*
|
||||
* @param $node
|
||||
* @param object $node
|
||||
* The node object from which to remove the unpublish_on date.
|
||||
*/
|
||||
function scheduler_remove_unpublish_date_action($node) {
|
||||
@ -213,19 +213,23 @@ function scheduler_rules_condition_info() {
|
||||
|
||||
// 1. Condition to check if publishing is enabled for the content type.
|
||||
$conditions['scheduler_condition_publishing_is_enabled'] = array(
|
||||
'label' => t('Scheduled publishing is enabled for this content type')) + $default;
|
||||
'label' => t('Scheduled publishing is enabled for this content type'),
|
||||
) + $default;
|
||||
|
||||
// 2. Condition to check if unpublishing is enabled for the content type.
|
||||
$conditions['scheduler_condition_unpublishing_is_enabled'] = array(
|
||||
'label' => t('Scheduled unpublishing is enabled for this content type')) + $default;
|
||||
'label' => t('Scheduled unpublishing is enabled for this content type'),
|
||||
) + $default;
|
||||
|
||||
// 3. Condition to check if the node is scheduled for publishing.
|
||||
$conditions['scheduler_condition_node_is_scheduled_for_publishing'] = array(
|
||||
'label' => t('The node is scheduled for publishing')) + $default;
|
||||
'label' => t('The node is scheduled for publishing'),
|
||||
) + $default;
|
||||
|
||||
// 4. Condition to check if the node is scheduled for unpublishing.
|
||||
$conditions['scheduler_condition_node_is_scheduled_for_unpublishing'] = array(
|
||||
'label' => t('The node is scheduled for unpublishing')) + $default;
|
||||
'label' => t('The node is scheduled for unpublishing'),
|
||||
) + $default;
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
@ -233,9 +237,10 @@ function scheduler_rules_condition_info() {
|
||||
/**
|
||||
* Determines whether scheduled publishing is enabled for this node type.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @return
|
||||
* @param object $node
|
||||
* The node to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if scheduled publishing is enabled for the node type, FALSE if not.
|
||||
*/
|
||||
function scheduler_condition_publishing_is_enabled($node) {
|
||||
@ -245,9 +250,10 @@ function scheduler_condition_publishing_is_enabled($node) {
|
||||
/**
|
||||
* Determines whether scheduled unpublishing is enabled for this node type.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @return
|
||||
* @param object $node
|
||||
* The node to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if scheduled unpublishing is enabled for the node type, FALSE if not.
|
||||
*/
|
||||
function scheduler_condition_unpublishing_is_enabled($node) {
|
||||
@ -257,9 +263,10 @@ function scheduler_condition_unpublishing_is_enabled($node) {
|
||||
/**
|
||||
* Determines whether a node is scheduled for publishing.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @return
|
||||
* @param object $node
|
||||
* The node to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the node is scheduled for publishing, FALSE if not.
|
||||
*/
|
||||
function scheduler_condition_node_is_scheduled_for_publishing($node) {
|
||||
@ -269,9 +276,10 @@ function scheduler_condition_node_is_scheduled_for_publishing($node) {
|
||||
/**
|
||||
* Determines whether a node is scheduled for unpublishing.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @return
|
||||
* @param object $node
|
||||
* The node to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the node is scheduled for unpublishing, FALSE if not.
|
||||
*/
|
||||
function scheduler_condition_node_is_scheduled_for_unpublishing($node) {
|
||||
|
@ -8,14 +8,13 @@
|
||||
/**
|
||||
* Implements hook_default_rules_configuration().
|
||||
*
|
||||
* @return
|
||||
* An array of rules configurations with the configuration names as keys.
|
||||
* This function returns an array of rules configurations with the configuration
|
||||
* names as keys. Two reaction rules and four components are provided.
|
||||
*/
|
||||
function scheduler_default_rules_configuration() {
|
||||
// Define two reaction rules which will be displayed on the 'Rules' tab. These
|
||||
// are initially inactive, but the user can enable them, and then modify the
|
||||
// values and/or add more conditions and actions.
|
||||
|
||||
// 1. Reaction rule to send an email when Scheduler publishes content.
|
||||
$rule = rules_reaction_rule();
|
||||
$rule->label = t('Send e-mail when content is published by Scheduler');
|
||||
@ -48,7 +47,6 @@ function scheduler_default_rules_configuration() {
|
||||
// Define four components which will be available in the 'Components' tab in
|
||||
// Rules admin. These are also available in Views Bulk Operations, to allow
|
||||
// a user to set or remove scheduling dates in bulk.
|
||||
|
||||
// 1. Component to set the publishing date on a node.
|
||||
$rule = rule(array(
|
||||
'scheduler_node' => array(
|
||||
|
@ -31,6 +31,12 @@ function scheduler_tokens($type, $tokens, array $data = array(), array $options
|
||||
$replacements = array();
|
||||
|
||||
if ($type == 'node' && !empty($data['node'])) {
|
||||
|
||||
// Initialise the two field variables. The syntax ${$field} = NULL inside
|
||||
// the foreach loop does work but we get warnings for Drupal Coding Practice
|
||||
// that the variables are not initialised, hence do it simply here instead.
|
||||
$publish_on = $unpublish_on = NULL;
|
||||
|
||||
// Usually the tokens are generated on saved node data, where the scheduler
|
||||
// fields are numeric timestamps. However, if the tokens are required during
|
||||
// the process of saving a node before hook_node_presave() has been executed
|
||||
@ -38,14 +44,15 @@ function scheduler_tokens($type, $tokens, array $data = array(), array $options
|
||||
// @see https://www.drupal.org/node/2750467
|
||||
$node = $data['node'];
|
||||
foreach (array('publish_on', 'unpublish_on') as $field) {
|
||||
if (empty($node->$field)) {
|
||||
${$field} = NULL;
|
||||
}
|
||||
elseif (is_numeric($node->$field)) {
|
||||
${$field} = $node->$field;
|
||||
}
|
||||
else {
|
||||
${$field} = _scheduler_strtotime($node->$field);
|
||||
if (isset($node->$field)) {
|
||||
if (is_numeric($node->$field)) {
|
||||
// We want the numeric value.
|
||||
${$field} = $node->$field;
|
||||
}
|
||||
elseif (!empty($node->$field)) {
|
||||
// Convert the text to a numeric value.
|
||||
${$field} = _scheduler_strtotime($node->$field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,11 +65,13 @@ function scheduler_tokens($type, $tokens, array $data = array(), array $options
|
||||
$replacements[$original] = format_date($publish_on, 'medium', '', NULL, $language_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'scheduler-unpublish':
|
||||
if (!empty($unpublish_on)) {
|
||||
$replacements[$original] = format_date($unpublish_on, 'medium', '', NULL, $language_code);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,11 @@ function scheduler_views_data() {
|
||||
|
||||
// Define how the node table is linked to the Scheduler table. This is needed
|
||||
// when 'scheduler' is the base table, to give access to the node fields.
|
||||
// Type = 'inner' will exclude any bad data rows in the scheduler table.
|
||||
$tables['node']['table']['join']['scheduler'] = array(
|
||||
'left_field' => 'nid',
|
||||
'field' => 'nid',
|
||||
'type' => 'inner', // to exclude any bad data rows in the scheduler table.
|
||||
'type' => 'inner',
|
||||
);
|
||||
|
||||
// Describe the two fields in the Scheduler database table.
|
||||
@ -72,9 +73,9 @@ function scheduler_views_data() {
|
||||
// Describe the two extra derived fields provided for Views.
|
||||
$tables['scheduler']['publish_countdown'] = array(
|
||||
'title' => t('Publish countdown'),
|
||||
'help' => t('Time until the article will be automatically published'),
|
||||
'help' => t('Time until the content will be published'),
|
||||
'field' => array(
|
||||
'handler' => 'scheduler_handler_field_scheduler_countdown',
|
||||
'handler' => 'SchedulerHandlerFieldSchedulerCountdown',
|
||||
'click sortable' => FALSE,
|
||||
'timestamp_field' => 'publish_on',
|
||||
),
|
||||
@ -82,9 +83,9 @@ function scheduler_views_data() {
|
||||
|
||||
$tables['scheduler']['unpublish_countdown'] = array(
|
||||
'title' => t('Unpublish countdown'),
|
||||
'help' => t('Time until the article will be automatically unpublished'),
|
||||
'help' => t('Time until the content will be unpublished'),
|
||||
'field' => array(
|
||||
'handler' => 'scheduler_handler_field_scheduler_countdown',
|
||||
'handler' => 'SchedulerHandlerFieldSchedulerCountdown',
|
||||
'click sortable' => FALSE,
|
||||
'timestamp_field' => 'unpublish_on',
|
||||
),
|
||||
@ -92,16 +93,3 @@ function scheduler_views_data() {
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_views_handlers().
|
||||
*/
|
||||
function scheduler_views_handlers() {
|
||||
return array(
|
||||
'handlers' => array(
|
||||
'scheduler_handler_field_scheduler_countdown' => array(
|
||||
'parent' => 'views_handler_field',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -10,16 +10,19 @@
|
||||
/**
|
||||
* Field handler to display a countdown until a scheduled action.
|
||||
*
|
||||
* Defines class scheduler_handler_field_scheduler_countdown.
|
||||
* Defines class SchedulerHandlerFieldSchedulerCountdown.
|
||||
* The structure is [module]_handler_[type]_[tablename]_[fieldname]
|
||||
* However, for standards compliance, CamelCase is now used where possible.
|
||||
*
|
||||
* @see http://www.ericschaefer.org/blog/2011/01/09/custom-field-handlers-for-views-2-drupal
|
||||
*/
|
||||
class scheduler_handler_field_scheduler_countdown extends views_handler_field {
|
||||
CONST SECOND_SCALE = 1;
|
||||
CONST MINUTE_SCALE = 60;
|
||||
CONST HOUR_SCALE = 3600;
|
||||
CONST DAY_SCALE = 86400;
|
||||
CONST WEEK_SCALE = 604800;
|
||||
class SchedulerHandlerFieldSchedulerCountdown extends views_handler_field {
|
||||
|
||||
const SECOND_SCALE = 1;
|
||||
const MINUTE_SCALE = 60;
|
||||
const HOUR_SCALE = 3600;
|
||||
const DAY_SCALE = 86400;
|
||||
const WEEK_SCALE = 604800;
|
||||
|
||||
/**
|
||||
* Add the timestamp_field into the SQL query.
|
||||
@ -28,7 +31,7 @@ class scheduler_handler_field_scheduler_countdown extends views_handler_field {
|
||||
* of seconds from now until publishing. If publish_on is in the past then
|
||||
* NULL is returned.
|
||||
*/
|
||||
function query() {
|
||||
public function query() {
|
||||
$this->ensure_my_table();
|
||||
$this->node_table = $this->query->ensure_table('node', $this->relationship);
|
||||
$time_field = $this->definition['timestamp_field'];
|
||||
@ -38,10 +41,17 @@ class scheduler_handler_field_scheduler_countdown extends views_handler_field {
|
||||
/**
|
||||
* Define our display options and provide defaults.
|
||||
*
|
||||
* The name of this function fails the coding standard sniff
|
||||
* Drupal.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
* However, the name is defined in Views module and has to match that, hence
|
||||
* we need to ignore this fault and not report it.
|
||||
*
|
||||
* @return array
|
||||
* An associative array containing the options.
|
||||
*/
|
||||
function option_definition() {
|
||||
// @codingStandardsIgnoreStart
|
||||
public function option_definition() {
|
||||
// @codingStandardsIgnoreEnd
|
||||
$options = parent::option_definition();
|
||||
$options['countdown_display'] = array('default' => 'smart');
|
||||
$options['units_display'] = array('default' => 'long');
|
||||
@ -51,7 +61,9 @@ class scheduler_handler_field_scheduler_countdown extends views_handler_field {
|
||||
/**
|
||||
* Defines the form for the user to select the display options.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
// @codingStandardsIgnoreStart
|
||||
public function options_form(&$form, &$form_state) {
|
||||
// @codingStandardsIgnoreEnd
|
||||
parent::options_form($form, $form_state);
|
||||
$form['countdown_display'] = array(
|
||||
'#title' => t('Display countdown as'),
|
||||
@ -79,17 +91,19 @@ class scheduler_handler_field_scheduler_countdown extends views_handler_field {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function to keep only the array scale values which are smaller
|
||||
* than the countdown value being displayed.
|
||||
* Callback function for array_filter.
|
||||
*
|
||||
* Keep only the array scale values which are smaller than the countdown
|
||||
* value being displayed.
|
||||
*/
|
||||
function scale_filter_callback($array_value) {
|
||||
public function scaleFilterCallback($array_value) {
|
||||
return ($this->raw_value >= $array_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the countdown value in the units required.
|
||||
*/
|
||||
function render($values) {
|
||||
public function render($values) {
|
||||
$countdown_display = $this->options['countdown_display'];
|
||||
$this->raw_value = $values->{$this->field_alias};
|
||||
|
||||
@ -102,7 +116,7 @@ class scheduler_handler_field_scheduler_countdown extends views_handler_field {
|
||||
);
|
||||
// If the field has been set to 'Smart', determine the right timescale.
|
||||
if ($countdown_display == 'smart') {
|
||||
$scales = array_filter($scales, array($this, 'scale_filter_callback'));
|
||||
$scales = array_filter($scales, array($this, 'scaleFilterCallback'));
|
||||
$scale = empty($scales) ? self::SECOND_SCALE : reset($scales);
|
||||
}
|
||||
// Otherwise use the fixed display requested.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file
|
||||
* jQuery to provide summary information inside vertical tabs.
|
||||
* JQuery to provide summary information inside vertical tabs.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
@ -20,7 +20,7 @@ Drupal.behaviors.scheduler_settings = {
|
||||
$('div.vertical-tabs').addClass(theme);
|
||||
|
||||
// Provide summary when editing a node.
|
||||
$('fieldset#edit-scheduler-settings', context).drupalSetSummary(function(context) {
|
||||
$('fieldset#edit-scheduler-settings', context).drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
if ($('#edit-publish-on').val() || $('#edit-publish-on-datepicker-popup-0').val()) {
|
||||
vals.push(Drupal.t('Scheduled for publishing'));
|
||||
@ -35,7 +35,7 @@ Drupal.behaviors.scheduler_settings = {
|
||||
});
|
||||
|
||||
// Provide summary during content type configuration.
|
||||
$('fieldset#edit-scheduler', context).drupalSetSummary(function(context) {
|
||||
$('fieldset#edit-scheduler', context).drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
if ($('#edit-scheduler-publish-enable', context).is(':checked')) {
|
||||
vals.push(Drupal.t('Publishing enabled'));
|
||||
|
@ -0,0 +1,13 @@
|
||||
name = "Scheduler tests"
|
||||
description = "Support module for Scheduler related testing."
|
||||
package = Testing
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
dependencies[] = list
|
||||
dependencies[] = options
|
||||
|
||||
; Information added by Drupal.org packaging script on 2020-09-15
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "scheduler"
|
||||
datestamp = "1600171819"
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, uninstall, update and schema hooks for the Scheduler Test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function scheduler_test_install() {
|
||||
$t = get_t();
|
||||
|
||||
// Ensure the scheduler_test node type is available.
|
||||
node_types_rebuild();
|
||||
$types = node_type_get_types();
|
||||
|
||||
// Attach a body field to the node type.
|
||||
node_add_body_field($types['scheduler_test']);
|
||||
|
||||
// Create a field to attach to the node type.
|
||||
$field = field_info_field('field_scheduler_test_approved');
|
||||
if (empty($field)) {
|
||||
$field = array(
|
||||
'field_name' => 'field_scheduler_test_approved',
|
||||
'type' => 'list_integer',
|
||||
'entity_types' => array('node'),
|
||||
'cardinality' => 2,
|
||||
'settings' => array(
|
||||
'allowed_values' => array(
|
||||
1 => $t('Approved for publication by the CEO'),
|
||||
),
|
||||
),
|
||||
);
|
||||
$field = field_create_field($field);
|
||||
}
|
||||
|
||||
$instance = field_info_instance('node', 'field_scheduler_test_approved', 'scheduler_test');
|
||||
if (empty($instance)) {
|
||||
$instance = array(
|
||||
'bundle' => 'scheduler_test',
|
||||
'display' => array(
|
||||
'default' => array('type' => 'list_default'),
|
||||
'teaser' => array('type' => 'hidden'),
|
||||
),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'field_scheduler_test_approved',
|
||||
'label' => 'Approved',
|
||||
'widget' => array('type' => 'options_buttons'),
|
||||
);
|
||||
field_create_instance($instance);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Main functions and hook implementations of the Scheduler Test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_node_info().
|
||||
*/
|
||||
function scheduler_test_node_info() {
|
||||
$items = array(
|
||||
'scheduler_test' => array(
|
||||
'name' => t('Scheduler test'),
|
||||
'base' => 'node_content',
|
||||
'description' => t('This content type is used to test the Scheduler module.'),
|
||||
'has_title' => '1',
|
||||
'title_label' => t('Title'),
|
||||
),
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_scheduler_allow_publishing().
|
||||
*/
|
||||
function scheduler_test_scheduler_allow_publishing($node) {
|
||||
// Only publish nodes that have the 'Approved for publication by the CEO'
|
||||
// checkbox ticked.
|
||||
$items = field_get_items('node', $node, 'field_scheduler_test_approved');
|
||||
$allowed = !empty($items[0]['value']);
|
||||
|
||||
// If publication is denied then inform the user why.
|
||||
if (!$allowed) {
|
||||
drupal_set_message(t('The content will only be published after approval by the CEO.'), 'status', FALSE);
|
||||
}
|
||||
|
||||
return $allowed;
|
||||
}
|
1692
frontend/drupal/sites/all/modules/scheduler/tests/scheduler.test
Normal file
1692
frontend/drupal/sites/all/modules/scheduler/tests/scheduler.test
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,10 @@
|
||||
* @file
|
||||
* Tests for the Scheduler API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests to cover the Scheduler API functions.
|
||||
*/
|
||||
class SchedulerApiTestCase extends DrupalWebTestCase {
|
||||
|
||||
/**
|
||||
@ -27,7 +31,7 @@ class SchedulerApiTestCase extends DrupalWebTestCase {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function setUp() {
|
||||
public function setUp() {
|
||||
parent::setUp('scheduler', 'scheduler_test');
|
||||
|
||||
// Add scheduler functionality to the 'scheduler_test' node type.
|
||||
@ -46,7 +50,7 @@ class SchedulerApiTestCase extends DrupalWebTestCase {
|
||||
* @todo Create and update the nodes through the interface so we can check if
|
||||
* the correct messages are displayed.
|
||||
*/
|
||||
function testAllowedPublishing() {
|
||||
public function testAllowedPublishing() {
|
||||
// Create a node that is not approved for publication. Then simulate a cron
|
||||
// run, and check that the node is not published.
|
||||
$node = $this->createUnapprovedNode();
|
||||
@ -101,14 +105,14 @@ class SchedulerApiTestCase extends DrupalWebTestCase {
|
||||
/**
|
||||
* Check to see if a node is not published.
|
||||
*
|
||||
* @param $nid
|
||||
* The nid of the node to check.
|
||||
* @param $message
|
||||
* @param int $nid
|
||||
* The id of the node to check.
|
||||
* @param string $message
|
||||
* The message to display along with the assertion.
|
||||
* @param $group
|
||||
* @param string $group
|
||||
* The type of assertion - examples are "Browser", "PHP".
|
||||
*
|
||||
* @return
|
||||
* @return bool
|
||||
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||
*/
|
||||
public function assertNodeNotPublished($nid, $message = NULL, $group = 'Other') {
|
||||
@ -119,14 +123,14 @@ class SchedulerApiTestCase extends DrupalWebTestCase {
|
||||
/**
|
||||
* Check to see if a node is published.
|
||||
*
|
||||
* @param $nid
|
||||
* The nid of the node to check.
|
||||
* @param $message
|
||||
* @param int $nid
|
||||
* The id of the node to check.
|
||||
* @param string $message
|
||||
* The message to display along with the assertion.
|
||||
* @param $group
|
||||
* @param string $group
|
||||
* The type of assertion - examples are "Browser", "PHP".
|
||||
*
|
||||
* @return
|
||||
* @return bool
|
||||
* TRUE if the assertion succeeded, FALSE otherwise.
|
||||
*/
|
||||
public function assertNodePublished($nid, $message = NULL, $group = 'Other') {
|
||||
@ -138,7 +142,7 @@ class SchedulerApiTestCase extends DrupalWebTestCase {
|
||||
* Returns the publication status of a node.
|
||||
*
|
||||
* @param int $nid
|
||||
* The nid of the node for which the publication status is desired.
|
||||
* The id of the node for which the publication status is desired.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the node is published, FALSE otherwise.
|
||||
|
Loading…
x
Reference in New Issue
Block a user