I am using the date popup field in a content type. The content type represents an event that can either be a single day event or a multiple day event.

Single day events should only specify an event date with a start time and an end time. I have javascript functionality to hide the date part of the to_date from the user when they specify that the event is supposed to be a single day event. The date part of the to_date is automatically set to the value of the from_date.

The problem that I face is when there is an event on 2011-05-11 that starts at 10:00PM and runs until 1:00AM the next day. Because if the javascript functionality, the to_date is equal to the from date. This causes the date module's validation functions to call form_set_error because "The To date must be greater than the From date." This is an accurate error message as the from_date would be 2011-05-11 22:00:00 and the to_date would be 2011-05-11 02:00:00.

In an attempt to resolve the issue, I planned on adding a validation function that runs before the date module's validation functions. I added the validation function in a form_alter hook using the following code:


$form['field_event_date']['#element_validate'] = array_merge(array('_events_field_event_date_validate'), $form['field_event_date']['#element_validate']); 

This is the validation function:

function _events_field_event_date_validate($element, &$form_state){
	//if this event is a single day event
  if ($form_state['values']['field_event_is_ongoing_yn'][0]['value'] == 0){
    $eventDate = $form_state['values']['field_event_date'];
    $fromTime = strtotime($eventDate['value']);
    $toTime = strtotime($eventDate['value2']);
    if ($fromTime > $toTime){
			//add 1 day to the ending date
      $eventDate['value2'] = date('Y-m-d H:i:s', $toTime + 60 * 60 * 24);
      form_set_value($element, $eventDate, $form_state);
    }
  }
}

Unfortunately, it appears that the date_combo_validate function does not use the $form_values variable to use as the source for the date values. It appears to me that this function uses the POST values as the data source.

I consider myself an experienced drupal developer, but perhaps I am mistaken in my assumption that validation functions should be using $form_values as the data source. Is this assumption incorrect?

What can I do that will allow me to update the date part of the to_date in my validation function so that the validation functions from the date module do not continue to throw an error?

Comments

douglasmiller’s picture

Title: Unable to fix date values before they are validated by date_combo_validate » date_combo_validate incorrectly used the $form['
Category: support » bug

I'm changing this to a bug report for now because I believe that there is a problem in how the date_combo_validate function operates. According to the Form API Quickstart Guide, "the [validation] function has two args: $form and $form_state. $form is the form array of the executed form, and $form_state['values'] contains the form values which you may perform validation on."

It is my understanding that the form_set_value function alters the $form_state. The parameter specification defines the $form_state parameter as follows: "$form_state The array where the value change should be recorded."

Due to the date_combo_validate function's use of $element['#post'][$field_name] as the source of data to validate, I am unable to alter the value of the to_date part of my submitted date in any correct way. Instead, I am forced to modify the validation function's parameter specification to pass the first parameter by reference instead of by value as it is supposed to be. Then I must modify the $element['#post'] array as well as using form_set_value.

I will defer to the expertise of the module maintainers on this matter, as I am unsure if this is truly a bug or not.

Could someone please supply me with some clarity on the matter?

douglasmiller’s picture

Title: date_combo_validate incorrectly used the $form[' » date_combo_validate incorrectly uses the $form variables #post array as a data source
douglasmiller’s picture

nothing?

arski’s picture

Hey there,

I'm not the maintainer of this module, but imo this is also a bug, or at least a very severe inconsistency with Drupal Form API. I'm having an issue with this over at #1156610: Datestamp field saves year only instead of timestamp where the content type form is inside another form and hence the #post values are not directly at ['#post'][$field_name]..

I see that there is a slight difference in the field's value in the $form_state and #post.. namely in $form_state you get something like

array(1) {
  [0]=>
  array(1) {
    ["value"]=>
    string(19) "2012-05-03 00:00:00"
  }
}

while in #post you get

array(1) {
  [0]=>
  array(1) {
    ["value"]=>
    array(6) {
      ["month"]=>
      string(1) "5"
      ["second"]=>
      string(1) "0"
      ["day"]=>
      string(1) "3"
      ["year"]=>
      string(4) "2012"
      ["hour"]=>
      string(0) ""
      ["minute"]=>
      string(0) ""
    }
  }

so the fix might not be quite straightforward.. although I assume the combined value is being set in another validating function, so it should be combineable.

Unfortunately, from my experience with this module, the maintainers are either too busy, or not too concerned with minor inconsistencies, so I would expect this to get fixed anytime soon.. :(

By the way, do you mind sharing what you're doing to edit the $element['#post'] value before the date_combo_validate kicks in? That might be very helpful for my module.

Thanks!

MrMaksimize’s picture

yeah, just took me a super long time to figure out what the problem is, but this kill drupal_execute and any services development on nodes using this module. Definitely would say it's a bug.

I actually ended up doing a little hack that looks like this:

function my_module_form_alter(&$form, &$form_state, $form_id){
  if ($form_id == 'vevent_node_form'){
    if ($_POST['date_time']){ //check #post on field_date 
    $form['#after_build'][] = 'apci_public_api_services_after_build';
    }
  }
}
function my_module_after_build($form, &$form_state) {
  $form['field_date']['#post']['field_date'] = $form_state['values']['field_date'];
  return $form;
}

What i'm doing, right after the form_builder is done, I tell it to call my_module_after_build which takes the data I gave in $form_state['values'] for the date field, and modifies the #post in the form array;
hope this helps someone. It drove me crazy :)

arski’s picture

Version: 6.x-2.7 » 6.x-2.x-dev
Component: Date Popup » Date Field
Priority: Normal » Major

Hmm, how can that possibly work on first load? Because when you load a form for the first time, it doesn't have any values yet, and hence nothing will be moved to #post..

Is there any way to modify the $form after it has been submitted and before it's validated?

I wish the maintainers of the module fixed this one day :/

arski’s picture

my bad about form_build.. that does work indeed.

arski’s picture

hmm, any chance of anything happening to this? :( been marked as a "major" priority bug report for ages now..

damienmckenna’s picture

Status: Active » Closed (won't fix)

Unfortunately the Drupal 6 version of the Date module is no longer supported. That said, we appreciate that you took time to work on this issue. Should this request still be relevant for Drupal 7 please feel free to reopen it. Thank you.