Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
forms system
Priority:
Normal
Category:
Bug report
Assigned:
Issue tags:
Reporter:
Created:
25 Nov 2009 at 16:46 UTC
Updated:
3 Jan 2014 at 00:29 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
sunAdditionally, to continue that example:
In case the validation fails, a validation handler needs to be able to reset the element's #value to an empty string. In this example, if the submitted CAPTCHA value was incorrect, the user has to input a new CAPTCHA anyway, so the validation handler needs to alter the element in the form structure, not just $form_state['values'].
Clarification on the last bit: $form_state['values'] can be altered via http://api.drupal.org/api/function/form_set_value/7, but doing so has no effect on the actual form element that will be rendered.
Comment #2
dries commentedI agree that this is much needed. It has been painful having to work around this. I think it could be useful to document this change though (if only to make sure we don't revert it) and/or to write a small test for it. Otherwise looks RTBC.
Comment #3
sunAdded tests. Looks ready to fly for me.
Comment #4
sunWe can go one step further and even test a validation handler that sets #access => FALSE on an element and the value should persist throughout subsequent validations + rebuilds.
This is currently not the case. Interestingly, this brings me back to #622922: User input keeping during multistep forms and seems to be a pretty simple test-case for it.
Comment #5
dries commented'alteration' is a fun word, a bit archaic even. It's correct though so no need to change this.
I think this is RTBC.
Comment #6
webchickI agree this would be convenient. Only thing is I'm pretty sure this was done as a deliberate decision so that validation was just for validating, since we used to be able to do changes to forms in #validate back in 4.7/5-ish.
It'd be nice to have chx or Eaton chime in here.
Comment #7
sunReally? I just checked in D5 as well as 4.7.6 and it wasn't possible in there.
If it was possible earlier, I guess that it was either mistakenly removed, or it was perhaps removed because people mistakenly thought they would be able to alter the submitted form values by altering $element['#value'], i.e. not realizing that any alterations to the form structure will of course only have an effect on the form in case of a validation error, in which case the form will be automatically rebuilt.
Are you sure you don't mean form_set_value(), which allows to alter the $form_state['values'], as mentioned in #1 already?
Comment #8
effulgentsia commentedIf it was an intentional decision to not pass $form by reference, I suspect it was because if a validation function makes a change to $form and there are validation errors, then the changed $form isn't cached, so when the user re-submits it, the input would be processed against a stale cached form build. If this change goes in, we would need to change the caching logic in drupal_build_form(). I suspect the intended way to accomplish the use-case described in this issue is to use $form_state['rebuild']. However, there are currently some major problems with form rebuilding. One of them is being worked on in #622922: User input keeping during multistep forms. But another one is that drupal_build_form() only calls drupal_rebuild_form() if there were no validation errors, which seems to cancel out any possibility for a validation function to trigger a rebuild. However, image_style_form_add_validate() and book_admin_edit_validate() attempt (unsuccessfully because of previous sentence) to trigger a rebuild from a validation error. So, basically, WTFs all over the place.
Seems like we need help from chx, Eaton, or another FAPI guru to explain exactly what form rebuilding was intended for, and if we need to fix it to work from validation handlers as well as submit handlers, and if not, then how else can the CAPTCHA use-case in this issue be solved.
Comment #9
sunTrying to trigger a rebuild via $form_state['rebuild'] is an entirely different issue. On that note, setting $form_state['rebuild'] AND setting a form validation error is senseless, because form errors overrule any rebuilding - the form is straight output with the same populated values again.
With regard to this - and that's what this patch is doing - form validation handlers need to be treated like #process handlers. They are the last instance in the form processing flow, and they need to be able to still alter the form elements.
However, as with everything else in form_builder() and drupal_process_form(), all of these handlers always run from scratch again, also for cached forms. Which means: A #process or #element_validate or #validate handler, which performs alterations to a form, has to execute its own conditional tasks each time.
Only the original $form, as returned by the form constructor function, plus any alterations by hook_form_alter() implementations, are cached.
Comment #10
effulgentsia commentedWorks for me. Thanks for the explanation. I'll keep that in mind when working on the rebuild issues.
Comment #11
sunOn a related note, comment_form() is entirely incompatible with form caching.
Why? As mentioned before: When caching is enabled, the constructed $form plus any alterations are cached and NOT rebuilt. When caching is enabled, comment_form() never has a "Submit" button.
Tagging.
Comment #12
chx commentedI am not changing the status but I am mailing Heine and want to talk to him before let this through.
Comment #13
chx commentedSuppose you change the form. if you do not change the form_state['values'] then you might get unvalidated form_state['values'] to the form submit.
However, this is not new. after_build already let's you do that. So I am blessing this if you add a warning to drupal_validate_form warning not to do that. (Optionally you can commit such a warning to the fapi docs in contrib for after_build too).
Edit: i did not need to send the mail to Heine because as I was trying to explain what caused me such unease I finally realized it and this was it.
Comment #14
sun@chx: Does the added PHPDoc meet your approval?
Comment #17
dries commentedFound a small typo:
"an validation error" should be "a validation error". I can fix that when I commit the patch though.
Comment #18
sunFixed that typo.
Comment #19
chx commentedI believe we are good to go.
Comment #20
dries commentedCommitted to CVS HEAD. Thanks sun and chx.