This patch adds a new callback to drupal_render() so that elements that require additional work before they are rendered.

An example of this is if the theme('table') is implemented into the form api, the table data needs to be pre-proceeded to square up the table, get all the columns in order, etc. To do this if the process is calling drupal_get_form() then #process can be used. But if drupal_render() is called directly then #pre_render can call the function to do all the work to format the table, before the themeing is done.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eaton’s picture

Can we get a post-render in there, too? It would actually be quite useful in a number of situations as we begin to push more elements through drupal_render(). In the future, when we start using it for node_view(), it can also replace some of the nodeapi funkiness.

eaton’s picture

Also, a +1 on the intelligent loading of element defaults. Right now, it's up to the builder functions to populate element defaults. This is pretty sub-optimal and leaves holes in the rendering infrastructure. FAPI needs to do it earlier because it uses the element properties for quite a few internal building checks, but for everything else doing it at the render step is fine.

gordon’s picture

Thanks for this vote of confidence.

However I am not sure how to implement the #post_render so we can make the best use of it. Since changing the element would result in no change to the output, I was thinking that I could pass down the $content so you can alter the output directly but I am not sure if this is what you mean, or how you would like to be able to use it.

eaton’s picture

FileSize
1.71 KB

Here's a re-rolled version of the patch with some tweaks to the comments and the addition of a #post_render check.

moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

tested - nothing breaks. i can see how this is needed when rendering view items as opposed to form items.

Dries’s picture

Status: Reviewed & tested by the community » Needs work

I think this is a reasonable change, but it needs to be documented better.

I think we need code comments that explain in clear terms how/when these hooks are useful and when they should (or should not) be used. This can be as simple as a couple lines of text for each hook. Let's document this properly so non-core developers can make sense of this too.

Add that, and the patch is RTBC.

gordon’s picture

Status: Needs work » Needs review
FileSize
2.43 KB

I have made the changes and added some comments. Also I fixed up the missing changes that stop the elements from being added twice.

Dries’s picture

Hi Gordon, that helps. :)

1. Can we rename $process to $function? A process != function.

2. The documentation could be expanded a bid. What is $content at this point? Is it flat text or a structured array? If $context is flat text, how would this still be useful and why do we want to pass in $elements? I'm trying to figure out concrete use-cases here but the documentation fails short. It doesn't make me see the light. Please be more verbose -- if possible.

3. The same with #pre_render. Can we be a bit more concrete in the help text? For example, when rendering a form, should I alter the form in the _validate hook or in the #pre_render callback? What is the difference? There is no easy answer to some of these questions, it seems.

Maybe I'm expecting to much from the code comments. Small documented use-cases usually do wonders to understand why this might be useful. :)

gordon’s picture

Hi,

1. I have changed $process to $function. How ever I did get this code from the #process in form.inc

2. for the #pre_render is a structured array, where as #post_render the $content is a flat text field. Jeff gave a use case earlier (or was it in IRC) where you can put a #post_render in the top the array and then filter the $content and make any final changes.

3. as above.

I have extended the inline comments, but maybe more needs to be done in the api documentation.

gordon’s picture

FileSize
2.62 KB

forgot the patch

eaton’s picture

2. for the #pre_render is a structured array, where as #post_render the $content is a flat text field. Jeff gave a use case earlier (or was it in IRC) where you can put a #post_render in the top the array and then filter the $content and make any final changes.

This is one of the pre-requisites for replacing nodeapi's weird and ugly 'alter' operation, which works lie 'view' used to in the 4.7 days so that modules like inline can do fulltext replacement properly.

The use case, basically, is this: you have a renderable structure (like a form, a node, a user profile). Your module needs to manipulate its elements after they've been fully built and arranged but just before they render to HTML. (To add additional properties, insert attributes based on what other modules did, etc.) In some cases, as with FormAPI, full form information is not there during the hook_form_alter() phase, only basic structural data. This gives a 'last chance' to manipulate a specific element based on what processing has already been done.

Similarly, what if you want to filter a particular element of a node? For example, doing realtime substitution the way upload module does when it substitutes clean urls for dirty ones when previewing. Or, the way inline.module does when turning [image:1] into an inline version of the first image attached to the node. There's no way to do that with element-level granularity, which causes quite a bit of confusion with inline.module -- because it's tied to the body format of the node, ther'es no way to have severla CCK fields get the substitution if the body doesn't have inline turned on -- and no way to keep the other fields from being substituted if body IS given a format that includes inline. If there is no body for the node, the module can't operate at all because the format is never specified. The use of #post_render would allow this information to be attached to individual fields if necessary, or at the top level of $node->content for full-node substitution.

The way it's implemented here, we also incur no penalty -- just a check to see if it's set rather than the 'call every module and see if they implement this op' approach that is currently used in nodeapi. The work going on in the node rendering system would greatly benefit from this, as would anyone else working on tweaky modules that need to manipulate HTML output.

Dave Cohen’s picture

FileSize
2.37 KB

I just want to say +1.

Also, here's a patch for Drupal 5.1, based on the latest patch from Gordon.

Wim Leers’s picture

Subscribing.

eaton’s picture

Status: Needs review » Reviewed & tested by the community

Tested and poked at; this is a simple change that gives us a lot more flexibility. Since it adds one check during an existing array walk, we don't take much of a speed hit. (EACH array walk we perform takes a long time, so the more we can do in each trip through the form, the better.)

Dries’s picture

Status: Reviewed & tested by the community » Fixed

I've committed this patch.

Anonymous’s picture

Status: Fixed » Closed (fixed)