We do an awful lot of messing around with $_POST in various system modules. One of the biggest reasons is buttons: in validation and submit handlers, we have no way of knowing which button was clicked without peeking directly at the post global.
The following patch moves $_POST['op'] to $_POST['edit']['op'], where it becomes a part of the $form_values collection and can be used properly without evil messing about. There are a handful of places where we're using it in ways that can't be easily converted without full Form API refactorings (modules that put their submission logic in the page view function, rather than a _submit() handler), but this patch will make such a conversion simpler.
It's a subtle but important flaw in our system that the API has no direct way of communiting which form button was clicked.
| Comment | File | Size | Author |
|---|---|---|---|
| #23 | files_1.patch | 3.2 KB | chx |
| #22 | files_0.patch | 3.2 KB | chx |
| #21 | files.patch | 3.75 KB | Steven |
| #18 | form_edit.patch | 17.53 KB | chx |
| #15 | post_edit_considered_harmful_2.patch | 20.84 KB | eaton |
Comments
Comment #1
webchick+57! I love cleaner/more straight-forward code!! And I love the idea of not mucking with $_POST!
However, node forms are broken atm. When I try to preview/submit, I just get redirected back to the add form.
Comment #2
eaton commentedThis is terribly broken right now, but in progress. ;)
Comment #3
pwolanin commented+1 to this
Comment #4
eaton commentedSlightly updated, still needs work, but things aren't obviously broken. ;)
This actually eliminates the $_POST['edit'] construct entirely in favor of $_POST.
Comment #5
eaton commentedAnd here's a better version, with form.inc actually included in the patch.
This version of the patch changes all references to $_POST['edit'] and ['#post']['edit'] to $_POST and ['#post'], respectively. Why? A lot of investigating and a conversaion with UnConeD revealed that the only reason $_POST['edit'] exists is the legacy requirement that incoming form edit values be castable straight into a valid node object, to be passed into node_save().
The use of $_POST['edit'] causes major problems integrating submit buttons into the legitimate form values collection, among other things. By rolling everything back into $_POST, we gain the ability to work with the full range of form data (including the clicked button) in our submit and validate handlers.
Reviews appreciated.
Comment #6
eaton commentedChanging the title to reflect the direness of $_POST['edit'].
Comment #7
asimmonds commentedAny form with multiple checkboxes is broken, all checkboxes are cleared after form submission.
eg admin/user/access and admin/settings/modules are a couple of affected forms
Comment #8
mfredrickson commentedI like the idea. Have you thought about linking buttons to specific functions? I would do this by reappropriating the rather useless #submit option.
eg.
This attempt is not incompatible with your approach, but might make things cleaner in the long run. Obviously, if '#submit' is unset, this would call $formname_submit
-M
Comment #9
eaton commentedNew patch that fixes the issues with checkboxes (and, in fact, any form elements deeply nested). #name was being built incorrectly. Two lines of array-wiggling in form_builder correct this problem.
mfredrickson, you bring up an excellent point. previous, all buttons were hard-coded with the name 'op'. It didn't matter much, because those values weren't really available to most form processing code. Now, we not only get op, we can name separate sets of buttons differently to accomplish different things and switch based on which one was pressed. It's valuable, but I think we're a bit late in the development cycle to try to add complex function-firing based on it at this point. It's definitely a direction for future improvement, though.
I'll reiterate quickly why this patch is valuable and important.
Comment #10
eaton commentedRe-rolled against the current HEAD.
Comment #11
eaton commentedAnd, ironically, $_POST['op'] wasn't making it into $form_values['op']. Fixed.
Comment #12
neclimdul+1
This is great! I've always hated grabing 'op' from $_POST. And the ['edit'] thing just seemed strange and clunky. Very good!
I've tested this with a test version of the ecommerce cart module and it is working great.
Comment #13
dries commentedLooks good to me.
Eaton: can you make your summary a bit more accessible (more practical, less marketing). You say we no longer have to mess aroudn with $_POST, and yet, there are a lot of $_POSTs in your patch.
mfredrickson: I think your suggestion makes for a great improvement.
Thanks and keep up the good work! :)
Comment #14
eaton commentedGood point. Here's the rationale for the chat, minus hype. :)
In some cases, $_POST is examined when forms are redirecting to each other, or when our API would not be handing off the $form_values at all. These cases still remain in the code, as they need more individual attention and (potentially) more complex logic conversion. This patch, though, lays the groundwork for them and makes almost all 'normal' cases of $_POST peeking unecessary.
I like ordered lists.
Comment #15
eaton commentedRe-rolled against HEAD
Comment #16
dries commentedThanks for the extended information. It really helps to keep on top of the work you guys are doing.
I'm OK with this patch now. I'm marking this RTBC but I leave it to be co-maintainers to review it one last time.
(I think the individual callbacks for button is really worth pursuing in a seperate patch, but only if it actually cleans up the code (not when it introduces a second, alternative mechanism to submit forms). If it can be the 'one and only' mechanism, it strikes me as a significant improvement in term of readability and ease of use.)
Comment #17
eaton commentedDries, I'm going to let this patch sit as it is at RTBC, and pursue an add-on this evening that implements the button mechanism discussed above.
Comment #18
chx commentedDrumm asked for id to be prefixed edit- for CSS/JS namespacing (and theme backwards compatibility). As form API does not use this attribute, there are no new concerns.
Comment #19
drummCommitted to HEAD with code cleanup.
Comment #20
drummComment #21
Steven commentedThis patch broke file uploads. The edit prefix was removed, but the file_check_upload() code was not updated.
However, even when we used
edit[upload]as the fieldname="..."attribute, the values didn't end up in the $_POST['edit'] array anyway. They ended up in $_FILES['edit'][...]['upload'].So, for
#type => filefields, I restored the array notation with the more descriptive 'files' name instead of 'edit'. That way, we don't have to unnecessarily rewrite file_check_upload() to accomodate the different array structure.Comment #22
chx commentedI am not content with this change. #name changes should not occur in the theming layer.
Comment #23
chx commentedWorks a lot better if I actually put the elements in the files array and not in the file one...
Comment #24
eaton commentedJust tested on a fresh HEAD; uploads are in fact working again and all is well in JavaScript land. Changing the handling of the files array to prevent attempts at nesting is also a good idea; such things can only end in tears.
Comment #25
drummCommitted to HEAD.
Comment #26
(not verified) commented