Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
The attached patch is *just* the drupal_execute() programmatic form handling code from http://drupal.org/node/79937. That issue was RTBC, drumm wanted it split.
Comment | File | Size | Author |
---|---|---|---|
#14 | patch_112 | 4.81 KB | moshe weitzman |
#13 | drupal_execute_3.patch | 3.87 KB | eaton |
#11 | drupal_execute_2.patch | 3.47 KB | eaton |
#6 | drupal_execute_1.patch | 3.5 KB | eaton |
#5 | drupal_execute_0.patch | 3.57 KB | eaton |
Comments
Comment #1
drummThanks.
in drupal_retrieve_form(), $args already is func_get_args() shifted once. Wouldn't that be better than all the arguments including form id for something like #parameters? I think I can see the use of #parameters, but I'd like to see some documentation other than "This is very useful for http://drupal.org/node/79900, Adrian's patch to allow recording of form input. It can store build params rather than the entire form."
The rest looks like a good cleanup.
Comment #2
Dries CreditAttribution: Dries commentedI agree with Neil that the argument handling is a bit weird.
Comment #3
drummComment #4
eaton CreditAttribution: eaton commented#parameters' purpose is to store *what is necessary to reconstitute the form* at another point.
$args isn't necessarily just the array-shifted version of the initial arguments. By the time #parameters is populated, it's also been merged with any hard-coded parameters specified in the hook_forms() function.
Why is that important? If we store a copy of *the original args passed into the function* we can feed #parameters straight back into drupal_retrieve_form to reconstitute a copy of the form. If we use the 'final' copy of $args, #parameters would be almost useless -- we couldn't use it with any of the core form functions, and we'd have to manually call the builder function.
I'll be adding a few lines of documentation to the code later this morning, but the code itself shouldn't change, IMO.
Comment #5
eaton CreditAttribution: eaton commentedAttached is a re-rolled patch with a comment explaining the purpose of #parameters, and why func_get_args() is used rather than $args.
Comment #6
eaton CreditAttribution: eaton commentedchx noted that drupal_execute() was irretrievably clobbering the return value of drupal_process_form(). We usually won't need that when programmatically processing a form, but it's impossible to recover that value after it's lost. It IS possible to call form_set_errors() after processing, though, so the redirect return value should win. Patch rerolled.
Comment #7
nickl CreditAttribution: nickl commentedSubscribe for http://drupal.org/node/79900 reroll... lets move this forward.
Other good reasons for this patch:
Test cases, submitting forms pragmatically.
Workflows, by executing other forms based on minimum user input or other events.
Using already implemented form functionality to execute streamlined processes or batch updates.
With all of these use cases only the field values to be submitted will be available and no reference to the $form array thus we need to be able to execute a form only with its values.
Comment #8
nickl CreditAttribution: nickl commentedStupid spell checkers: pragmatically could also be programatically...
Comment #9
Dries CreditAttribution: Dries commentedEven with the extra documentation I don't get it, and it is not properly documented in the code. (At least, not without spending 30 minutes looking that form API's control flow.) Also,
drupal_execute()
sounds weird. Maybedrupal_post()
ordrupal_submit()
is better? (Not sure, not important at this point.)Maybe I'm the only one here, but I find the form handling pretty darn hard to grok. Imagine the day, we loose our form API experts ... and we're left with something like the menu system ...
Comment #10
eaton CreditAttribution: eaton commented#parameters is, essentially, "what would have to be passed into drupal_get_form() to pull this form up again."
In cases where a given form id is mapped to a separate builder function using hook_forms(), drupal_retrieve_form() adds the callback arguments from the hook_forms() entry into the $args list. The full combined args list is passed to the form builder function. For example:
This is rather complex. But it's what allows us to alias multiple form IDs (some with slightly different callback arguments) to a central builder function. Like some of the other more esoteric properties, the only real solution is to either stop doing complicated things with forms, or duplicate a LOT of code between very similar forms, introducing many other errors along the way.
We do it in multiform scenerios by packing logic inside of drupal_get_form(). This parameter just allows other module code the opportunity to get at the same 'original parameters list' drupal_get_form() sees. It's a key requirement for Adrian's form-recording and playback workflow system, and it opens up opportunities for other modules to access more core data baout the formAPI system. It also doesn't break anything. ;)
If the #parameters thing is really a sticking point, I'm more than willing to pull it out. I suppose that it could, if really necessary, be turned into its own one-liner patch in a separate issue.
creating a new node is one example, though it's a little ugly because the node system itself requires some funky parameters. I'll look around for a good example that doesn't get too complicated. (Creating a new user is very clean, thus very convenient for demo use).
I went round and round on this; it's hard to find a descriptive function without trampling on or overloading functions we already use in the form workflow. The reason I settled on execute(), after a lof of discussion in #drupal, was because it uses the formAPI system but opens the doors for using in ways that aren't 'forms' at all, like Jaza's import-export system.
This is indeed a problem. I think the biggest areas of 'voodoo' right now are form_builder (because of the tremendous amount of work it does), the multistep form feature (because only a handful of peopel have used it), and hook_forms(). They're all necessary, but they are either super-complicated or very new.
Are there any 'hot spots' of mysteriousness that you can see? I've been neck-deep in forms for a month or two now, and while the workflow is something I feel I can confidently understand and explain now, I'm sure that I'm missing bits that are confusing to a casual peruser.
Comment #11
eaton CreditAttribution: eaton commentedrerolled against HEAD.
Comment #12
adrian CreditAttribution: adrian commentedWe need to know the parameters used when creating the form, because in the case of the node form .. you pass a node type (to add a node) or a node object to edit (which is kind of funky , since we need to build a node object in _menu, imo).
If you don't have the original parameters that were given to the form, what you do when you replay the functionality can be wildly different. For example recording a node/add , if you didn't have the type you would create dud nodes, if it even worked at all.
A type of form is identified by it's form id, but that SPECIFIC form is the form_id + it's parameters.
Comment #13
eaton CreditAttribution: eaton commentedCode is expensive, comments are cheap. There are now two simple examples of programmatic submission at the top of form.inc: adding a new user and creating a new node. One uses no parameters, the other (the node form) requires one. The chunk is as follows:
Hopefully, with Adrian's explanation re: the #parameters array, and the additional comments, this is RTBC. :)
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commentedCode looks good. I tested the both example submissions and they worked. I had to change $value['author'] to $value['name'] since thats what node form expects now. I removed the programmatic submit docs from top of node.module since this patch changes how things work and gives an up to date example at top of form.inc.
RTBC.
Comment #15
drummI'm okay with this.
I'll leave it to Dries to decide if his questions got answered.
Comment #16
nickl CreditAttribution: nickl commentedPatched to fresh head. +1
Lets move this forward...
Comment #17
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD. Thanks.
Comment #18
(not verified) CreditAttribution: commented