? ~signup-DRUPAL-6--1.patch
Index: signup.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/signup.module,v
retrieving revision 1.205.2.36
diff -u -p -r1.205.2.36 signup.module
--- signup.module	8 Oct 2009 00:01:29 -0000	1.205.2.36
+++ signup.module	10 Oct 2009 16:21:02 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: signup.module,v 1.205.2.36 2009/10/08 00:01:29 dww Exp $
+// $Id: signup.module,v 1.205.2.34 2009/09/19 01:42:58 dww Exp $
 
 
 /**
@@ -201,6 +201,7 @@ function signup_cron() {
   module_load_include('inc', 'signup', 'includes/cron');
   _signup_initialize_scheduler_backend();
   _signup_cron_send_reminders();
+  _signup_cron_autoopen();
   _signup_cron_autoclose();
 }
 
@@ -238,6 +239,9 @@ function _signup_build_query($common_sql
   if (!empty($full_sql['group_by'])) {
     $sql .= ' GROUP BY '. implode(', ', $full_sql['group_by']);
   }
+  if (!empty($full_sql['having'])) {
+    $sql .= ' HAVING '. implode(', ', $full_sql['having']);
+  }
   return $sql;
 }
 
@@ -764,6 +768,8 @@ function signup_nodeapi(&$node, $op, $te
         $node->signup_reminder_email = $signup->reminder_email;
         $node->signup_close_signup_limit = $signup->close_signup_limit;
         $node->signup_status = $signup->status;
+        $node->signup_open_at = $signup->open_at;
+        $node->signup_close_at = $signup->close_at;
         if ($node->nid) {
           $node->signup_total = db_result(db_query("SELECT COUNT(*) FROM {signup_log} WHERE nid = %d", $node->nid));
           $node->signup_effective_total = db_result(db_query("SELECT SUM(count_towards_limit) FROM {signup_log} WHERE nid = %d", $node->nid));
Index: includes/admin.settings.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/includes/admin.settings.inc,v
retrieving revision 1.2.2.5
diff -u -p -r1.2.2.5 admin.settings.inc
--- includes/admin.settings.inc	24 Jan 2009 08:52:46 -0000	1.2.2.5
+++ includes/admin.settings.inc	10 Oct 2009 16:21:02 -0000
@@ -13,12 +13,19 @@
 function signup_settings_form() {
   module_load_include('inc', 'signup', 'includes/node_settings');
   if (signup_site_has_dates()) {
-    $form['signup_close_early'] = array(
+    $form['signup_open_before'] = array(
+      '#title' => t('Open x hours before start'),
+      '#type' => 'textfield',
+      '#default_value' => variable_get('signup_open_before', 100),
+      '#size' => 5, '#maxlength' => 10,
+      '#description' => t('The default number of hours before the event which signups will begin. Use negative numbers to open signups after the event start (example: -12).'),
+    );
+    $form['signup_close_before'] = array(
       '#title' => t('Close x hours before'),
       '#type' => 'textfield',
-      '#default_value' => variable_get('signup_close_early', 1),
+      '#default_value' => variable_get('signup_close_before', 1),
       '#size' => 5, '#maxlength' => 10,
-      '#description' => t('The number of hours before the event which signups will no longer be allowed. Use negative numbers to close signups after the event start (example: -12).'),
+      '#description' => t('The default number of hours before the event which signups will no longer be allowed. Use negative numbers to close signups after the event start (example: -12).'),
     );
   };
   $form['node_defaults'] = array(
Index: includes/cron.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/includes/cron.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 cron.inc
--- includes/cron.inc	14 Aug 2009 23:26:10 -0000	1.1.2.2
+++ includes/cron.inc	10 Oct 2009 16:21:02 -0000
@@ -79,49 +79,95 @@ function _signup_cron_send_reminders() {
 /**
  * Helper function that handles auto-closing time-based nodes during cron.
  *
- * Loops over all the node types that are signup-enabled.  For each one, it
- * invokes the method for the installed event/date backend module to get the
- * right query fragments, and builds a query to find all nodes of that type
- * where signups should be closed (e.g. events that already started, etc).
+ * Determine current time in UTC and fetch all open signup enabled nodes with a signup close time before current UTC time.
+ * Requires Date API or PHP5.2+
  *
  * @see signup_cron()
- * @see signup_autoclose_sql()
+ * @see _signup_cron_autoopen()
  * @see _signup_build_query()
  */
 function _signup_cron_autoclose() {
-  $type_autoclose_sql = array();
-  foreach (signup_content_types() as $type) {
-    $type_sql = signup_autoclose_sql($type);
-    if (!empty($type_sql)) {
-      $type_autoclose_sql[$type] = $type_sql;
-    }
+
+  // Get current time in UTC for comparison. If Date_API is unavailable, try PHP5.2 functions. Use basic date() and time() computations if both fail.
+  if (function_exists(date_make_date)) {
+    $current_time = date_format_date(date_make_date('now', 'UTC'), 'custom', DATE_FORMAT_DATETIME);
   }
-  if (empty($type_autoclose_sql)) {
-    // No node types support auto-close, so bail out now.
-    return;
+  elseif (function_exists(date_create)) {
+    $current_time = date_format(date_create('now',timezone_open('UTC')), 'Y-m-d H:i:s');
   }
-
-  $autoclose_common_sql = array(
+  else {
+    $time = time();
+    $time = $time + date('Z',$time);
+    $current_time = date('Y-m-d H:i:s',$time);
+  }
+  
+  $autoclose_sql = array(
     'primary' => '{node} n',
     'fields' => array('n.nid', 'n.type'),
-    'where' => array('s.status = 1', "n.type = '%s'"),
+    'where' => array('s.status = 1', "s.close_at <= '$current_time'", "s.close_at > '0000-00-00 00:00:00'"),
     'joins' => array('INNER JOIN {signup} s ON s.nid = n.nid'),
   );
 
-  foreach ($type_autoclose_sql as $type => $autoclose_sql) {
-    $sql = _signup_build_query($autoclose_common_sql, $autoclose_sql);
-    $result = db_query($sql, $type);
-
-    // Loop through the results, calling the signup closing function.
-    while ($signup = db_fetch_object($result)) {
-      signup_close_signup($signup->nid, $cron = 'yes');
-      $node = node_load($signup->nid);
-      foreach (module_implements('signup_close') as $module) {
-        $function = $module .'_signup_close';
-        $function($node);
-      }
-      watchdog('signup', 'Signups closed for %title by cron.', array('%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
+  $sql = _signup_build_query($autoclose_sql, array());
+  $result = db_query($sql, $type);
+
+  // Loop through the results, calling the signup closing function.
+  while ($signup = db_fetch_object($result)) {
+    signup_close_signup($signup->nid, $cron = 'yes');
+    $node = node_load($nid);
+    foreach (module_implements('signup_close') as $module) {
+      $function = $module .'_signup_close';
+      $function($node);
     }
+    watchdog('signup', 'Signups closed for %title by cron.', array('%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
   }
 }
 
+/**
+ * Helper function that handles auto-opening time-based nodes during cron.
+ *
+ * Determine current time in UTC and fetch all closed signup enabled nodes with a signup open time before current UTC time.
+ * Requires Date API or PHP5.2+
+ *
+ * @see signup_cron()
+ * @see _signup_cron_autoclose()
+ * @see _signup_build_query()
+ */
+function _signup_cron_autoopen() {
+
+  // Get current time in UTC for comparison. If Date_API is unavailable, try PHP5.2 functions. Use basic date() and time() computations if both fail.
+  if (function_exists(date_make_date)) {
+    $current_time = date_format(date_make_date('now', 'UTC'),DATE_FORMAT_DATETIME);
+  }
+  elseif (function_exists(date_create)) {
+    $current_time = date_format(date_create('now',timezone_open('UTC')),'Y-m-d H:i:s');
+  }
+  else {
+    $time = time();
+    $time = $time + date('Z',$time);
+    $current_time = date('Y-m-d H:i:s',$time);
+  }
+  
+  $autoopen_sql = array(
+    'primary' => '{node} n',
+    'fields' => array('n.nid', 'n.type'),
+    'where' => array('s.status = 0', "s.open_at <= '$current_time'", "s.close_at > '$current_time'", "s.open_at > '0000-00-00 00:00:00'", "s.close_at > '0000-00-00 00:00:00'"),
+    'having' => array('(SUM(l.count_towards_limit) < s.close_signup_limit OR SUM(l.count_towards_limit) IS NULL)'),
+    'joins' => array('INNER JOIN {signup} s ON s.nid = n.nid','LEFT JOIN {signup_log} l ON l.nid = s.nid'),
+    'group_by' => array('s.close_signup_limit'),
+  );
+
+  $sql = _signup_build_query($autoopen_sql, array());
+  $result = db_query($sql, $type);
+
+  // Loop through the results, calling the signup closing function.
+  while ($signup = db_fetch_object($result)) {
+    signup_open_signup($signup->nid, $cron = 'yes');
+    $node = node_load($nid);
+    foreach (module_implements('signup_open') as $module) {
+      $function = $module .'_signup_open';
+      $function($node);
+    }
+    watchdog('signup', 'Signups opened for %title by cron.', array('%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
+  }
+}
Index: includes/date.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/includes/date.inc,v
retrieving revision 1.16.2.4
diff -u -p -r1.16.2.4 date.inc
--- includes/date.inc	4 Mar 2009 19:19:34 -0000	1.16.2.4
+++ includes/date.inc	10 Oct 2009 16:21:02 -0000
@@ -549,3 +549,38 @@ function _signup_date_format_date($node,
   return $date_out;
 }
 
+/**
+ * Collect the start time of the event
+ *
+ * A similar function for event.module based nodes will be required.
+ * A parameter should be added to allow returned time for different timezones.
+ *
+ * @param $node
+ *   The node to return the start time for
+ * @return $date
+ *   The start time for the signup enabled event. Returns as UTC time.
+ */
+ 
+function _signup_date_node_start_at(&$node) {
+  // Get the date field information for this content type.
+  $field = signup_date_field($node->type);
+  
+  // Grab whatever date value we actually have, regardless of format.
+  $date_value = $node->{$field['field_name']}[0]['value'];
+  // Figure out the timezone handling for this date.
+  if ($field['tz_handling'] == 'date') {
+    $tz = $node->{$field['field_name']}[0]['timezone'];
+  }
+  else {
+    $tz = date_default_timezone_name();
+  }
+  $db_tz = date_get_timezone_db($field['tz_handling'], $tz);
+  // Create a date object
+  $date = date_make_date($date_value, $db_tz, $field['type']);
+  // Make sure the date object is going to print UTC values.
+  date_timezone_set($date, timezone_open('UTC'));
+  
+  date_format_date($date, 'custom', DATE_DATETIME);
+  
+  return $date;
+}
Index: includes/node_form.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/includes/node_form.inc,v
retrieving revision 1.4.2.2
diff -u -p -r1.4.2.2 node_form.inc
--- includes/node_form.inc	16 Sep 2009 00:42:57 -0000	1.4.2.2
+++ includes/node_form.inc	10 Oct 2009 16:21:02 -0000
@@ -63,14 +63,27 @@ function signup_save_node($node, $op) {
       $needs_defaults = empty($has_record);
     }
   }
+  //Needs the time information from the full node, so loading of the full node is now done before loading of defaults.
+  $node = node_load($node->nid); 
   
   if ($needs_defaults) {
     $values = db_fetch_array(db_query("SELECT forwarding_email, send_confirmation, confirmation_email, close_signup_limit, send_reminder, reminder_days_before, reminder_email FROM {signup} WHERE nid = 0"));
+    
+    // Get the date field information for this content type.
+    $field = signup_date_field($node->type);
+    
+    //Calculate open and close time for signups.
+    $open_at = signup_node_start_at($node);
+    $close_at = signup_node_start_at($node);
+    date_modify($open_at, '-'.variable_get('signup_open_before',100).'hours');
+    date_modify($close_at, '-'.variable_get('signup_close_before', 1).'hours');
+    $values['open_at'] = date_format_date($open_at, 'custom', DATE_FORMAT_DATETIME);
+    $values['close_at'] = date_format_date($close_at, 'custom', DATE_FORMAT_DATETIME);
     $values[] = $node->nid;
-    db_query("INSERT INTO {signup} (forwarding_email, send_confirmation, confirmation_email, close_signup_limit, send_reminder, reminder_days_before, reminder_email, nid) VALUES ('%s', %d, '%s', %d, %d, %d, '%s', %d)", $values);
+    
+    db_query("INSERT INTO {signup} (forwarding_email, send_confirmation, confirmation_email, close_signup_limit, send_reminder, reminder_days_before, reminder_email, open_at, close_at, nid) VALUES ('%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', %d)", $values);
   }
 
-  $node = node_load($node->nid);
   if (_signup_node_completed($node) && !empty($node->signup_status)) {
     // If this is an time-based node, and it's already past the close in
     // advance time (e.g. someone just changed the node start time), and
Index: includes/node_settings.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/includes/node_settings.inc,v
retrieving revision 1.1.2.4
diff -u -p -r1.1.2.4 node_settings.inc
--- includes/node_settings.inc	21 Sep 2009 05:23:09 -0000	1.1.2.4
+++ includes/node_settings.inc	10 Oct 2009 16:21:02 -0000
@@ -73,6 +73,48 @@ function signup_node_settings_form($form
   }
 
   if ($has_date) {
+    if ($node->nid) {
+      // Use Drupal's date element to get a basic input for open and close times.
+      $open_date = explode('-',$node->singup_open_at);
+      $close_date = explode('-',$node->singup_close_at);
+      $form['signup_open_at'] = array(
+        '#type' => 'date',
+        '#title' => t('Time to open signup'),
+        '#default_value' => array('year'=>$open_date[0],'month'=>$open_date[1],'day'=>$open_date[2]),
+        '#description' => t('The time on which singups should be opened for this node.'),
+      );
+      $form['signup_close_at'] = array(
+        '#type' => 'date',
+        '#title' => t('Time to close signup'),
+        '#default_value' => array('year'=>$close_date[0],'month'=>$close_date[1],'day'=>$close_date[2]),
+        '#description' => t('The time on which signups should be closed for this node.'),
+      );
+      
+      if (module_exists('date_api')) {
+        // Compute the times in user or site timezone
+        $timezone = date_default_timezone_name();
+        $open_at = date_make_date($node->signup_open_at, 'UTC');
+        $close_at = date_make_date($node->signup_close_at, 'UTC');
+        date_timezone_set($open_at, timezone_open($timezone));
+        date_timezone_set($close_at, timezone_open($timezone));
+        
+        //Modify the form elements to utilize the Date API.
+        $form['signup_open_at']['#type'] = 'date_select';
+        $form['signup_open_at']['#default_value'] = date_format_date($open_at,'custom',DATE_FORMAT_DATETIME);
+        $form['signup_open_at']['#date_format'] = DATE_FORMAT_DATETIME;
+        $form['signup_open_at']['#timezone'] = $timezone;
+        $form['signup_close_at']['#type'] = 'date_select';
+        $form['signup_close_at']['#default_value'] = date_format_date($close_at,'custom',DATE_FORMAT_DATETIME);
+        $form['signup_close_at']['#date_format'] = DATE_FORMAT_DATETIME;
+        $form['signup_close_at']['#timezone'] = $timezone;
+      }
+      
+      // If the date_popup module is enabled we want to use the popup element
+      if (module_exists('date_popup')) {
+        $form['signup_open_at']['#type'] = 'date_popup';
+        $form['signup_close_at']['#type'] = 'date_popup';
+      }
+    }
     // Define a sub-tree to wrap the next 2 form elements together in an
     // inline div for better display.
     $form['signup_reminder'] = array(
@@ -169,13 +211,34 @@ function signup_node_settings_form_submi
     $values['send_reminder'] = isset($form_state['values']['signup_send_reminder']) ? $form_state['values']['signup_send_reminder'] : 0;
     $values['reminder_days_before'] = isset($form_state['values']['signup_reminder_days_before']) ? $form_state['values']['signup_reminder_days_before'] : 0;
     $values['reminder_email'] = isset($form_state['values']['signup_reminder_email']) ? $form_state['values']['signup_reminder_email'] : '';
+    
+    if (isset($form_state['values']['signup_open_at']) && isset($form['signup_open_at']['#date_timezone'])) {
+      if ($form['signup_open_at']['#type'] == 'date_select' || $form['signup_open_at']['#type'] == 'date_popup') {
+        $open_at = date_make_date($form_state['values']['signup_open_at'], $form['signup_open_at']['#date_timezone']);
+        date_timezone_set($open_at, timezone_open('UTC'));
+        $values['signup_open_at'] = date_format_date($open_at, 'custom', DATE_FORMAT_DATETIME);
+      }
+      elseif ($form['signup_open_at']['#type'] == 'date') {
+        $values['signup_open_at'] = $form_state['values']['signup_open_at']['year'].'-'.$form_state['values']['signup_open_at']['month'].'-'.$form_state['values']['signup_open_at']['day'];
+      }
+    }
+    if (isset($form_state['values']['signup_close_at']) && isset($form['signup_close_at']['#date_timezone'])) {
+      if ($form['signup_close_at']['#type'] == 'date_select' || $form['signup_close_at']['#type'] == 'date_popup') {
+        $close_at = date_make_date($form_state['values']['signup_close_at'], $form['signup_close_at']['#date_timezone']);
+        date_timezone_set($close_at, timezone_open('UTC'));
+        $values['signup_close_at'] = date_format_date($close_at, 'custom', DATE_FORMAT_DATETIME);
+      }
+      elseif ($form['signup_close_at']['#type'] == 'date') {
+        $values['signup_close_at'] = $form_state['values']['signup_close_at']['year'].'-'.$form_state['values']['signup_close_at']['month'].'-'.$form_state['values']['signup_close_at']['day'];
+      }
+    }
   }
 
   // Either way, we want to make sure we're updating the values for the
   // current node, not nid 0...
   $node = $form['#node'];
   $values[] = $node->nid;
-  db_query("UPDATE {signup} SET forwarding_email = '%s', send_confirmation = %d, confirmation_email = '%s', close_signup_limit = %d, send_reminder = %d, reminder_days_before = %d, reminder_email = '%s' WHERE nid = %d", $values);
+  db_query("UPDATE {signup} SET forwarding_email = '%s', send_confirmation = %d, confirmation_email = '%s', close_signup_limit = %d, send_reminder = %d, reminder_days_before = %d, reminder_email = '%s', open_at = '%s', close_at = '%s' WHERE nid = %d", $values);
 
   // See if the limit changed, and if so, take any necessary action.
   if ($node->signup_close_signup_limit != $form_state['values']['signup_close_signup_limit']) {
Index: includes/scheduler.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup/includes/scheduler.inc,v
retrieving revision 1.4
diff -u -p -r1.4 scheduler.inc
--- includes/scheduler.inc	6 Nov 2008 10:20:48 -0000	1.4
+++ includes/scheduler.inc	10 Oct 2009 16:21:02 -0000
@@ -124,29 +124,35 @@ function signup_reminder_sql($node_type)
   }
 }
 
-function signup_autoclose_sql($node_type) {
+function signup_admin_sql($node_type) {
   switch (_signup_get_node_type_scheduler($node_type)) {
     case 'event':
-      return _signup_event_autoclose_sql($node_type);
+      return _signup_event_admin_sql($node_type);
 
     case 'date':
-      return _signup_date_autoclose_sql($node_type);
+      return _signup_date_admin_sql($node_type);
 
     default:
       return array();
   }
 }
 
-function signup_admin_sql($node_type) {
-  switch (_signup_get_node_type_scheduler($node_type)) {
+/**
+ * Get the start time for the node.
+ */
+function signup_node_start_at(&$node) {
+  if (is_numeric($node)) {
+    $node = node_load($node);
+  }
+  switch (_signup_get_node_scheduler($node)) {
     case 'event':
-      return _signup_event_admin_sql($node_type);
+      //Function not yet present, must be written to autoopen/close signups with event.
+      //return _signup_event_node_start_at($node);
 
     case 'date':
-      return _signup_date_admin_sql($node_type);
+      return _signup_date_node_start_at($node);
 
     default:
-      return array();
+      return FALSE;
   }
 }
-
