1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* Rules scheduler module.
|
6 |
|
|
*/
|
7 |
|
|
|
8 |
|
|
define('RULES_SCHEDULER_PATH', 'admin/config/workflow/rules/schedule');
|
9 |
|
|
|
10 |
|
|
/**
|
11 |
|
|
* Implements hook_cron().
|
12 |
|
|
*/
|
13 |
|
|
function rules_scheduler_cron() {
|
14 |
|
|
if (rules_scheduler_queue_tasks()) {
|
15 |
|
|
// hook_exit() is not invoked for cron runs, so register it as shutdown
|
16 |
|
|
// callback for logging the rules log to the watchdog.
|
17 |
|
|
drupal_register_shutdown_function('rules_exit');
|
18 |
|
|
// Clear the log before running tasks via the queue to avoid logging
|
19 |
|
|
// unrelated logs from previous cron-operations.
|
20 |
|
|
RulesLog::logger()->clear();
|
21 |
|
|
}
|
22 |
|
|
}
|
23 |
|
|
|
24 |
|
|
/**
|
25 |
|
|
* Implements hook_cron_queue_info().
|
26 |
|
|
*/
|
27 |
|
|
function rules_scheduler_cron_queue_info() {
|
28 |
|
|
$queues['rules_scheduler_tasks'] = array(
|
29 |
|
|
'worker callback' => 'rules_scheduler_run_task',
|
30 |
|
|
'time' => 15,
|
31 |
|
|
);
|
32 |
|
|
return $queues;
|
33 |
|
|
}
|
34 |
|
|
|
35 |
|
|
/**
|
36 |
|
|
* Queue worker callback for running a single task.
|
37 |
|
|
*
|
38 |
|
|
* @param array $task
|
39 |
|
|
* The task to process.
|
40 |
|
|
*/
|
41 |
|
|
function rules_scheduler_run_task(array $task) {
|
42 |
|
|
try {
|
43 |
76e2e7c3
|
Assos Assos
|
// BC support for tasks that have been already queued, before update
|
44 |
|
|
// rules_scheduler_update_7204() ran.
|
45 |
|
|
if (isset($task['state'])) {
|
46 |
|
|
$task['data'] = $task['state'];
|
47 |
|
|
}
|
48 |
85ad3d82
|
Assos Assos
|
rules_scheduler_task_handler($task)->runTask();
|
49 |
|
|
}
|
50 |
|
|
catch (RulesEvaluationException $e) {
|
51 |
|
|
rules_log($e->msg, $e->args, $e->severity);
|
52 |
|
|
rules_log('Unable to execute task with identifier %id scheduled on date %date.', array('%id' => $task['identifier'], '%date' => format_date($task['date'])), RulesLog::ERROR);
|
53 |
|
|
}
|
54 |
|
|
}
|
55 |
|
|
|
56 |
|
|
/**
|
57 |
|
|
* Returns the task handler for a given task.
|
58 |
|
|
*
|
59 |
|
|
* @param array $task
|
60 |
|
|
* A task (queue item) array.
|
61 |
|
|
*
|
62 |
|
|
* @throws RulesEvaluationException
|
63 |
|
|
* If the task handler class is missing.
|
64 |
|
|
*
|
65 |
|
|
* @return RulesSchedulerTaskHandlerInterface
|
66 |
|
|
* The task handler.
|
67 |
|
|
*/
|
68 |
|
|
function rules_scheduler_task_handler(array $task) {
|
69 |
|
|
$class = !empty($task['handler']) ? $task['handler'] : 'RulesSchedulerDefaultTaskHandler';
|
70 |
|
|
if (!class_exists($class)) {
|
71 |
|
|
throw new RulesEvaluationException('Missing task handler implementation %class.', array('%class' => $class), NULL, RulesLog::ERROR);
|
72 |
|
|
}
|
73 |
|
|
return new $class($task);
|
74 |
|
|
}
|
75 |
|
|
|
76 |
|
|
/**
|
77 |
|
|
* Implements hook_rules_ui_menu_alter().
|
78 |
|
|
*
|
79 |
|
|
* Adds a menu item for the 'schedule' operation.
|
80 |
|
|
*/
|
81 |
|
|
function rules_scheduler_rules_ui_menu_alter(&$items, $base_path, $base_count) {
|
82 |
|
|
$items[$base_path . '/manage/%rules_config/schedule'] = array(
|
83 |
|
|
'title callback' => 'rules_get_title',
|
84 |
|
|
'title arguments' => array('Schedule !plugin "!label"', $base_count + 1),
|
85 |
|
|
'page callback' => 'drupal_get_form',
|
86 |
|
|
'page arguments' => array('rules_scheduler_schedule_form', $base_count + 1, $base_path),
|
87 |
|
|
'access callback' => 'rules_config_access',
|
88 |
|
|
'access arguments' => array('update', $base_count + 1),
|
89 |
|
|
'file' => 'rules_scheduler.admin.inc',
|
90 |
|
|
'file path' => drupal_get_path('module', 'rules_scheduler'),
|
91 |
|
|
);
|
92 |
|
|
}
|
93 |
|
|
|
94 |
|
|
/**
|
95 |
|
|
* Implements hook_menu().
|
96 |
|
|
*/
|
97 |
|
|
function rules_scheduler_menu() {
|
98 |
|
|
$items = array();
|
99 |
|
|
$items[RULES_SCHEDULER_PATH] = array(
|
100 |
|
|
'title' => 'Schedule',
|
101 |
|
|
'type' => MENU_LOCAL_TASK,
|
102 |
|
|
'page callback' => 'rules_scheduler_schedule_page',
|
103 |
|
|
'access arguments' => array('administer rules'),
|
104 |
|
|
'file' => 'rules_scheduler.admin.inc',
|
105 |
|
|
);
|
106 |
|
|
$items[RULES_SCHEDULER_PATH .'/%rules_scheduler_task/delete'] = array(
|
107 |
|
|
'title' => 'Delete a scheduled task',
|
108 |
|
|
'type' => MENU_CALLBACK,
|
109 |
|
|
'page callback' => 'drupal_get_form',
|
110 |
|
|
'page arguments' => array('rules_scheduler_delete_task', 5),
|
111 |
|
|
'access arguments' => array('administer rules'),
|
112 |
|
|
'file' => 'rules_scheduler.admin.inc',
|
113 |
|
|
);
|
114 |
|
|
return $items;
|
115 |
|
|
}
|
116 |
|
|
|
117 |
|
|
/**
|
118 |
|
|
* Load a task by a given task ID.
|
119 |
|
|
*/
|
120 |
|
|
function rules_scheduler_task_load($tid) {
|
121 |
|
|
$result = db_select('rules_scheduler', 'r')
|
122 |
|
|
->fields('r')
|
123 |
|
|
->condition('tid', (int) $tid)
|
124 |
|
|
->execute();
|
125 |
|
|
return $result->fetchAssoc();
|
126 |
|
|
}
|
127 |
|
|
|
128 |
|
|
/**
|
129 |
|
|
* Delete a task by a given task ID.
|
130 |
|
|
*/
|
131 |
|
|
function rules_scheduler_task_delete($tid) {
|
132 |
|
|
db_delete('rules_scheduler')
|
133 |
|
|
->condition('tid', $tid)
|
134 |
|
|
->execute();
|
135 |
|
|
}
|
136 |
|
|
|
137 |
|
|
/**
|
138 |
|
|
* Schedule a task to be executed later on.
|
139 |
|
|
*
|
140 |
|
|
* @param $task
|
141 |
|
|
* An array representing the task with the following keys:
|
142 |
|
|
* - config: The machine readable name of the to be scheduled component.
|
143 |
|
|
* - date: Timestamp when the component should be executed.
|
144 |
|
|
* - state: (deprecated) Rules evaluation state to use for scheduling.
|
145 |
|
|
* - data: Any additional data to store with the task.
|
146 |
|
|
* - handler: The name of the task handler class.
|
147 |
|
|
* - identifier: User provided string to identify the task per scheduled
|
148 |
|
|
* configuration.
|
149 |
|
|
*/
|
150 |
|
|
function rules_scheduler_schedule_task($task) {
|
151 |
|
|
// Map the deprecated 'state' property into 'data'.
|
152 |
|
|
if (isset($task['state'])) {
|
153 |
|
|
$task['data'] = $task['state'];
|
154 |
|
|
unset($task['state']);
|
155 |
|
|
}
|
156 |
|
|
if (!empty($task['identifier'])) {
|
157 |
|
|
// If there is a task with the same identifier and component, we replace it.
|
158 |
|
|
db_delete('rules_scheduler')
|
159 |
|
|
->condition('config', $task['config'])
|
160 |
|
|
->condition('identifier', $task['identifier'])
|
161 |
|
|
->execute();
|
162 |
|
|
}
|
163 |
|
|
drupal_write_record('rules_scheduler', $task);
|
164 |
|
|
}
|
165 |
|
|
|
166 |
|
|
/**
|
167 |
|
|
* Queue tasks that are ready for execution.
|
168 |
|
|
*
|
169 |
|
|
* @return boolean
|
170 |
|
|
* Returns TRUE if any queue items where created, otherwise FALSE.
|
171 |
|
|
*/
|
172 |
|
|
function rules_scheduler_queue_tasks() {
|
173 |
|
|
$items_created = FALSE;
|
174 |
|
|
// Limit adding tasks to 1000 per cron run.
|
175 |
|
|
$result = db_select('rules_scheduler', 'r', array('fetch' => PDO::FETCH_ASSOC))
|
176 |
|
|
->fields('r')
|
177 |
|
|
->condition('date', time(), '<=')
|
178 |
|
|
->orderBy('date')
|
179 |
|
|
->range(0, 1000)
|
180 |
|
|
->execute();
|
181 |
|
|
|
182 |
|
|
$queue = DrupalQueue::get('rules_scheduler_tasks');
|
183 |
|
|
foreach ($result as $task) {
|
184 |
|
|
// Add the task to the queue and remove the entry afterwards.
|
185 |
|
|
if ($queue->createItem($task)) {
|
186 |
|
|
$items_created = TRUE;
|
187 |
|
|
rules_scheduler_task_handler($task)->afterTaskQueued();
|
188 |
|
|
}
|
189 |
|
|
}
|
190 |
|
|
return $items_created;
|
191 |
|
|
}
|
192 |
|
|
|
193 |
|
|
/**
|
194 |
|
|
* Implements hook_rules_config_delete().
|
195 |
|
|
*/
|
196 |
|
|
function rules_scheduler_rules_config_delete($rules_config) {
|
197 |
76e2e7c3
|
Assos Assos
|
// Only react on real delete, not revert.
|
198 |
|
|
if (!$rules_config->hasStatus(ENTITY_IN_CODE)) {
|
199 |
|
|
// Delete all tasks scheduled for this config.
|
200 |
|
|
db_delete('rules_scheduler')
|
201 |
|
|
->condition('config', $rules_config->name)
|
202 |
|
|
->execute();
|
203 |
|
|
}
|
204 |
85ad3d82
|
Assos Assos
|
}
|
205 |
|
|
|
206 |
|
|
/**
|
207 |
|
|
* Implements hook_views_api().
|
208 |
|
|
*/
|
209 |
|
|
function rules_scheduler_views_api() {
|
210 |
|
|
return array(
|
211 |
|
|
'api' => '3.0-alpha1',
|
212 |
|
|
'path' => drupal_get_path('module', 'rules_scheduler') .'/includes',
|
213 |
|
|
);
|
214 |
|
|
} |