I am a Permanent Member (or Community Ambassador) of the Drupal Association.Sometimes you might want to alter a $form array in a systematic and declarative manner. For example, say you want to change all of the #title elements to "foo". Here's a function that Adrian Rossouw and I just wrote that does just that. It recurses through all of the children elements of the form sending them (by reference) to a callback function of your choice. That callback can then alter them in any way it wants.
<?php
/**
* Take a form element or whole form array, and a callback, and
* recurse through all children elements, passing them to
* the callback function for processing.
*/
function step_form(&$element, $callback) {
foreach (element_children($element) as $child) {
step_form($element[$child], $callback);
}
$callback($element);
}
/**
* A callback function to change #title elements to the value "foo"
*/
function change_title(&$element) {
if (isset($element['#title'])) {
$element['#title'] = 'foo';
}
}
/**
* A fictional module's hook_form_alter implementation that sends the form
* to step_form() specifying change_title() as the callback function.
*/
function foo_form_alter(&$form, $form_state, $form_id) {
step_form($form, 'change_title');
}
?>
Comments
#process
#process is a better alternative.
Both Wysiwyg API module as well as #translatable module contain advanced examples of recursing into forms goodness.
That's why I post these!
Thanks for the better idea. I'll check it out right away!
-Rob
great idea (again)
This is a great idea! I never looked at the code behind it, but I think http://drupal.org/project/fquery provides a very similar feature
Yes it does
But I wanted something lightweight enough that I can just copy it into my module and not stress if it is duplicated code. I think the 5 lines are light enough for that. Sun's idea is even better. Will try it =)
-Rob
#process
Interestingly, #process isn’t included in the grid at the top of the API page, but it is documented lower on the page.
I am not sure that #process is a better replacement for the code I show above. It’s handy for telling the form system to do something with an element during processing, but to get the #process callback on every element I’d still have to use the recursive code from above. Remember that my goal here is to modify existing forms with my 3rd party contrib module (ie I don’t have the luxury of adding #process to the original form definition). Plus, it’s not exactly clear from the API docs at what point in the form processing the #process callback gets invoked. With the code above I at least know that it gets invoked before any processing has happened (aside from other form_alter hooks). I may be overlooking something, but I think I’ll stick with my code for now.
-Rob
Many moons ago, I took this
Many moons ago, I took this technique to an extreme in drupal 5. My takeaway was that with drupal's pseudo-object-alterable-array-anti-pattern the only sane thing to do was to minimize the number of functions you can possibly forget about, and only use helper functions with form alters in extreme circumstances [ this holds true for any of drupal's many pass an array by reference, and hope to god you're module weights are in order ] apis.
Then again -- I created a rather extreme, flexibile, feature-rich recursive mutant horror compared to this code snippet. #title is an innocent enough property... My implementation was in some ways a textbook example of the innerplatform effect.
[google "inner platform effect"]
But one must admit -- drupal's current php4 era array by reference madness does encourage inner platforms!
Lately, I've tended to do form altering the old fashioned way, using $form[#theme] whenever possible... $form[#theme] is a terrible trouble causing goblin -- but less so than the other root level "#foo" properties I've messed with that don't merely handle validate, or submit, or multistep, or all those other #bug_goblins I'm forgetting.
I can't help but think of Walkah's [google "why i hate drupal"] presentation at drupalcon... its true -- no one else tries to do this... If we can't improve the API -- then I think Boulton's 80% rule will certainly go a long way in ensuring we don't have override so many bloody things in order to make our sites presentable!
This is a Very good Idea
This is a Very good Idea
Thank you very much for sharing this useful Info.
Its an excellent tutorial about altering the titles of the form
Thanks
theme designer
Post new comment