rules_scheduler.module 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * @file
  4. * Rules scheduler module.
  5. */
  6. define('RULES_SCHEDULER_PATH', 'admin/config/workflow/rules/schedule');
  7. /**
  8. * Implements hook_cron().
  9. */
  10. function rules_scheduler_cron() {
  11. // Limit adding tasks to 1000 per cron run.
  12. $result = db_select('rules_scheduler', 'r', array('fetch' => PDO::FETCH_ASSOC))
  13. ->fields('r')
  14. ->condition('date', time(), '<=')
  15. ->range(0, 1000)
  16. ->execute();
  17. $queue = DrupalQueue::get('rules_scheduler_tasks');
  18. foreach ($result as $task) {
  19. // Add the task to the queue and remove the entry afterwards.
  20. if ($queue->createItem($task)) {
  21. db_delete('rules_scheduler')
  22. ->condition('tid', $task['tid'])
  23. ->execute();
  24. $task_created = TRUE;
  25. }
  26. }
  27. if (!empty($task_created)) {
  28. // hook_exit() is not invoked for cron runs, so register it as shutdown
  29. // callback for logging the rules log to the watchdog.
  30. drupal_register_shutdown_function('rules_exit');
  31. // Clear the log before running tasks via the queue to avoid logging
  32. // unrelated logs from previous cron-operations.
  33. RulesLog::logger()->clear();
  34. }
  35. }
  36. /**
  37. * Implements hook_cron_queue_info().
  38. */
  39. function rules_scheduler_cron_queue_info() {
  40. $queues['rules_scheduler_tasks'] = array(
  41. 'worker callback' => 'rules_scheduler_run_task',
  42. 'time' => 15,
  43. );
  44. return $queues;
  45. }
  46. /**
  47. * Queue worker callback for running a single task.
  48. */
  49. function rules_scheduler_run_task(array $task) {
  50. if ($component = rules_get_cache('comp_' . $task['config'])) {
  51. $replacements = array('%label' => $component->label(), '%plugin' => $component->plugin());
  52. $replacements['%identifier'] = $task['identifier'] ? $task['identifier'] : t('without identifier');
  53. rules_log('Scheduled evaluation of %plugin %label, task %identifier.', $replacements, RulesLog::INFO, $component, TRUE);
  54. $state = unserialize($task['state']);
  55. $state->restoreBlocks();
  56. // Finally evaluate the component with the given state.
  57. $component->evaluate($state);
  58. rules_log('Finished evaluation of %plugin %label, task %identifier.', $replacements, RulesLog::INFO, $component, FALSE);
  59. $state->cleanUp();
  60. }
  61. }
  62. /**
  63. * Implements hook_rules_ui_menu_alter().
  64. *
  65. * Adds a menu item for the 'schedule' operation.
  66. */
  67. function rules_scheduler_rules_ui_menu_alter(&$items, $base_path, $base_count) {
  68. $items[$base_path . '/manage/%rules_config/schedule'] = array(
  69. 'title callback' => 'rules_get_title',
  70. 'title arguments' => array('Schedule !plugin "!label"', $base_count + 1),
  71. 'page callback' => 'drupal_get_form',
  72. 'page arguments' => array('rules_scheduler_schedule_form', $base_count + 1, $base_path),
  73. 'access callback' => 'rules_config_access',
  74. 'access arguments' => array('update', $base_count + 1),
  75. 'file' => 'rules_scheduler.admin.inc',
  76. 'file path' => drupal_get_path('module', 'rules_scheduler'),
  77. );
  78. }
  79. /**
  80. * Implements hook_menu().
  81. */
  82. function rules_scheduler_menu() {
  83. $items = array();
  84. $items[RULES_SCHEDULER_PATH] = array(
  85. 'title' => 'Schedule',
  86. 'type' => MENU_LOCAL_TASK,
  87. 'page callback' => 'rules_scheduler_schedule_page',
  88. 'access arguments' => array('administer rules'),
  89. 'file' => 'rules_scheduler.admin.inc',
  90. );
  91. $items[RULES_SCHEDULER_PATH .'/%rules_scheduler_task/delete'] = array(
  92. 'title' => 'Delete a scheduled task',
  93. 'type' => MENU_CALLBACK,
  94. 'page callback' => 'drupal_get_form',
  95. 'page arguments' => array('rules_scheduler_delete_task', 5),
  96. 'access arguments' => array('administer rules'),
  97. 'file' => 'rules_scheduler.admin.inc',
  98. );
  99. return $items;
  100. }
  101. /**
  102. * Load a task by a given task ID.
  103. */
  104. function rules_scheduler_task_load($tid) {
  105. $result = db_select('rules_scheduler', 'r')
  106. ->fields('r')
  107. ->condition('tid', (int) $tid)
  108. ->execute();
  109. return $result->fetchAssoc();
  110. }
  111. /**
  112. * Delete a task by a given task ID.
  113. */
  114. function rules_scheduler_task_delete($tid) {
  115. db_delete('rules_scheduler')
  116. ->condition('tid', $tid)
  117. ->execute();
  118. }
  119. /**
  120. * Schedule a task to be executed later on.
  121. *
  122. * @param $task
  123. * An array representing the task with the following keys:
  124. * - config: The machine readable name of the to be scheduled component.
  125. * - date: Timestamp when the component should be executed.
  126. * - state: An rules evaluation state to use for scheduling.
  127. * - identifier: User provided string to identify the task per scheduled
  128. * configuration.
  129. */
  130. function rules_scheduler_schedule_task($task) {
  131. if (!empty($task['identifier'])) {
  132. // If there is a task with the same identifier and component, we replace it.
  133. db_delete('rules_scheduler')
  134. ->condition('config', $task['config'])
  135. ->condition('identifier', $task['identifier'])
  136. ->execute();
  137. }
  138. drupal_write_record('rules_scheduler', $task);
  139. }
  140. /**
  141. * Implements hook_rules_config_delete().
  142. */
  143. function rules_scheduler_rules_config_delete($rules_config) {
  144. // Delete all tasks scheduled for this config.
  145. db_delete('rules_scheduler')
  146. ->condition('config', $rules_config->name)
  147. ->execute();
  148. }
  149. /**
  150. * Implements hook_views_api().
  151. */
  152. function rules_scheduler_views_api() {
  153. return array(
  154. 'api' => '3.0-alpha1',
  155. 'path' => drupal_get_path('module', 'rules_scheduler') .'/includes',
  156. );
  157. }