rules_scheduler.rules.inc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. /**
  3. * @file
  4. * Rules integration for the rules scheduler module.
  5. *
  6. * @addtogroup rules
  7. *
  8. * @{
  9. */
  10. /**
  11. * Implements hook_rules_action_info().
  12. */
  13. function rules_scheduler_rules_action_info() {
  14. $items['schedule'] = array(
  15. 'label' => t('Schedule component evaluation'),
  16. 'group' => t('Rules scheduler'),
  17. 'base' => 'rules_scheduler_action_schedule',
  18. 'named parameter' => TRUE,
  19. 'parameter' => array(
  20. 'component' => array(
  21. 'type' => 'text',
  22. 'label' => t('Component'),
  23. 'options list' => 'rules_scheduler_component_options_list',
  24. 'restriction' => 'input',
  25. 'description' => 'Select the component to schedule. Only components containing actions are available – no condition sets.',
  26. ),
  27. 'date' => array(
  28. 'type' => 'date',
  29. 'label' => t('Scheduled evaluation date'),
  30. ),
  31. 'identifier' => array(
  32. 'type' => 'text',
  33. 'label' => t('Identifier'),
  34. 'description' => t('A string used for identifying this task. Any existing tasks for this component with the same identifier will be replaced.'),
  35. 'optional' => TRUE,
  36. ),
  37. // Further needed parameter by the component are added during processing.
  38. ),
  39. );
  40. // Add action to delete scheduled tasks.
  41. $items['schedule_delete'] = array(
  42. 'label' => t('Delete scheduled tasks'),
  43. 'group' => t('Rules scheduler'),
  44. 'base' => 'rules_scheduler_action_delete',
  45. 'parameter' => array(
  46. 'component' => array(
  47. 'type' => 'text',
  48. 'label' => t('Component'),
  49. 'options list' => 'rules_scheduler_component_options_list',
  50. 'description' => t('The component for which scheduled tasks will be deleted.'),
  51. 'optional' => TRUE,
  52. ),
  53. 'task' => array(
  54. 'type' => 'text',
  55. 'label' => t('Task identifier'),
  56. 'description' => t('All tasks that are annotated with the given identifier will be deleted.'),
  57. 'optional' => TRUE,
  58. ),
  59. ),
  60. );
  61. return $items;
  62. }
  63. /**
  64. * Options list callback returning a list of action components.
  65. */
  66. function rules_scheduler_component_options_list() {
  67. return rules_get_components(TRUE, 'action');
  68. }
  69. /**
  70. * Base action implementation for scheduling components.
  71. */
  72. function rules_scheduler_action_schedule($args, $element) {
  73. $state = $args['state'];
  74. if ($component = rules_get_cache('comp_' . $args['component'])) {
  75. // Manually create a new evaluation state for scheduling the evaluation.
  76. $new_state = new RulesState();
  77. // Register all parameters as variables.
  78. foreach ($element->pluginParameterInfo() as $name => $info) {
  79. if (strpos($name, 'param_') === 0) {
  80. // Remove the parameter name prefix 'param_'.
  81. $var_name = substr($name, 6);
  82. $new_state->addVariable($var_name, $state->currentArguments[$name], $info);
  83. }
  84. }
  85. rules_scheduler_schedule_task(array(
  86. 'date' => $args['date'],
  87. 'config' => $args['component'],
  88. 'data' => $new_state,
  89. 'identifier' => $args['identifier'],
  90. ));
  91. }
  92. else {
  93. throw new RulesEvaluationException('Unable to get the component %name', array('%name' => $args['component']), $element, RulesLog::ERROR);
  94. }
  95. }
  96. /**
  97. * Info alteration callback for the schedule action.
  98. */
  99. function rules_scheduler_action_schedule_info_alter(&$element_info, RulesPlugin $element) {
  100. if (isset($element->settings['component'])) {
  101. // If run during a cache rebuild the cache might not be instantiated yet,
  102. // so fail back to loading the component from database.
  103. if (($component = rules_get_cache('comp_' . $element->settings['component'])) || $component = rules_config_load($element->settings['component'])) {
  104. // Add in the needed parameters.
  105. foreach ($component->parameterInfo() as $name => $info) {
  106. $element_info['parameter']['param_' . $name] = $info;
  107. }
  108. }
  109. }
  110. }
  111. /**
  112. * Validate callback for the schedule action.
  113. *
  114. * Makes sure the component exists and is not dirty.
  115. *
  116. * @see rules_element_invoke_component_validate()
  117. */
  118. function rules_scheduler_action_schedule_validate(RulesPlugin $element) {
  119. $info = $element->info();
  120. $component = rules_config_load($element->settings['component']);
  121. if (!$component) {
  122. throw new RulesIntegrityException(t('The component %config does not exist.', array('%config' => $element->settings['component'])), $element);
  123. }
  124. // Check if the component is marked as dirty.
  125. rules_config_update_dirty_flag($component);
  126. if (!empty($component->dirty)) {
  127. throw new RulesIntegrityException(t('The utilized component %config fails the integrity check.', array('%config' => $element->settings['component'])), $element);
  128. }
  129. }
  130. /**
  131. * Help for the schedule action.
  132. */
  133. function rules_scheduler_action_schedule_help() {
  134. 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.",
  135. array('!status' => l(t('Status report'), 'admin/reports/status'),
  136. '@url' => rules_external_help('scheduler')));
  137. }
  138. /**
  139. * Form alter callback for the schedule action.
  140. */
  141. function rules_scheduler_action_schedule_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) {
  142. $first_step = empty($element->settings['component']);
  143. $form['reload'] = array(
  144. '#weight' => 5,
  145. '#type' => 'submit',
  146. '#name' => 'reload',
  147. '#value' => $first_step ? t('Continue') : t('Reload form'),
  148. '#limit_validation_errors' => array(array('parameter', 'component')),
  149. '#submit' => array('rules_action_type_form_submit_rebuild'),
  150. '#ajax' => rules_ui_form_default_ajax(),
  151. );
  152. // Use ajax and trigger as the reload button.
  153. $form['parameter']['component']['settings']['type']['#ajax'] = $form['reload']['#ajax'] + array(
  154. 'event' => 'change',
  155. 'trigger_as' => array('name' => 'reload'),
  156. );
  157. if ($first_step) {
  158. // In the first step show only the component select.
  159. foreach (element_children($form['parameter']) as $key) {
  160. if ($key != 'component') {
  161. unset($form['parameter'][$key]);
  162. }
  163. }
  164. unset($form['submit']);
  165. unset($form['provides']);
  166. }
  167. else {
  168. // Hide the reload button in case js is enabled and it's not the first step.
  169. $form['reload']['#attributes'] = array('class' => array('rules-hide-js'));
  170. }
  171. }
  172. /**
  173. * Action: Delete scheduled tasks.
  174. */
  175. function rules_scheduler_action_delete($component_name = NULL, $task_identifier = NULL) {
  176. $query = db_delete('rules_scheduler');
  177. if (!empty($component_name)) {
  178. $query->condition('config', $component_name);
  179. }
  180. if (!empty($task_identifier)) {
  181. $query->condition('identifier', $task_identifier);
  182. }
  183. $query->execute();
  184. }
  185. /**
  186. * Cancels scheduled task action validation callback.
  187. */
  188. function rules_scheduler_action_delete_validate($element) {
  189. if (empty($element->settings['task']) && empty($element->settings['task:select']) &&
  190. empty($element->settings['component']) && empty($element->settings['component:select'])) {
  191. throw new RulesIntegrityException(t('You have to specify at least either a component or a task identifier.'), $element);
  192. }
  193. }
  194. /**
  195. * Help for the cancel action.
  196. */
  197. function rules_scheduler_action_delete_help() {
  198. 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.');
  199. }
  200. /**
  201. * @}
  202. */