When a form is initially built and $form_state['cache'] is TRUE, the $form structure as well as (certain properties of) $form_state is cached.
Form #process handlers and #validate handlers are then supposed to use $form_state - as the name implies - as state machine for subsequent rebuilds of the form.
They are also supposed to use $form_state['storage'] to store stateful data.
However, after regular form processing, $form_state is never written back to the cache.
The cached $form and $form_state is only ever updated when drupal_rebuild_form() is invoked. That, however, is purposively not invoked in case of a validation error.
Comment | File | Size | Author |
---|---|---|---|
#16 | drupal.form-state-cache.14.patch | 2.54 KB | sun |
#15 | form-state-cache.patch | 3.62 KB | fago |
#14 | drupal.form-state-cache.14.patch | 2.54 KB | sun |
#12 | drupal.form-state-cache.12.patch | 2.83 KB | sun |
#8 | drupal.form-state-cache.8.patch | 11.38 KB | sun |
Comments
Comment #2
sun.
Comment #3
sunComment #4
Dries CreditAttribution: Dries commentedLooks correct. Committed to CVS HEAD. Setting to 'needs work' because this could use a test.
Comment #5
sunBoy.
Somehow, I really doubt that anyone ever really used anything related to form storage and form caching in real applications. Even totally simple assertions fail -- like: verifying that form_build_id stays the same in multi-step scenarios?!?
I can't believe this.
Attached patch
- fixes aforementioned bug (and while doing so, streamlines the caching condition)
- adds tests
Comment #6
sunThat comment in the test read a little bit wonky. Fixed.
Comment #7
Dries CreditAttribution: Dries commentedIn general, this looks good to me, but it feels like the tests could be documented better. It would be beneficial to explain what exactly we're testing, and to outline the approach taken on a high-level. I think that would help people grok things -- I know it would have saved me quite a bit of time. So, if possible, add a two sentence introduction as that would have helped wonders.
Comment #8
sunTrue. Added extensive docs.
Comment #9
chx CreditAttribution: chx commentedWhy should form_build_id be the same? If you re-submit some step of a multistep form and the form is gone from cache because you overwrote it what then...?
Comment #10
chx CreditAttribution: chx commentedthe build_id change is bogus, the tests are moving to #622922: User input keeping during multistep forms. Thanks for the tests.
Comment #11
sunWhile the test has been moved to #622922: User input keeping during multistep forms, we still want to do the minor clean-up to the usage of $form_build_id as condition for form_set_cache() from this patch.
I'll re-roll shortly.
Comment #12
sunchx additionally requested to update the inline comments.
Comment #13
Dries CreditAttribution: Dries commentedAdmittedly, I'm not sure why form ID isn't always set. The comments don't explain what it means for form ID not to be set. I'm happy to commit it with chx' blessing, but for me, it is a bit magical at the moment. It would be nice to have a comment that explains when form ID is and isn't set and why that is the case.
Comment #14
sunYou are right - that was a needless condition. Hence, this slightly revised patch simply brings consistency into both cases:
Even more clean now, thanks!
Comment #15
fagoI realized that the caching logic needs more improvements. Currently when a form is going to be rebuilt and needs caching, it's cached, then rebuilt and cached again. So in case we do the rebuild we don't need to cache beforehand.
I improved your patch to fix that by moving the caching block below the rebuild, which also has the side-affect of making caching possible when $_SESSION['batch_form_state'] is set. However the case when running from $_SESSION['batch_form_state'] seems broken to me anyway, as $form never gets set somewhere? But that's another issue then.
Also $form_state['cache'] has a default value, so no need to use !empty() to check it.
>Form #process handlers and #validate handlers are then supposed to use $form_state - as the name implies - as state machine for subsequent rebuilds of the form.
Right, but that patch does fix it only for storage. So let's tackle that in #641356: Cache more of $form_state when form caching is enabled afterwards.
Comment #16
sunArgh. Please don't. I think you're losing $form_build_id now. At least, it's not passed to drupal_rebuild_form(), which performs its own caching.
That's the part that was contained in earlier patches of this issue. chx disagreed that $form_build_id should keep the same in rebuild scenarios, so I removed it, and I already mentioned in #622922: User input keeping during multistep forms that I want/need to open a separate issue about that.
Since you didn't change the code of the old patch, I'm re-uploading and marking this RTBC.
Comment #17
Dries CreditAttribution: Dries commentedI committed sun's patch, but happy to keep working on fago's suggested improvements. Please re-open the issue if necessary, fago. Thanks all.
Comment #18
fago>Argh. Please don't. I think you're losing $form_build_id now. At least, it's not passed to drupal_rebuild_form(), which performs its own caching.
It was never passed to drupal_rebuild_form() inside from drupal_build_form() and my patch doesn't touch that at all, that's only done via the ajax handler. Also my patch doesn't touch the $form_build_id logic - still each rebuild gets its own build-id. But when you are already rebuilding you don't need to cache for the old build id too. So I re-rolled the patch and moved it into #647130: Cache only once when rebuilding a form