? 641850_date_repeat_12.patch
Index: resource_conflict.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/resource_conflict/resource_conflict.module,v
retrieving revision 1.8
diff -u -p -r1.8 resource_conflict.module
--- resource_conflict.module	30 May 2010 21:22:25 -0000	1.8
+++ resource_conflict.module	8 Jun 2010 22:25:49 -0000
@@ -29,6 +29,14 @@ function resource_conflict_nodeapi(&$nod
         // Get all conflicting Date nodes
         if (!empty($start) && !empty($end)) {
           $overlapping_node_ids = _resource_conflict_overlaps_from_date($start, $end);
+          $time_spans_raw = array();
+          foreach ($node->{$date_field} as $single_repetition_date) {
+            $time_spans_raw[] = array(
+              'start' => $single_repetition_date['value'],
+              'end' => $single_repetition_date['value2'],
+            );
+          }
+          $overlapping_node_ids = _resource_conflict_overlaps_from_date($time_spans_raw);
         }
         else {
           // If we got here, someone broke the requirements, so turn off
@@ -84,7 +92,7 @@ function _resource_conflict_display_conf
       if (strpos($date_field, 'field_', 0) === 0) {
         $type = DATE_ISO;
         // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
-        if (!date_is_valid($date_start,DATE_ISO)) {
+        if (! _resource_conflict_date_is_valid($date_start,DATE_ISO)) {
           $type = DATE_DATETIME;
         }
 
@@ -324,24 +332,28 @@ function _resource_conflict_get_node_res
 /**
  * Determine if any nodes conflict between the specified dates using Date API.
  *
- * @param $date_start
- *   The start date of the date to check
- * @param $date_end
- *   The end date of the date to check.
+ * @param $time_spans_input
+ *   An array of 'time span' arrays.
+ *   Each 'time span' array has a 'start' and an 'end' key and ISO timestamps as values.
  * @return
  *   An array of node ID's
  */
-function _resource_conflict_overlaps_from_date($date_start, $date_end) {
-  // Make the default type to DATE_ISO.
-  $type = DATE_ISO;
-  // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
-  if (!date_is_valid($date_start,DATE_ISO)) {
-    $type = DATE_DATETIME;
-  }
+function _resource_conflict_overlaps_from_date($time_spans_input) {
+  $time_spans = array();
+  foreach ($time_spans_input as $single_time_span_input) {
+    // Make the default type to DATE_ISO.
+    $type = DATE_ISO;
+    // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
+    if (!_resource_conflict_date_is_valid($single_time_span_input['start'],DATE_ISO)) {
+      $type = DATE_DATETIME;
+    }
 
-  $start = date_make_date($date_start, 'GMT', $type);
-  $end = date_make_date($date_end, 'GMT', $type);
-  return _resource_conflict_get_overlaps($start, $end);
+    $time_spans[] = array(
+      'start' => date_make_date($single_time_span_input['start'], 'GMT', $type),
+      'end' => date_make_date($single_time_span_input['end'], 'GMT', $type),
+    );
+  }
+  return _resource_conflict_get_overlaps($time_spans);
 }
 
 /**
@@ -357,7 +369,7 @@ function _resource_conflict_overlaps_fro
 function _resource_conflict_overlaps_from_event($event_start, $event_end) {
   $start = date_make_date($event_start, 'GMT', DATE_UNIX);
   $end = date_make_date($event_end, 'GMT', DATE_UNIX);
-  return _resource_conflict_get_overlaps($start, $end);
+  return _resource_conflict_get_overlaps(array(array('start' => $start, 'end' => $end)));
 }
 
 /**
@@ -368,18 +380,13 @@ function _resource_conflict_overlaps_fro
  * 3. The event encompasses $start and $end
  * 4. Allow the end of one event to occur at the start of the next
  * 
- * @param $start
- *   The start time of events to search as dateAPI object
- * @param $end
- *   The end time of events to search as dateAPI object
+ * @param $time_spans
+ *   An array of 'time span' arrays.
+ *   Each 'time span' array has a 'start' and an 'end' key and dateAPI objects as values.
  * @return
  *   An array of node ID's
  */
-function _resource_conflict_get_overlaps($start, $end) {
-  $date_start = date_convert($start, DATE_OBJECT, DATE_ISO);
-  $date_end = date_convert($end, DATE_OBJECT, DATE_ISO);
-  $event_start = date_convert($start, DATE_OBJECT, DATE_UNIX);
-  $event_end = date_convert($end, DATE_OBJECT, DATE_UNIX);
+function _resource_conflict_get_overlaps($time_spans) {
 
   $rows = array();
   $conflict_types = _resource_conflict_get_conflict_enabled_types();
@@ -394,12 +401,33 @@ function _resource_conflict_get_overlaps
       $start_field_name = $date_db_info['columns']['value']['column'];
       $end_field_name = $date_db_info['columns']['value2']['column'];
 
+      $start_field_type = DATE_ISO;
+      if ($date_db_info['columns']['value']['type'] == 'datetime') $start_field_type = DATE_DATETIME;
+
+      $where_or = array();
+      $query_args = array();
+      foreach ($time_spans as $time_span) {
+        $date_start = date_convert($time_span['start'], DATE_OBJECT, $start_field_type);
+        $date_end = date_convert($time_span['end'], DATE_OBJECT, $start_field_type);
+
+        $where_or[] = "('%s' >= date_table.$start_field_name AND '%s' < date_table.$end_field_name)";
+        $query_args[] = $date_start;
+        $query_args[] = $date_start;
+
+        $where_or[] = "('%s' > date_table.$start_field_name AND '%s' <= date_table.$end_field_name)";
+        $query_args[] = $date_end;
+        $query_args[] = $date_end;
+
+        $where_or[] = "('%s' <= date_table.$start_field_name AND '%s' >= date_table.$end_field_name)";
+        $query_args[] = $date_start;
+        $query_args[] = $date_end;
+      }
+
       $query = "SELECT DISTINCT {node}.nid FROM {node} INNER JOIN $date_table date_table ON {node}.vid = date_table.vid
-        WHERE('%s' >= date_table.$start_field_name AND '%s' < date_table.$end_field_name)
-        OR('%s' > date_table.$start_field_name AND '%s' <= date_table.$end_field_name)
-        OR('%s' <= date_table.$start_field_name AND '%s' >= date_table.$end_field_name)";
+        WHERE " . implode(' OR ', $where_or);
+      $query .= " ORDER BY date_table.$start_field_name";
 
-      $result = db_query($query, $date_start, $date_start, $date_end, $date_end, $date_start, $date_end);
+      $result = db_query($query, $query_args);
 
       // Create an array of all of the results
       while ($row = db_fetch_array($result)) {
@@ -407,6 +435,8 @@ function _resource_conflict_get_overlaps
       }
     }
     elseif ($date_field == 'event') { //event enabled
+      $event_start = date_convert($time_spans[0]['start'], DATE_OBJECT, DATE_UNIX);
+      $event_end = date_convert($time_spans[0]['end'], DATE_OBJECT, DATE_UNIX);
       $query = "SELECT DISTINCT nid FROM {event} WHERE (%d >= event_start AND %d < event_end)
         OR (%d > event_start AND %d <= event_end)
         OR (%d <= event_start AND %d >= event_end)";
@@ -464,3 +494,22 @@ if (!function_exists('date_show_value'))
   }
 }
 
+/**
+  * This function exists to work around a bug in date_is_valid as described in
+  * http://drupal.org/node/792012
+  *
+  *   The date_is_valid tests the validity of a date in various formats.
+  *  Has special case for ISO dates and arrays which can be missing
+  *  month and day and still be valid.
+  *
+  *  @param $type
+  *    could be DATE_ARRAY, DATE_UNIX, DATE_DATETIME, DATE_ISO, or DATE_OBJECT
+  *  @param $granularity
+  *    The granularity of the date value provided. Set this for partial
+  *    dates so they pass validation.
+  */
+function _resource_conflict_date_is_valid($date, $type = DATE_DATETIME, $granularity = array('year', 'month', 'day', 'hour', 'minute')) {
+  if ($type == DATE_ISO && (!is_string($date) || !preg_match(DATE_REGEX_ISO, $date))) return FALSE;
+  if ($type == DATE_DATETIME && (!is_string($date) || !preg_match(DATE_REGEX_DATETIME, $date))) return FALSE;
+  return date_is_valid($date, $type, $granularity);
+}
