When building forms, the form_state['build_info']['files'] should contain all files that should be included for the form to work when it is cached.
When presently your try to execute a cached a block configuration form with a sub-module, such as menu_block, enabled, you will get the error 'Fatal error: Call to undefined function menu_block_configure_form_follow_validate() in /home/adrupal/www/includes/form.inc on line 1389'. I found that this was because menu_block defines its form builder and validators in the include file 'menu_block.admin.inc', which is logical and a good thing from the performance viewpoint. However, it does so by including it on-the-fly, as follows:
function menu_block_block_configure($delta = '') {
module_load_include('inc', 'menu_block', 'menu_block.admin');
return _menu_block_block_configure($delta);
}
I first thought this would be a bug in menu_block but the problem lies in block.module. It should provide a form_state, so that menu_block can add menu_block.admin.inc to form_state['build_info']['files']. Then, the error message won't appear when caching the form.
The solution is simple: extend the hook with a form state parameter.
/**
* Define a configuration form for a block.
*
* @param $delta
* Which block is being configured. This is a unique identifier for the block
* within the module, defined in hook_block_info().
* @param $form_state
* The form state of the form that the settings will be included in. You may
* have to use this, for example, when you use a include file.
*
* @return
* A configuration form, if one is needed for your block beyond the standard
* elements that the block module provides (block title, visibility, etc.).
*
* For a detailed usage example, see block_example.module.
*
* @see hook_block_info()
* @see hook_block_save()
*/
function hook_block_configure($delta = '', &$form_state) {
// This example comes from node.module.
$form = array();
if ($delta == 'recent') {
$form['node_recent_block_count'] = array(
'#type' => 'select',
'#title' => t('Number of recent content items to display'),
'#default_value' => variable_get('node_recent_block_count', 10),
'#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)),
);
}
return $form;
}
Comment | File | Size | Author |
---|---|---|---|
#4 | 1596244-4.patch | 1.5 KB | joelpittet |
Comments
Comment #1
benjy CreditAttribution: benjy commentedIs this still an issue?
The code around block and menu has vastly changed since this report.
Comment #2
bvanmeurs CreditAttribution: bvanmeurs commentedThis is still an issue, as hook_block_configure does not have a form_state as the parameter. Because of this, it is still not possible to use include files in hook_block_configure.
However, I think this is more a feature request than a bug. It causes a bug when you try to implement the hook using an include file, as menu_block does, but is not a bug in itself.
That's why I change the status. The priority is minor as cached forms are not frequently used in practice.
Comment #3
swentel CreditAttribution: swentel commentedIt's not relevant anymore though for D8 - blocks are now plugins and completely different (and the configure method passes by ref too btw)
Comment #3.0
swentel CreditAttribution: swentel commented.
Comment #4
joelpittetHow about this? Would help us use
form_load_include()
. So that the callbacks could be outside the module.Comment #5
joelpittetRelated issue #2574457: Fatal Error: Call to undefined function menu_block_configure_form_follow_validate()
Comment #7
joelpittetFluke fail
Comment #8
joelpittet