Commit dc22e33b authored by David Rothstein's avatar David Rothstein
Browse files

Issue #2760609 by Fabianx, stefan.r, chx: Allow the use of callbacks instead...

Issue #2760609 by Fabianx, stefan.r, chx: Allow the use of callbacks instead of global functions in parts of the Form API
parent 8ec2182e
Loading
Loading
Loading
Loading
+4 −3
Changes for includes/form.inc: 4 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -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;
+25 −11
Changes for modules/system/system.api.php: 25 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -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;
}