I've been trying to post a form programmatically but find that the Date module (ab)uses the form api.
I have a node form with a date popup field. It expects the element #value structure array('date' => .., 'time' => ...) while the #default_value is simply a string, such as '2012-02-01 00:00:00'. If you try to set the #value to the #default_value (which should work as the default_value should be compatible to value) and post the form programmatically you get the error 'field_nieuws_datum][und][0][value The value input for field Datum is invalid.' or something like it.
This is due tue the fact that Date uses the process hook to change the form element structure of the #value during the processing phase. When you request a form from a url, this means that the rendered form is shown with the default_value translated to the correct structure. Then, when you post it, the $_POST array has the values in the correct structure, $form_state['values'] is accepted by date_popup_validate (which checks for form_state['values']) and the form is submitted correctly.
But when you post a form programatically, this two-staged trick doesn't work. There is no rendering before posting, all needs to be done in one go. So this process-hook trick may seem to work, but it is faulty as it breaks the requirement that the #default_value is compatible with the #value.
Also, the date module does expect to find the form_state values of its fields, and does not take into account that in a programmatic form submission these may not be set (in which case the current value should be left alone).
Imo, some other approach should be used.
Comments
Comment #1
mgiffordAny thoughts on which other approaches should be considered?
Comment #2
bvanmeurs commentedmgifford, I found a solution by first calling drupal_get_form, and then doing a form submit directly. This way the two-staged approached works with the date module. So, even if this is an issue, there is a good work-around.
The solution to this problem is to use a standard value format for all phases in the form creation/manipulation. But this requires quite a rewrite..
Comment #3
mgiffordThanks @bvanmeurs - How do we make this an issue for the next time a rewrite is being considered for the Date module?
Comment #4
bvanmeurs commentedMaybe change the validation function such that if it is in the '2012-02-02 10:00:00' format, to change it automatically into the array(date, time) according to the date field settings. This shouldn't be too rigorous a change, but the downside to this approach is that it may lead to some code quality degration.
Comment #5
karens commentedI am not too interested in adding more complexity to this module to allow for programmatic submissions that don't match the expected values. I already had to do a bunch of cartwheels to allow for all the crazy stuff that happens in Views and with Views exposed filters and I'm trying to simplify the code so we can move it into core in D8.
You really need to pass in the expected values in your code and it sounds like if you do that it works.
Comment #6
MD3 commentedFor anyone still confused as to what format Date is expecting, I found this blog post by fooninja very helpful.
Also, if you're using entities be sure and use the ->save() method instead of going through a form.