? rules-455560.patch
Index: rules_scheduler/rules_scheduler.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_scheduler/Attic/rules_scheduler.install,v
retrieving revision 1.1.2.5
diff -u -p -r1.1.2.5 rules_scheduler.install
--- rules_scheduler/rules_scheduler.install	19 Apr 2009 18:19:07 -0000	1.1.2.5
+++ rules_scheduler/rules_scheduler.install	5 Jul 2009 21:10:46 -0000
@@ -3,7 +3,8 @@
 
 
 /**
- * @file Rules Scheduler - Installation file.
+ * @file
+ * Rules Scheduler - Installation file.
  */
 
 /**
@@ -21,7 +22,7 @@ function rules_scheduler_uninstall() {
 }
 
 /**
- * Implementation of hook_schema.
+ * Implementation of hook_schema().
  */
 function rules_scheduler_schema() {
 
@@ -52,6 +53,13 @@ function rules_scheduler_schema() {
         'serialize' => TRUE,
         'description' => t('The whole, serialized item configuration.'),
       ),
+      'identifier' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'default' => '',
+        'not null' => FALSE,
+        'description' => t('The user defined string identifying this task.'),
+      ),
     ),
     'primary key' => array('tid'),
     'indexes' => array('date' => array('date')),
@@ -59,3 +67,19 @@ function rules_scheduler_schema() {
   return $schema;
 }
 
+/**
+ * Implementation of hook_update_N(). Adds an identifier field to the table.
+ */
+function rules_scheduler_update_6100() {
+  $spec = array(
+    'type' => 'varchar',
+    'length' => '255',
+    'default' => '',
+    'not null' => FALSE,
+    'description' => t('The user defined string identifying this task.'),
+  );
+  $ret = array();
+  db_add_field($ret, 'rules_scheduler', 'identifier', $spec);
+  return $ret;
+}
+
Index: rules_scheduler/rules_scheduler.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_scheduler/Attic/rules_scheduler.module,v
retrieving revision 1.1.2.4
diff -u -p -r1.1.2.4 rules_scheduler.module
--- rules_scheduler/rules_scheduler.module	19 Apr 2009 15:03:43 -0000	1.1.2.4
+++ rules_scheduler/rules_scheduler.module	5 Jul 2009 21:10:46 -0000
@@ -3,9 +3,13 @@
 
 
 /**
- * @file Rules scheduler module
+ * @file
+ * Rules scheduler module.
  */
 
+// Path definition for scheduling page
+define('RULES_SCHEDULER_PATH', RULES_ADMIN_SET_PATH .'/scheduling');
+
 /**
  * Implementation of hook_cron().
  */
@@ -28,3 +32,281 @@ function rules_scheduler_cron() {
   }
 }
 
+/**
+ * Implementation of hook_menu().
+ */
+function rules_scheduler_menu() {
+  $items = array();
+  $items[RULES_SCHEDULER_PATH] = array(
+    'title' => 'Scheduling',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'rules_scheduler_scheduling',
+    'access arguments' => array('administer rules'),
+  );
+  $items[RULES_SCHEDULER_PATH .'/%rules_scheduler_tid/delete'] = array(
+    'title' => 'Delete a scheduled task',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rules_scheduler_delete_task', 4),
+    'access arguments' => array('administer rules'),
+    'load arguments' => array(4),
+  );
+  return $items;
+}
+
+function rules_scheduler_scheduling() {
+  return drupal_get_form('rules_scheduler_form');
+}
+
+/**
+ * Builds the scheduling page with a form for manual scheduling and deletion of tasks.
+ */
+function rules_scheduler_form($form_state) {
+  $form = array();
+  // Display view for all scheduled tasks
+  if (module_exists('views')) {
+    $task_list = views_embed_view('rules_scheduler');
+  }
+  else {
+    $task_list = t('To display scheduled tasks you have to install the <a href="http://drupal.org/project/views">Views</a> module.');
+  }
+  $form['task_view'] = array(
+    '#type' => 'markup',
+    '#value' => $task_list,
+  );
+  
+  // form fieldset for manual scheduling
+  $form['manual_scheduling'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Manual scheduling of rule sets without arguments'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $rulesets = rules_scheduler_rulesets_without_arguments();
+  if (empty($rulesets)) {
+    $form['manual_scheduling']['#description'] = t('There are currently no rule sets without arguments available.');
+  }
+  else {
+    $form['manual_scheduling']['ruleset_manual'] = array(
+      '#title' => t('Rule set name'),
+      '#type' => 'select',
+      '#options' => $rulesets,
+      '#multiple' => FALSE,
+    );
+    $form['manual_scheduling']['task_identifier'] = array(
+      '#title' => t('Identifier'),
+      '#type' => 'textfield',
+      '#description' => t('User provided string to identify the task.'),
+    );
+    $rules_date = new rules_data_type_date();
+    $form['manual_scheduling']['date'] = $rules_date->get_default_input_form(array('label' => 'Execution date'), NULL);
+    $form['manual_scheduling']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Schedule'),
+      '#submit' => array('rules_scheduler_manual_submit'),
+    );
+  }
+  
+  // form fieldset for deleting by rule set name
+  $result = db_query("SELECT DISTINCT set_name FROM {rules_scheduler}");
+  $ruleset_names = array();
+  while ($name = db_fetch_array($result)) {
+    $ruleset_names[$name['set_name']] = $name['set_name'];
+  }
+  
+  $form['delete_by_ruleset_name'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Delete tasks by rule set name'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  if (empty($ruleset_names)) {
+    $form['delete_by_ruleset_name']['#description'] = t('There are currently no scheduled tasks available to delete.');
+  }
+  else {
+    $form['delete_by_ruleset_name']['ruleset_delete'] = array(
+      '#title' => t('Rule set name'),
+      '#type' => 'select',
+      '#options' => $ruleset_names,
+      '#multiple' => FALSE,
+    );
+    $form['delete_by_ruleset_name']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Delete'),
+      '#submit' => array('rules_scheduler_delete_submit'),
+    );
+  }
+  
+  return $form;
+}
+
+/**
+ * Retrieves all rule sets that do not have arguments attached.
+ */
+function rules_scheduler_rulesets_without_arguments() {
+  $rule_sets = array();
+  foreach (rules_get_configured_items('rule_sets') as $name => $set_info) {
+    if (empty($set_info['arguments'])) {
+      $rule_sets[$name] = $set_info['label'] .' ('. $name .')';
+    }
+  }
+  return $rule_sets;
+}
+
+/**
+ * Submit handler for manual scheduling of tasks.
+ */
+function rules_scheduler_manual_submit($form, &$form_state) {
+  $pack = rules_pack_variables(array(), NULL);
+  if ($pack === FALSE) {
+    rules_log(t('Packing arguments for scheduling the rule set %set failed.', array('%set' => $element['#info']['set'])), TRUE);
+  }
+  else {
+    $rules_date = new rules_data_type_date();
+    $date = $rules_date->check_value(array('label' => 'execution date'), $form_state['values']['date']);
+    drupal_write_record('rules_scheduler', $task = array(
+        'date' => $date,
+        'set_name' => $form_state['values']['ruleset_manual'],
+        'arguments' => $pack,
+        'identifier' => $form_state['values']['task_identifier'],
+      ));
+  }
+  drupal_set_message(t('The rule set %name has been scheduled on %date.', array('%name' => $form_state['values']['ruleset_manual'], '%date' => $date)));
+}
+
+/**
+ * Submit handler for deletion/cancellation of future scheduled tasks.
+ */
+function rules_scheduler_delete_submit($form, &$form_state) {
+  require_once('rules_scheduler.rules.inc');
+  rules_scheduler_action_delete(NULL, $form_state['values']['ruleset_delete']);
+  drupal_set_message(t('All tasks associated with %ruleset have been deleted.', array('%ruleset' => $form_state['values']['ruleset_delete'])));
+}
+
+/**
+ * Load a task by a given task ID.
+ */
+function rules_scheduler_tid_load($tid) {
+  $result = db_query("SELECT * FROM {rules_scheduler} WHERE tid = %d", $tid);
+  $task = db_fetch_array($result);
+  return $task;
+}
+
+/**
+ * Confirmation form for deleting single tasks.
+ */
+function rules_scheduler_delete_task(&$form_state, $task) {
+  $form = array();
+  $form_state['task'] = $task;
+
+  $path = array();
+  $path['path'] = isset($_GET['destination']) ? $_GET['destination'] : RULES_SCHEDULER_PATH;
+  
+  $title = t('Are you sure you want to delete task %tid?', array('%tid' => $task['tid']));
+  if (!empty($task['identifier'])) {
+    $msg = t('This task refers to the custom identifier %id and rule set %ruleset, it will be executed on %date. The delete action cannot be undone.', array(
+      '%ruleset' => $task['set_name'],
+      '%id' => $task['identifier'],
+      '%date' => $task['date'],
+    ));
+  }
+  else {
+    $msg = t('This task refers to the rule set %ruleset and will be executed on %date. The delete action cannot be undone.', array(
+      '%ruleset' => $task['set_name'],
+      '%id' => $task['identifier'],
+      '%date' => $task['date'],
+    ));
+  }
+  return confirm_form($form, $title, $path, $msg, t('Delete'), t('Cancel'));
+}
+
+/**
+ * Submit handler for deleting single tasks.
+ */
+function rules_scheduler_delete_task_submit($form, &$form_state) {
+  db_query("DELETE FROM {rules_scheduler} WHERE tid = %d", $form_state['task']['tid']);
+  drupal_set_message(t("Task %label has been deleted.", array('%label' => $form_state['task']['tid'])));
+  $form_state['redirect'] = RULES_SCHEDULER_PATH;
+}
+
+
+/**
+ * Implementation of hook_views_data(). Specifies the list of future scheduled
+ * tasks displayed on the scheduling page.
+ */
+function rules_scheduler_views_data() {
+  $table = array(
+    'rules_scheduler' => array(
+      'table' => array(
+        'group' => 'Rules scheduler',
+        'base' => array(
+          'field' => 'tid',
+          'title' => t('Scheduled rule sets'),
+          'help' => t("Scheduled rules that are executed based on time and cron"),
+          'weight' => -10,
+        ),
+      ),
+      'tid' => array(
+        'title' => t('Tid'),
+        'help' => t('The internal ID of the scheduled rule set'),
+        'field' => array(
+          'click sortable' => TRUE,
+        ),
+        'filter' => array(
+          'handler' => 'views_handler_filter_numeric',
+        ),
+        'sort' => array(
+          'handler' => 'views_handler_sort',
+        ),
+      ),
+      'set_name' => array(
+        'title' => t('Rule set name'),
+        'help' => t('The name of the rule set'),
+        'field' => array(
+          'click sortable' => TRUE,
+        ),
+        'filter' => array(
+          'handler' => 'views_handler_filter',
+        ),
+        'sort' => array(
+          'handler' => 'views_handler_sort',
+        ),
+      ),
+      'date' => array(
+        'title' => t('Scheduled date'),
+        'help' => t('Scheduled date and time stamp'),
+        'field' => array(
+          'handler' => 'rules_scheduler_datetime',
+          'click sortable' => TRUE,
+        ),
+        'filter' => array(
+          'handler' => 'views_handler_filter',
+        ),
+        'sort' => array(
+          'handler' => 'views_handler_sort',
+        ),
+      ),
+      'identifier' => array(
+        'title' => t('User provided identifier'),
+        'help' => t('ID to recognize this specific scheduled task'),
+        'field' => array(
+          'click sortable' => TRUE,
+        ),
+        'filter' => array(
+          'handler' => 'views_handler_filter',
+        ),
+        'sort' => array(
+          'handler' => 'views_handler_sort',
+        ),
+      ),
+    ),
+  );
+  return $table;
+}
+
+/**
+ * Implementation of hook_views_api().
+ */
+function rules_scheduler_views_api() {
+  return array('api' => 2.0);
+}
\ No newline at end of file
Index: rules_scheduler/rules_scheduler.rules.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/rules/rules_scheduler/Attic/rules_scheduler.rules.inc,v
retrieving revision 1.1.2.4
diff -u -p -r1.1.2.4 rules_scheduler.rules.inc
--- rules_scheduler/rules_scheduler.rules.inc	19 Apr 2009 15:03:43 -0000	1.1.2.4
+++ rules_scheduler/rules_scheduler.rules.inc	5 Jul 2009 21:10:46 -0000
@@ -3,7 +3,8 @@
 
 
 /**
- * @file rules integration for the rules scheduler module
+ * @file
+ * Rules integration for the rules scheduler module.
  */
 
 /**
@@ -26,7 +27,32 @@ function rules_scheduler_rules_action_in
         'label' => t('Scheduled evaluation date'),
       ));
     $item['arguments'] = array_merge($date_arg, $item['arguments']);
+    $identifier_arg = array('task_identifier' => array(
+        'type' => 'string',
+        'label' => t('Identifier'),
+        'description' => t('User provided string to identify the task.'),
+      ));
+    $item['arguments'] = array_merge($identifier_arg, $item['arguments']);
   }
+  
+  // Add action to delete scheduled rule sets
+  $items['rules_action_delete_scheduled_set'] = array(
+    'label' => t('Delete scheduled rule sets'),
+    'module' => 'Rule Scheduler',
+    'base' => 'rules_scheduler_action_delete',
+    'arguments' => array(
+      'task_identifier' => array(
+        'type' => 'string',
+        'label' => t('Identifier'),
+        'description' => t('All tasks that are annotated with this user provided identifier will be deleted.'),
+      ),
+      'ruleset' => array(
+        'type' => 'string',
+        'label' => t('Rule set'),
+        'description' => t('All tasks that execute this rule set will be deleted.'),
+      ),
+    ),
+  );
   return $items;
 }
 
@@ -39,9 +65,11 @@ function rules_scheduler_action() {
   $element  = array_pop($args);
   $settings = array_pop($args);
 
+  $task_id = array_shift($args);
   $date = array_shift($args);
+  
+  array_shift($element['#info']['arguments']);
   array_shift($element['#info']['arguments']);
-
   $pack = rules_pack_variables($element['#info']['arguments'], $args);
 
   if ($pack === FALSE) {
@@ -52,6 +80,7 @@ function rules_scheduler_action() {
         'date' => $date,
         'set_name' => $element['#info']['set'],
         'arguments' => $pack,
+        'identifier' => $task_id,
       ));
   }
 }
@@ -63,3 +92,53 @@ function rules_scheduler_action_help() {
   return t("The evaluation of the rule set is going to be scheduled by cron. So make sure you have configured cron correctly by checking your site's !status.", array('!status' => l('Status report', 'admin/reports/status'))) .' '. t('Also note that the scheduling time accuracy depends on your configured cron interval.');
 }
 
+/**
+ * Action implementation for deleting already scheduled tasks.
+ */
+function rules_scheduler_action_delete($task_identifier = NULL, $rule_set_name = NULL) {
+  if (!empty($rule_set_name)) {
+    if (!empty($task_identifier)) {
+      db_query("DELETE FROM {rules_scheduler} WHERE set_name = '%s' AND identifier = '%s'", $rule_set_name, $task_identifier);
+    }
+    else {
+      db_query("DELETE FROM {rules_scheduler} WHERE set_name = '%s'", $rule_set_name);
+    }
+  }
+  else {
+    if (!empty($task_identifier)) {
+      db_query("DELETE FROM {rules_scheduler} WHERE identifier = '%s'", $task_identifier);
+    }
+  }
+}
+
+/**
+ * Help for the delete action.
+ */
+function rules_scheduler_action_delete_help() {
+  return t('This action allows you to cancel scheduled tasks that are waiting for future execution.') .' '. t('They can be addressed by an identifier or by the rule set name, if both are specified only tasks fulfilling both requirements will be deleted.');
+}
+
+/**
+ * Changes the style of the action form, rule sets have to be selected from a select box.
+ */
+function rules_scheduler_action_delete_form($settings, &$form) {
+  $form['settings']['ruleset']['#type'] = 'select';
+  $rule_sets = array('' => '');
+  foreach (rules_get_configured_items('rule_sets') as $name => $set_info) {
+    $rule_sets[$name] = $set_info['label'] .' ('. $name .')';
+  }
+  $form['settings']['ruleset']['#options'] = $rule_sets;
+  $form['settings']['ruleset']['#multiple'] = FALSE;
+  $form['settings']['ruleset']['#required'] = FALSE;
+  
+  $form['settings']['task_identifier']['#required'] = FALSE;
+}
+
+/**
+ * Validates the parameters of the delete action, at least one must be specified.
+ */
+function rules_scheduler_action_delete_validate($form, $form_state) {
+  if ($form_state['values']['settings']['task_identifier'] == "" && empty($form_state['values']['settings']['ruleset'])) {
+    form_set_error('settings', t('You have specify at least one field.'));
+  }
+}
\ No newline at end of file
Index: rules_scheduler/rules_scheduler.views.inc
===================================================================
RCS file: rules_scheduler/rules_scheduler.views.inc
diff -N rules_scheduler/rules_scheduler.views.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rules_scheduler/rules_scheduler.views.inc	5 Jul 2009 21:10:46 -0000
@@ -0,0 +1,24 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Views integration for the rules scheduler module.
+ */
+
+/**
+ * Implementation of hook_views_handlers().
+ */
+function rules_scheduler_views_handlers() {
+  return array(
+    'info' => array(
+      'path' => drupal_get_path('module', 'rules_scheduler'),
+    ),
+    // A handler for datetime
+    'handlers' => array(
+      'rules_scheduler_datetime' => array(
+        'parent' => 'views_handler_field_date',
+        ),
+      ),
+    );
+}
\ No newline at end of file
Index: rules_scheduler/rules_scheduler.views_default.inc
===================================================================
RCS file: rules_scheduler/rules_scheduler.views_default.inc
diff -N rules_scheduler/rules_scheduler.views_default.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rules_scheduler/rules_scheduler.views_default.inc	5 Jul 2009 21:10:46 -0000
@@ -0,0 +1,201 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Views integration for the rules scheduler module.
+ */
+
+/**
+ * Implementation of hook_views_default_views().
+ */
+function rules_scheduler_views_default_views() {
+  $view = new view;
+  $view->name = 'rules_scheduler';
+  $view->description = 'Rules scheduler view';
+  $view->tag = '';
+  $view->view_php = '';
+  $view->base_table = 'rules_scheduler';
+  $view->is_cacheable = FALSE;
+  $view->api_version = 2;
+  $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+  $handler = $view->new_display('default', 'Defaults', 'default');
+  $handler->override_option('fields', array(
+    'tid' => array(
+      'label' => 'Task ID',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'exclude' => 0,
+      'id' => 'tid',
+      'table' => 'rules_scheduler',
+      'field' => 'tid',
+      'relationship' => 'none',
+    ),
+    'set_name' => array(
+      'label' => 'Rule set name',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'exclude' => 0,
+      'id' => 'set_name',
+      'table' => 'rules_scheduler',
+      'field' => 'set_name',
+      'relationship' => 'none',
+    ),
+    'date' => array(
+      'label' => 'Scheduled date',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'date_format' => 'custom',
+      'custom_date_format' => 'Y-m-d H:i:s',
+      'exclude' => 0,
+      'id' => 'date',
+      'table' => 'rules_scheduler',
+      'field' => 'date',
+      'relationship' => 'none',
+    ),
+    'identifier' => array(
+      'label' => 'User provided identifier',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'exclude' => 0,
+      'id' => 'identifier',
+      'table' => 'rules_scheduler',
+      'field' => 'identifier',
+      'relationship' => 'none',
+    ),
+    'nothing' => array(
+      'label' => 'Operations',
+      'alter' => array(
+        'text' => 'delete',
+        'make_link' => 1,
+        'path' => 'admin/rules/rule_sets/scheduling/[tid]/delete',
+        'link_class' => '',
+        'alt' => 'Delete this scheduled task',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'exclude' => 0,
+      'id' => 'nothing',
+      'table' => 'views',
+      'field' => 'nothing',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('sorts', array(
+    'date' => array(
+      'order' => 'ASC',
+      'id' => 'date',
+      'table' => 'rules_scheduler',
+      'field' => 'date',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('access', array(
+    'type' => 'perm',
+    'perm' => 'administer rules',
+  ));
+  $handler->override_option('cache', array(
+    'type' => 'none',
+  ));
+  $handler->override_option('empty', 'No tasks scheduled.');
+  $handler->override_option('empty_format', '1');
+  $handler->override_option('items_per_page', 30);
+  $handler->override_option('style_plugin', 'table');
+  $handler->override_option('style_options', array(
+    'grouping' => '',
+    'override' => 1,
+    'sticky' => 0,
+    'order' => 'asc',
+    'columns' => array(
+      'set_name' => 'set_name',
+      'date' => 'date',
+      'tid' => 'tid',
+    ),
+    'info' => array(
+      'set_name' => array(
+        'sortable' => 1,
+        'separator' => '',
+      ),
+      'date' => array(
+        'sortable' => 1,
+        'separator' => '',
+      ),
+      'tid' => array(
+        'sortable' => 1,
+        'separator' => '',
+      ),
+    ),
+    'default' => '-1',
+  ));
+
+  $views = array();
+  $views[$view->name] = $view;
+  return $views;
+}
\ No newline at end of file
Index: rules_scheduler/rules_scheduler_datetime.inc
===================================================================
RCS file: rules_scheduler/rules_scheduler_datetime.inc
diff -N rules_scheduler/rules_scheduler_datetime.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rules_scheduler/rules_scheduler_datetime.inc	5 Jul 2009 21:10:46 -0000
@@ -0,0 +1,22 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * An extended subclass for datetime handling.
+ * We need this to correctly convert our SQL datetime field to local user date/time.
+ */
+class rules_scheduler_datetime extends views_handler_field_date {
+
+  function render($values) {
+    $value = $values->{$this->field_alias};
+    // convert to unix timestamp (int), local time
+    $value = strtotime($value);
+    // convert to GMT unix timestamp
+    $value = gmmktime(date('H', $value), date('i', $value), date('s', $value), date('n', $value), date('j', $value), date('Y', $value));
+    // overwrite date string with timestamp
+    $values->{$this->field_alias} = $value;
+    // call parent method with modified values
+    return parent::render($values);
+  }
+}
\ No newline at end of file
