Commit 6303a156 authored by stefan.r's avatar stefan.r

Issue #2760609: Allow the use of callbacks instead of global functions in the Form API

parent ee2f0346
......@@ -105,7 +105,8 @@
* generate the same form (or very similar forms) using different $form_ids
* can implement hook_forms(), which maps different $form_id values to the
* proper form constructor function. Examples may be found in node_forms(),
* and search_forms().
* and search_forms(). hook_forms() can also be used to define forms in
* classes.
* @param ...
* Any additional arguments are passed on to the functions called by
* drupal_get_form(), including the unique form constructor function. For
......@@ -809,7 +810,7 @@ function drupal_retrieve_form($form_id, &$form_state) {
}
if (isset($form_definition['callback'])) {
$callback = $form_definition['callback'];
$form_state['build_info']['base_form_id'] = $callback;
$form_state['build_info']['base_form_id'] = isset($form_definition['base_form_id']) ? $form_definition['base_form_id'] : $callback;
}
// In case $form_state['wrapper_callback'] is not defined already, we also
// allow hook_forms() to define one.
......@@ -830,7 +831,7 @@ function drupal_retrieve_form($form_id, &$form_state) {
// the actual form builder function ($callback) expects. This allows for
// pre-populating a form with common elements for certain forms, such as
// back/next/save buttons in multi-step form wizards. See drupal_build_form().
if (isset($form_state['wrapper_callback']) && function_exists($form_state['wrapper_callback'])) {
if (isset($form_state['wrapper_callback']) && is_callable($form_state['wrapper_callback'])) {
$form = call_user_func_array($form_state['wrapper_callback'], $args);
// Put the prepopulated $form into $args.
$args[0] = $form;
......
......@@ -1797,6 +1797,8 @@ function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
* the $form_id input matched your module's format for dynamically-generated
* form IDs, and if so, act appropriately.
*
* Third, forms defined in classes can be defined this way.
*
* @param $form_id
* The unique string identifying the desired form.
* @param $args
......@@ -1807,19 +1809,22 @@ function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
* @return
* An associative array whose keys define form_ids and whose values are an
* associative array defining the following keys:
* - callback: The name of the form builder function to invoke. This will be
* used for the base form ID, for example, to target a base form using
* hook_form_BASE_FORM_ID_alter().
* - callback: The callable returning the form array. If it is the name of
* the form builder function then this will be used for the base
* form ID, for example, to target a base form using
* hook_form_BASE_FORM_ID_alter(). Otherwise use the base_form_id key to
* define the base form ID.
* - callback arguments: (optional) Additional arguments to pass to the
* function defined in 'callback', which are prepended to $args.
* - wrapper_callback: (optional) The name of a form builder function to
* invoke before the form builder defined in 'callback' is invoked. This
* wrapper callback may prepopulate the $form array with form elements,
* which will then be already contained in the $form that is passed on to
* the form builder defined in 'callback'. For example, a wrapper callback
* could setup wizard-alike form buttons that are the same for a variety of
* forms that belong to the wizard, which all share the same wrapper
* callback.
* - base_form_id: The base form ID can be specified explicitly. This is
* required when callback is not the name of a function.
* - wrapper_callback: (optional) Any callable to invoke before the form
* builder defined in 'callback' is invoked. This wrapper callback may
* prepopulate the $form array with form elements, which will then be
* already contained in the $form that is passed on to the form builder
* defined in 'callback'. For example, a wrapper callback could setup
* wizard-like form buttons that are the same for a variety of forms that
* belong to the wizard, which all share the same wrapper callback.
*/
function hook_forms($form_id, $args) {
// Simply reroute the (non-existing) $form_id 'mymodule_first_form' to
......@@ -1843,6 +1848,15 @@ function hook_forms($form_id, $args) {
'wrapper_callback' => 'mymodule_main_form_wrapper',
);
// Build a form with a static class callback.
$forms['mymodule_class_generated_form'] = array(
// This will call: MyClass::generateMainForm().
'callback' => array('MyClass', 'generateMainForm'),
// The base_form_id is required when the callback is a static function in
// a class. This can also be used to keep newer code backwards compatible.
'base_form_id' => 'mymodule_main_form',
);
return $forms;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment