Presently, drupal_get_form() is an all-or-nothing affair. You call it and it builds, validates, submits, and (if applicable) renders the form and returns it as HTML.

This causes problems, though, when forms are to be used in other processes or when forms must submit to themselves multiple times and dynamically change their contents. This patch splits the actual rendering of the form as HTML into a separate function. drupal_get_form() also gets a new optional paramater: $render. It defaults to true, but if it's set to false the function will return the raw form array rather than its HTML representation.

I'd like to split the building (including form_alter hook calls), the validation, and the submission portions into their own separate functions as well, allowing modules that need full contorl over the process to bypass drupal_get_form() entirely, but... baby steps.

Reviews would be much appreciated.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eaton’s picture

Title: FormAPI: make drupal_get_form() more flexible » FormAPI: make drupal_get_form() more granular
FileSize
5.39 KB

Here's a patch that *does* split out drupal_build_form(), allowing all the form altering and addition of necessary properties like #form_id to occur in a separate function. This will make it much, much simpler to create dynamic forms.

drupal_get_form() is now basically a wrapper for logic, and the relatively complex redirection handling. In cases where modules have to do very complex things with forms (wizards, and cases like views.module come to mind) it is now possible to sidestep drupal_get_form entirely and control the flow of form building and rendering without reimplimenting ~100 additional lines of essential code.

Yay.

eaton’s picture

FileSize
4.91 KB

And finally...

After some IRC discussions with chx, Vertice, and clouseau, a third version.

In this patch, drupal_get_form() is back to its original parameter list. However, all the meat of it is split out into separate functions:

drupal_build_form()
drupal_validate_form()
drupal_submit_form()
drupal_redirect_form()
drupal_render_form()

*no* existing behavior is changed, but modules with special needs and complex form based workflows can use those separate functions to bypass drupal_get_form() entirely and do their business as needed. drupal_get_form() would serve as the 'easy' way to display forms, and a reference implementation for those that need to build them in more complicated ways.

adrian’s picture

I am all for more granular code.

Not sure I like the extra parameter added.

eaton’s picture

Adrian, I've see the light on the extra parameter. the latest patch in this series eliminates that. With this patch, modules that need custom flow handling would just bypass drupal_get_form() entirely and do their thing.

With things broken out this way, doing so would still be reliable and safe -- there would be no need to duplicate the API's existing building/rendering/etc functions.

moshe weitzman’s picture

whats not to like? as long as it doesn't break anything, +1

eaton’s picture

FileSize
4.47 KB

Missed a change that went in yesterday (a clarifying comment in the rendering code). Added that and re-rolled.

eaton’s picture

FileSize
7.85 KB

Now with doxygen comments. Since the sub-functions are now acceptable for use by other modules, documenting them is a good thing.

eaton’s picture

FileSize
8.17 KB

Tweaks to the docs based on responses from chx and clouseau on #drupal. Thanks!

Dries’s picture

Version: 4.7.2 » x.y.z
Status: Needs review » Fixed

Looks good to me. Marking this RTBC. Will commit unless someone objects. Updating version to 'cvs'.

eaton’s picture

FileSize
8.17 KB

And... one more quick fix. I wasn't passing $form into drupal_redirect_form(), which obviously broke redirection.

webchick’s picture

Status: Fixed » Reviewed & tested by the community

I think this was meant to be marked RTBC

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Committed to CVS HEAD. Thanks.

Anonymous’s picture

Status: Fixed » Closed (fixed)