updated rules
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Views integration for the rules scheduler module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default scheduled task handler.
|
||||
*/
|
||||
class RulesSchedulerDefaultTaskHandler implements RulesSchedulerTaskHandlerInterface {
|
||||
|
||||
/**
|
||||
* The task array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $task;
|
||||
|
||||
/**
|
||||
* Constructs a repetitive task handler object.
|
||||
*/
|
||||
public function __construct(array $task) {
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements RulesSchedulerTaskHandlerInterface::runTask().
|
||||
*/
|
||||
public function runTask() {
|
||||
if ($component = rules_get_cache('comp_' . $this->task['config'])) {
|
||||
$replacements = array('%label' => $component->label(), '%plugin' => $component->plugin());
|
||||
$replacements['%identifier'] = $this->task['identifier'] ? $this->task['identifier'] : t('without identifier');
|
||||
rules_log('Scheduled evaluation of %plugin %label, task %identifier.', $replacements, RulesLog::INFO, $component, TRUE);
|
||||
$state = unserialize($this->task['data']);
|
||||
$state->restoreBlocks();
|
||||
// Block the config to prevent any future recursion.
|
||||
$state->block($component);
|
||||
// Finally evaluate the component with the given state.
|
||||
$component->evaluate($state);
|
||||
$state->unblock($component);
|
||||
rules_log('Finished evaluation of %plugin %label, task %identifier.', $replacements, RulesLog::INFO, $component, FALSE);
|
||||
$state->cleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements RulesSchedulerTaskHandlerInterface::afterTaskQueued().
|
||||
*/
|
||||
public function afterTaskQueued() {
|
||||
// Delete the task from the task list.
|
||||
db_delete('rules_scheduler')
|
||||
->condition('tid', $this->task['tid'])
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements RulesSchedulerTaskHandlerInterface::getTask().
|
||||
*/
|
||||
public function getTask() {
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for scheduled task handlers.
|
||||
*
|
||||
* Task handlers control the behavior of a task when it's queued or executed.
|
||||
* Unless specified otherwise, the RulesSchedulerDefaultTaskHandler task handler
|
||||
* is used.
|
||||
*
|
||||
* @see rules_scheduler_run_task()
|
||||
* @see rules_scheduler_cron()
|
||||
* @see RulesSchedulerDefaultTaskHandler
|
||||
*/
|
||||
interface RulesSchedulerTaskHandlerInterface {
|
||||
|
||||
/**
|
||||
* Processes a queue item.
|
||||
*
|
||||
* @throws RulesEvaluationException
|
||||
* If there are any problems executing the task.
|
||||
*
|
||||
* @see rules_scheduler_run_task()
|
||||
*/
|
||||
public function runTask();
|
||||
|
||||
/**
|
||||
* Processes a task after it has been queued.
|
||||
*
|
||||
* @see rules_scheduler_cron()
|
||||
*/
|
||||
public function afterTaskQueued();
|
||||
|
||||
/**
|
||||
* Returns the task associated with the task handler.
|
||||
*
|
||||
* @return array
|
||||
* The task (queue item) array.
|
||||
*/
|
||||
public function getTask();
|
||||
|
||||
}
|
@@ -6,8 +6,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_views_data(). Specifies the list of future scheduled
|
||||
* tasks displayed on the schedule page.
|
||||
* Implements hook_views_data().
|
||||
*
|
||||
* Specifies the list of future scheduled tasks displayed on the schedule page.
|
||||
*/
|
||||
function rules_scheduler_views_data() {
|
||||
$table = array(
|
||||
@@ -71,7 +72,7 @@ function rules_scheduler_views_data() {
|
||||
'click sortable' => TRUE,
|
||||
),
|
||||
'filter' => array(
|
||||
'handler' => 'views_handler_filter',
|
||||
'handler' => 'views_handler_filter_string',
|
||||
),
|
||||
'sort' => array(
|
||||
'handler' => 'views_handler_sort',
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* Implements hook_views_default_views().
|
||||
*/
|
||||
function rules_scheduler_views_default_views() {
|
||||
$view = new view;
|
||||
$view = new view();
|
||||
$view->name = 'rules_scheduler';
|
||||
$view->description = 'Scheduled Rules components';
|
||||
$view->tag = '';
|
||||
@@ -86,7 +86,7 @@ function rules_scheduler_views_default_views() {
|
||||
$handler->display->display_options['fields']['config']['field'] = 'config';
|
||||
$handler->display->display_options['fields']['config']['alter']['alter_text'] = 0;
|
||||
$handler->display->display_options['fields']['config']['alter']['make_link'] = 1;
|
||||
$handler->display->display_options['fields']['config']['alter']['path'] = 'admin/config/workflow/rules/config/[config]';
|
||||
$handler->display->display_options['fields']['config']['alter']['path'] = 'admin/config/workflow/rules/components/manage/[config]';
|
||||
$handler->display->display_options['fields']['config']['alter']['absolute'] = 0;
|
||||
$handler->display->display_options['fields']['config']['alter']['trim'] = 0;
|
||||
$handler->display->display_options['fields']['config']['alter']['word_boundary'] = 1;
|
||||
@@ -163,7 +163,7 @@ function rules_scheduler_views_default_views() {
|
||||
t('No tasks have been scheduled.'),
|
||||
t('Tid'),
|
||||
t('Component name'),
|
||||
t('admin/config/workflow/rules/config/[config]'),
|
||||
t('admin/config/workflow/rules/components/manage/[config]'),
|
||||
t('Scheduled date'),
|
||||
t('User provided identifier'),
|
||||
t('Operations'),
|
||||
|
@@ -4,8 +4,10 @@
|
||||
* @file
|
||||
* An extended subclass for component filtering.
|
||||
*/
|
||||
|
||||
class rules_scheduler_views_filter extends views_handler_filter_in_operator {
|
||||
function get_value_options() {
|
||||
|
||||
public function get_value_options() {
|
||||
if (!isset($this->value_options)) {
|
||||
$this->value_title = t('Component');
|
||||
$result = db_select('rules_scheduler', 'r')
|
||||
@@ -19,4 +21,5 @@ class rules_scheduler_views_filter extends views_handler_filter_in_operator {
|
||||
$this->value_options = $config_names;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* Schedule page with a view for the scheduled tasks.
|
||||
*/
|
||||
function rules_scheduler_schedule_page() {
|
||||
// Display view for all scheduled tasks
|
||||
// Display view for all scheduled tasks.
|
||||
if (module_exists('views')) {
|
||||
// We cannot use views_embed_view() here as we need to set the path for the
|
||||
// component filter form.
|
||||
@@ -18,7 +18,7 @@ function rules_scheduler_schedule_page() {
|
||||
$task_list = $view->preview();
|
||||
}
|
||||
else {
|
||||
$task_list = t('To display scheduled tasks you have to install the <a href="http://drupal.org/project/views">Views</a> module.');
|
||||
$task_list = t('To display scheduled tasks you have to install the <a href="https://www.drupal.org/project/views">Views</a> module.');
|
||||
}
|
||||
$page['task_view'] = array(
|
||||
'#markup' => $task_list,
|
||||
@@ -44,7 +44,7 @@ function rules_scheduler_form($form, &$form_state) {
|
||||
$form['delete_by_config'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Delete tasks by component name'),
|
||||
'#disabled' => empty($config_options)
|
||||
'#disabled' => empty($config_options),
|
||||
);
|
||||
$form['delete_by_config']['config'] = array(
|
||||
'#title' => t('Component'),
|
||||
@@ -57,7 +57,7 @@ function rules_scheduler_form($form, &$form_state) {
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Delete tasks'),
|
||||
'#submit' => array('rules_scheduler_form_delete_by_config_submit'),
|
||||
);
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,6 @@ function rules_scheduler_delete_task($form, &$form_state, $task) {
|
||||
else {
|
||||
$msg = t('This task executes component %label and will be executed on %date. The action cannot be undone.', array(
|
||||
'%label' => $config->label(),
|
||||
'%id' => $task['identifier'],
|
||||
'%date' => format_date($task['date']),
|
||||
));
|
||||
}
|
||||
@@ -116,7 +115,7 @@ function rules_scheduler_schedule_form($form, &$form_state, $rules_config, $base
|
||||
$form_state['component'] = $rules_config->name;
|
||||
$action = rules_action('schedule', array('component' => $rules_config->name));
|
||||
$action->form($form, $form_state);
|
||||
// The component should be fixed, so hide the paramter for it.
|
||||
// The component should be fixed, so hide the parameter for it.
|
||||
$form['parameter']['component']['#access'] = FALSE;
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Rules Scheduler Drush integration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_drush_command().
|
||||
*/
|
||||
function rules_scheduler_drush_command() {
|
||||
$items = array();
|
||||
|
||||
$items['rules-scheduler-tasks'] = array(
|
||||
'description' => 'Check for scheduled tasks to be added to the queue.',
|
||||
'options' => array(
|
||||
'claim' => 'Optionally claim tasks from the queue to work on. Any value set will override the default time spent on this queue.',
|
||||
),
|
||||
'drupal dependencies' => array('rules', 'rules_scheduler'),
|
||||
'aliases' => array('rusch'),
|
||||
'examples' => array(
|
||||
'drush rusch' => 'Add scheduled tasks to the queue.',
|
||||
'drush rusch --claim' => 'Add scheduled tasks to the queue and claim items for the default amount of time.',
|
||||
'drush rusch --claim=30' => 'Add scheduled tasks to the queue and claim items for 30 seconds.',
|
||||
),
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_drush_help().
|
||||
*/
|
||||
function rules_scheduler_drush_help($section) {
|
||||
switch ($section) {
|
||||
case 'drush:rules-scheduler-tasks':
|
||||
return dt('Checks for scheduled tasks to be added the queue. Can optionally claim tasks from the queue to work on.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback for processing the rules_scheduler_tasks queue.
|
||||
*
|
||||
* @see rules_scheduler_cron_queue_info()
|
||||
* @see rules_scheduler_cron()
|
||||
*/
|
||||
function drush_rules_scheduler_tasks() {
|
||||
if (rules_scheduler_queue_tasks()) {
|
||||
// hook_exit() is not invoked for drush runs, so register it as shutdown
|
||||
// callback for logging the rules log to the watchdog.
|
||||
drupal_register_shutdown_function('rules_exit');
|
||||
// Clear the log before running tasks via the queue to avoid logging
|
||||
// unrelated logs from previous operations.
|
||||
RulesLog::logger()->clear();
|
||||
drush_log(dt('Added scheduled tasks to the queue.'), 'success');
|
||||
}
|
||||
|
||||
$claim = drush_get_option('claim', FALSE);
|
||||
if ($claim) {
|
||||
// Fetch the queue information and let other modules alter it.
|
||||
$queue_name = 'rules_scheduler_tasks';
|
||||
$info = module_invoke('rules_scheduler', 'cron_queue_info');
|
||||
drupal_alter('cron_queue_info', $info);
|
||||
|
||||
$function = $info[$queue_name]['worker callback'];
|
||||
// The drush option can override the default process time.
|
||||
$time = is_numeric($claim) ? (int) $claim : $info[$queue_name]['time'];
|
||||
$end = time() + $time;
|
||||
// Claim items and process the queue.
|
||||
$queue = DrupalQueue::get($queue_name);
|
||||
$claimed = 0;
|
||||
while (time() < $end && ($item = $queue->claimItem())) {
|
||||
$function($item->data);
|
||||
$queue->deleteItem($item);
|
||||
$claimed++;
|
||||
}
|
||||
if ($claimed) {
|
||||
drush_log(dt('Claimed and worked on !claimed scheduled tasks for up to !time seconds.', array('!claimed' => $claimed, '!time' => $time)), 'success');
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,18 +3,17 @@ description = Schedule the execution of Rules components using actions.
|
||||
dependencies[] = rules
|
||||
package = Rules
|
||||
core = 7.x
|
||||
files[] = rules_scheduler.admin.inc
|
||||
files[] = rules_scheduler.module
|
||||
files[] = rules_scheduler.install
|
||||
files[] = rules_scheduler.rules.inc
|
||||
files[] = rules_scheduler.test
|
||||
files[] = includes/rules_scheduler.views_default.inc
|
||||
files[] = includes/rules_scheduler.views.inc
|
||||
files[] = includes/rules_scheduler.handler.inc
|
||||
|
||||
; Views handlers
|
||||
files[] = includes/rules_scheduler_views_filter.inc
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-27
|
||||
version = "7.x-2.3"
|
||||
; Test cases
|
||||
files[] = tests/rules_scheduler.test
|
||||
files[] = tests/rules_scheduler_test.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-01-24
|
||||
version = "7.x-2.12"
|
||||
core = "7.x"
|
||||
project = "rules"
|
||||
datestamp = "1364401818"
|
||||
|
||||
datestamp = "1548305586"
|
||||
|
@@ -30,11 +30,12 @@ function rules_scheduler_schema() {
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'state' => array(
|
||||
'type' => 'text',
|
||||
'data' => array(
|
||||
'type' => 'blob',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
'serialize' => TRUE,
|
||||
'description' => 'The whole, serialized evaluation state.',
|
||||
'description' => 'The whole, serialized evaluation data.',
|
||||
),
|
||||
'identifier' => array(
|
||||
'type' => 'varchar',
|
||||
@@ -43,6 +44,12 @@ function rules_scheduler_schema() {
|
||||
'not null' => FALSE,
|
||||
'description' => 'The user defined string identifying this task.',
|
||||
),
|
||||
'handler' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => '255',
|
||||
'not null' => FALSE,
|
||||
'description' => 'The fully-qualified class name of the queue item handler.',
|
||||
),
|
||||
),
|
||||
'primary key' => array('tid'),
|
||||
'indexes' => array(
|
||||
@@ -55,6 +62,24 @@ function rules_scheduler_schema() {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function rules_scheduler_install() {
|
||||
// Create the queue to hold scheduled tasks.
|
||||
$queue = DrupalQueue::get('rules_scheduler_tasks', TRUE);
|
||||
$queue->createQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_uninstall().
|
||||
*/
|
||||
function rules_scheduler_uninstall() {
|
||||
// Clean up after ourselves by deleting the queue and all items in it.
|
||||
$queue = DrupalQueue::get('rules_scheduler_tasks');
|
||||
$queue->deleteQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade from Rules scheduler 6.x-1.x to 7.x.
|
||||
*/
|
||||
@@ -84,11 +109,11 @@ function rules_scheduler_update_7200() {
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'state' => array(
|
||||
'data' => array(
|
||||
'type' => 'text',
|
||||
'not null' => FALSE,
|
||||
'serialize' => TRUE,
|
||||
'description' => 'The whole, serialized evaluation state.',
|
||||
'description' => 'The whole, serialized evaluation data.',
|
||||
),
|
||||
'identifier' => array(
|
||||
'type' => 'varchar',
|
||||
@@ -122,6 +147,47 @@ function rules_scheduler_update_7202() {
|
||||
db_add_unique_key('rules_scheduler', 'id', array('config', 'identifier'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a database column for specifying a queue item handler.
|
||||
*/
|
||||
function rules_scheduler_update_7203() {
|
||||
db_add_field('rules_scheduler', 'handler', array(
|
||||
'type' => 'varchar',
|
||||
'length' => '255',
|
||||
'not null' => FALSE,
|
||||
'description' => 'The fully-qualified class name of the queue item handler.',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename rules_scheduler.state into rules_scheduler.data.
|
||||
*/
|
||||
function rules_scheduler_update_7204() {
|
||||
if (db_field_exists('rules_scheduler', 'state')) {
|
||||
db_change_field('rules_scheduler', 'state', 'data', array(
|
||||
'type' => 'text',
|
||||
'not null' => FALSE,
|
||||
'serialize' => TRUE,
|
||||
'description' => 'The whole, serialized evaluation data.',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use blob:big for rules_scheduler.data for compatibility with PostgreSQL.
|
||||
*/
|
||||
function rules_scheduler_update_7205() {
|
||||
if (db_field_exists('rules_scheduler', 'data')) {
|
||||
db_change_field('rules_scheduler', 'data', 'data', array(
|
||||
'type' => 'blob',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
'serialize' => TRUE,
|
||||
'description' => 'The whole, serialized evaluation data.',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules upgrade callback for mapping the action name.
|
||||
*/
|
||||
|
@@ -11,25 +11,7 @@ define('RULES_SCHEDULER_PATH', 'admin/config/workflow/rules/schedule');
|
||||
* Implements hook_cron().
|
||||
*/
|
||||
function rules_scheduler_cron() {
|
||||
// Limit adding tasks to 1000 per cron run.
|
||||
$result = db_select('rules_scheduler', 'r', array('fetch' => PDO::FETCH_ASSOC))
|
||||
->fields('r')
|
||||
->condition('date', time(), '<=')
|
||||
->range(0, 1000)
|
||||
->execute();
|
||||
|
||||
$queue = DrupalQueue::get('rules_scheduler_tasks');
|
||||
foreach ($result as $task) {
|
||||
// Add the task to the queue and remove the entry afterwards.
|
||||
if ($queue->createItem($task)) {
|
||||
db_delete('rules_scheduler')
|
||||
->condition('tid', $task['tid'])
|
||||
->execute();
|
||||
$task_created = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($task_created)) {
|
||||
if (rules_scheduler_queue_tasks()) {
|
||||
// hook_exit() is not invoked for cron runs, so register it as shutdown
|
||||
// callback for logging the rules log to the watchdog.
|
||||
drupal_register_shutdown_function('rules_exit');
|
||||
@@ -52,19 +34,43 @@ function rules_scheduler_cron_queue_info() {
|
||||
|
||||
/**
|
||||
* Queue worker callback for running a single task.
|
||||
*
|
||||
* @param array $task
|
||||
* The task to process.
|
||||
*/
|
||||
function rules_scheduler_run_task(array $task) {
|
||||
if ($component = rules_get_cache('comp_' . $task['config'])) {
|
||||
$replacements = array('%label' => $component->label(), '%plugin' => $component->plugin());
|
||||
$replacements['%identifier'] = $task['identifier'] ? $task['identifier'] : t('without identifier');
|
||||
rules_log('Scheduled evaluation of %plugin %label, task %identifier.', $replacements, RulesLog::INFO, $component, TRUE);
|
||||
$state = unserialize($task['state']);
|
||||
$state->restoreBlocks();
|
||||
// Finally evaluate the component with the given state.
|
||||
$component->evaluate($state);
|
||||
rules_log('Finished evaluation of %plugin %label, task %identifier.', $replacements, RulesLog::INFO, $component, FALSE);
|
||||
$state->cleanUp();
|
||||
try {
|
||||
// BC support for tasks that have been already queued, before update
|
||||
// rules_scheduler_update_7204() ran.
|
||||
if (isset($task['state'])) {
|
||||
$task['data'] = $task['state'];
|
||||
}
|
||||
rules_scheduler_task_handler($task)->runTask();
|
||||
}
|
||||
catch (RulesEvaluationException $e) {
|
||||
rules_log($e->msg, $e->args, $e->severity);
|
||||
rules_log('Unable to execute task with identifier %id scheduled on date %date.', array('%id' => $task['identifier'], '%date' => format_date($task['date'])), RulesLog::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the task handler for a given task.
|
||||
*
|
||||
* @param array $task
|
||||
* A task (queue item) array.
|
||||
*
|
||||
* @throws RulesEvaluationException
|
||||
* If the task handler class is missing.
|
||||
*
|
||||
* @return RulesSchedulerTaskHandlerInterface
|
||||
* The task handler.
|
||||
*/
|
||||
function rules_scheduler_task_handler(array $task) {
|
||||
$class = !empty($task['handler']) ? $task['handler'] : 'RulesSchedulerDefaultTaskHandler';
|
||||
if (!class_exists($class)) {
|
||||
throw new RulesEvaluationException('Missing task handler implementation %class.', array('%class' => $class), NULL, RulesLog::ERROR);
|
||||
}
|
||||
return new $class($task);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +103,7 @@ function rules_scheduler_menu() {
|
||||
'access arguments' => array('administer rules'),
|
||||
'file' => 'rules_scheduler.admin.inc',
|
||||
);
|
||||
$items[RULES_SCHEDULER_PATH .'/%rules_scheduler_task/delete'] = array(
|
||||
$items[RULES_SCHEDULER_PATH . '/%rules_scheduler_task/delete'] = array(
|
||||
'title' => 'Delete a scheduled task',
|
||||
'type' => MENU_CALLBACK,
|
||||
'page callback' => 'drupal_get_form',
|
||||
@@ -109,7 +115,10 @@ function rules_scheduler_menu() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a task by a given task ID.
|
||||
* Loads a task by a given task ID.
|
||||
*
|
||||
* @param int $tid
|
||||
* The task ID.
|
||||
*/
|
||||
function rules_scheduler_task_load($tid) {
|
||||
$result = db_select('rules_scheduler', 'r')
|
||||
@@ -120,7 +129,10 @@ function rules_scheduler_task_load($tid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a task by a given task ID.
|
||||
* Deletes a task by a given task ID.
|
||||
*
|
||||
* @param int $tid
|
||||
* The task ID.
|
||||
*/
|
||||
function rules_scheduler_task_delete($tid) {
|
||||
db_delete('rules_scheduler')
|
||||
@@ -131,15 +143,22 @@ function rules_scheduler_task_delete($tid) {
|
||||
/**
|
||||
* Schedule a task to be executed later on.
|
||||
*
|
||||
* @param $task
|
||||
* @param array $task
|
||||
* An array representing the task with the following keys:
|
||||
* - config: The machine readable name of the to be scheduled component.
|
||||
* - config: The machine readable name of the to-be-scheduled component.
|
||||
* - date: Timestamp when the component should be executed.
|
||||
* - state: An rules evaluation state to use for scheduling.
|
||||
* - state: (deprecated) Rules evaluation state to use for scheduling.
|
||||
* - data: Any additional data to store with the task.
|
||||
* - handler: The name of the task handler class.
|
||||
* - identifier: User provided string to identify the task per scheduled
|
||||
* configuration.
|
||||
*/
|
||||
function rules_scheduler_schedule_task($task) {
|
||||
// Map the deprecated 'state' property into 'data'.
|
||||
if (isset($task['state'])) {
|
||||
$task['data'] = $task['state'];
|
||||
unset($task['state']);
|
||||
}
|
||||
if (!empty($task['identifier'])) {
|
||||
// If there is a task with the same identifier and component, we replace it.
|
||||
db_delete('rules_scheduler')
|
||||
@@ -150,14 +169,44 @@ function rules_scheduler_schedule_task($task) {
|
||||
drupal_write_record('rules_scheduler', $task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue tasks that are ready for execution.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if any queue items where created, otherwise FALSE.
|
||||
*/
|
||||
function rules_scheduler_queue_tasks() {
|
||||
$items_created = FALSE;
|
||||
// Limit adding tasks to 1000 per cron run.
|
||||
$result = db_select('rules_scheduler', 'r', array('fetch' => PDO::FETCH_ASSOC))
|
||||
->fields('r')
|
||||
->condition('date', time(), '<=')
|
||||
->orderBy('date')
|
||||
->range(0, 1000)
|
||||
->execute();
|
||||
|
||||
$queue = DrupalQueue::get('rules_scheduler_tasks');
|
||||
foreach ($result as $task) {
|
||||
// Add the task to the queue and remove the entry afterwards.
|
||||
if ($queue->createItem($task)) {
|
||||
$items_created = TRUE;
|
||||
rules_scheduler_task_handler($task)->afterTaskQueued();
|
||||
}
|
||||
}
|
||||
return $items_created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_rules_config_delete().
|
||||
*/
|
||||
function rules_scheduler_rules_config_delete($rules_config) {
|
||||
// Delete all tasks scheduled for this config.
|
||||
db_delete('rules_scheduler')
|
||||
->condition('config', $rules_config->name)
|
||||
->execute();
|
||||
// Only react on real delete, not revert.
|
||||
if (!$rules_config->hasStatus(ENTITY_IN_CODE)) {
|
||||
// Delete all tasks scheduled for this config.
|
||||
db_delete('rules_scheduler')
|
||||
->condition('config', $rules_config->name)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,6 +215,6 @@ function rules_scheduler_rules_config_delete($rules_config) {
|
||||
function rules_scheduler_views_api() {
|
||||
return array(
|
||||
'api' => '3.0-alpha1',
|
||||
'path' => drupal_get_path('module', 'rules_scheduler') .'/includes',
|
||||
'path' => drupal_get_path('module', 'rules_scheduler') . '/includes',
|
||||
);
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
* Rules integration for the rules scheduler module.
|
||||
*
|
||||
* @addtogroup rules
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
@@ -89,7 +90,7 @@ function rules_scheduler_action_schedule($args, $element) {
|
||||
rules_scheduler_schedule_task(array(
|
||||
'date' => $args['date'],
|
||||
'config' => $args['component'],
|
||||
'state' => $new_state,
|
||||
'data' => $new_state,
|
||||
'identifier' => $args['identifier'],
|
||||
));
|
||||
}
|
||||
@@ -115,7 +116,9 @@ function rules_scheduler_action_schedule_info_alter(&$element_info, RulesPlugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate callback for the schedule action to make sure the component exists and is not dirty.
|
||||
* Validate callback for the schedule action.
|
||||
*
|
||||
* Makes sure the component exists and is not dirty.
|
||||
*
|
||||
* @see rules_element_invoke_component_validate()
|
||||
*/
|
||||
@@ -137,7 +140,7 @@ function rules_scheduler_action_schedule_validate(RulesPlugin $element) {
|
||||
*/
|
||||
function rules_scheduler_action_schedule_help() {
|
||||
return t("Note that component evaluation is triggered by <em>cron</em> – make sure cron is configured correctly by checking your site's !status. The scheduling time accuracy depends on your configured cron interval. See <a href='@url'>the online documentation</a> for more information on how to schedule evaluation of components.",
|
||||
array('!status' => l('Status report', 'admin/reports/status'),
|
||||
array('!status' => l(t('Status report'), 'admin/reports/status'),
|
||||
'@url' => rules_external_help('scheduler')));
|
||||
}
|
||||
|
||||
@@ -192,7 +195,7 @@ function rules_scheduler_action_delete($component_name = NULL, $task_identifier
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel scheduled task action validation callback.
|
||||
* Cancels scheduled task action validation callback.
|
||||
*/
|
||||
function rules_scheduler_action_delete_validate($element) {
|
||||
if (empty($element->settings['task']) && empty($element->settings['task:select']) &&
|
||||
@@ -206,7 +209,7 @@ function rules_scheduler_action_delete_validate($element) {
|
||||
* Help for the cancel action.
|
||||
*/
|
||||
function rules_scheduler_action_delete_help() {
|
||||
return t('This action allows you to delete scheduled tasks that are waiting for future execution.') .' '. t('They can be addressed by an identifier or by the component name, whereas if both are specified only tasks fulfilling both requirements will be deleted.');
|
||||
return t('This action allows you to delete scheduled tasks that are waiting for future execution.') . ' ' . t('They can be addressed by an identifier or by the component name, whereas if both are specified only tasks fulfilling both requirements will be deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -5,9 +5,15 @@
|
||||
* Rules Scheduler tests.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test cases for the Rules Scheduler module.
|
||||
*/
|
||||
class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
|
||||
static function getInfo() {
|
||||
/**
|
||||
* Declares test metadata.
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Rules Scheduler tests',
|
||||
'description' => 'Test scheduling components.',
|
||||
@@ -15,10 +21,13 @@ class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('rules_scheduler');
|
||||
/**
|
||||
* Overrides DrupalWebTestCase::setUp().
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp('rules_scheduler', 'rules_scheduler_test');
|
||||
RulesLog::logger()->clear();
|
||||
variable_set('rules_debug_log', 1);
|
||||
variable_set('rules_debug_log', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,7 +36,7 @@ class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
* Note that this also makes sure Rules properly handles timezones, else this
|
||||
* test could fail due to a wrong 'now' timestamp.
|
||||
*/
|
||||
function testComponentSchedule() {
|
||||
public function testComponentSchedule() {
|
||||
$set = rules_rule_set(array(
|
||||
'node1' => array('type' => 'node', 'label' => 'node'),
|
||||
));
|
||||
@@ -51,7 +60,7 @@ class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
$rule->execute($node);
|
||||
|
||||
// Run cron to let the rules scheduler do its work.
|
||||
drupal_cron_run();
|
||||
$this->cronRun();
|
||||
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertFalse($node->status, 'The component has been properly scheduled.');
|
||||
@@ -59,9 +68,9 @@ class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recurion prevention is working fine for scheduled rule sets.
|
||||
* Makes sure recursion prevention is working fine for scheduled rule sets.
|
||||
*/
|
||||
function testRecursionPrevention() {
|
||||
public function testRecursionPrevention() {
|
||||
$set = rules_rule_set(array(
|
||||
'node1' => array('type' => 'node', 'label' => 'node'),
|
||||
));
|
||||
@@ -78,7 +87,7 @@ class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
$rule->event('node_update');
|
||||
$rule->action('schedule', array(
|
||||
'component' => 'rules_test_set_2',
|
||||
'identifier' => '',
|
||||
'identifier' => 'test_recursion_prevention',
|
||||
'date' => 'now',
|
||||
'param_node1:select' => 'node',
|
||||
));
|
||||
@@ -87,14 +96,54 @@ class RulesSchedulerTestCase extends DrupalWebTestCase {
|
||||
// Create a node, what triggers the rule.
|
||||
$node = $this->drupalCreateNode(array('title' => 'The title.', 'status' => 1));
|
||||
// Run cron to let the rules scheduler do its work.
|
||||
drupal_cron_run();
|
||||
$this->cronRun();
|
||||
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertFalse($node->status, 'The component has been properly scheduled.');
|
||||
$text1 = RulesLog::logger()->render();
|
||||
$text2 = RulesTestCase::t('Not evaluating reaction rule %unlabeled to prevent recursion.', array('unlabeled' => $rule->name));
|
||||
$this->assertTrue((strpos($text1, $text2) !== FALSE), "Scheduled recursion prevented.");
|
||||
|
||||
// Create a simple user account with permission to see the dblog.
|
||||
$user = $this->drupalCreateUser(array('access site reports'));
|
||||
$this->drupalLogin($user);
|
||||
|
||||
// View the database log.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
|
||||
// Can't use
|
||||
// $this->clickLink('Rules debug information: " Scheduled evaluation...')
|
||||
// because xpath doesn't allow : or " in the string.
|
||||
// So instead, use our own xpath to figure out the href of the second link
|
||||
// on the page (the first link is the most recent log entry, which is the
|
||||
// log entry for the user login, above.)
|
||||
|
||||
// All links.
|
||||
$links = $this->xpath('//a[contains(@href, :href)]', array(':href' => 'admin/reports/event/'));
|
||||
// Strip off /?q= from href.
|
||||
$href = explode('=', $links[1]['href']);
|
||||
// Click the link for the RulesLog entry.
|
||||
$this->drupalGet($href[1]);
|
||||
$this->assertRaw(RulesTestCase::t('Not evaluating reaction rule %unlabeled to prevent recursion.', array('unlabeled' => $rule->name)), "Scheduled recursion prevented.");
|
||||
RulesLog::logger()->checkLog();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that custom task handlers are properly invoked.
|
||||
*/
|
||||
public function testCustomTaskHandler() {
|
||||
// Set up a scheduled task that will simply write a variable when executed.
|
||||
$variable = 'rules_schedule_task_handler_variable';
|
||||
rules_scheduler_schedule_task(array(
|
||||
'date' => REQUEST_TIME,
|
||||
'identifier' => '',
|
||||
'config' => '',
|
||||
'data' => array('variable' => $variable),
|
||||
'handler' => 'RulesTestTaskHandler',
|
||||
));
|
||||
|
||||
// Run cron to let the rules scheduler do its work.
|
||||
$this->cronRun();
|
||||
|
||||
// The task handler should have set the variable to TRUE now.
|
||||
$this->assertTrue(variable_get($variable));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Include file for Rules Scheduler tests.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test task handler class.
|
||||
*/
|
||||
class RulesTestTaskHandler extends RulesSchedulerDefaultTaskHandler {
|
||||
|
||||
/**
|
||||
* Overrides RulesSchedulerDefaultTaskHandler::runTask().
|
||||
*/
|
||||
public function runTask() {
|
||||
$task = $this->getTask();
|
||||
$data = unserialize($task['data']);
|
||||
|
||||
// Set the variable defined in the test to TRUE.
|
||||
variable_set($data['variable'], TRUE);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
name = "Rules Scheduler Tests"
|
||||
description = "Support module for the Rules Scheduler tests."
|
||||
package = Testing
|
||||
core = 7.x
|
||||
files[] = rules_scheduler_test.inc
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-01-24
|
||||
version = "7.x-2.12"
|
||||
core = "7.x"
|
||||
project = "rules"
|
||||
datestamp = "1548305586"
|
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Rules Scheduler test module.
|
||||
*/
|
Reference in New Issue
Block a user