diff --git a/core/includes/form.inc b/core/includes/form.inc index 99fa7afedff..95470f98135 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -137,6 +137,28 @@ function drupal_get_form($form_id) { return drupal_build_form($form_id, $form_state); } +/** + * Returns a renderable form array using a specific callback. + * + * When using drupal_get_form(), the $form_id or information from hook_forms() + * is used to determine the callback used to build the form. If the callback + * needs to be explicitly specified, or if it is a method, use this function. + * + * @param string $form_id + * The unique string identifying the desired form. + * @param callable $callback + * A callback to be used for building the form. + * @param array $args + * (optional) An array of arguments to pass to the form callback. Defaults to + * an empty array. + */ +function drupal_get_callback_form($form_id, $callback, array $args = array()) { + $form_state = array(); + $form_state['build_info']['args'] = $args; + $form_state['build_info']['callback'] = $callback; + return drupal_build_form($form_id, $form_state); +} + /** * Builds and processes a form for a given form ID. * diff --git a/core/modules/block/lib/Drupal/block/BlockListController.php b/core/modules/block/lib/Drupal/block/BlockListController.php index d21e1a97b03..fc827711e59 100644 --- a/core/modules/block/lib/Drupal/block/BlockListController.php +++ b/core/modules/block/lib/Drupal/block/BlockListController.php @@ -55,10 +55,7 @@ class BlockListController extends ConfigEntityListController { // If no theme was specified, use the current theme. $this->theme = $theme ?: $GLOBALS['theme_key']; - $form_state = array(); - $form_state['build_info']['args'] = array(); - $form_state['build_info']['callback'] = array($this, 'form'); - return drupal_build_form('block_admin_display_form', $form_state); + return drupal_get_callback_form('block_admin_display_form', array($this, 'form')); } /** diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc index 269344c1c1a..4056e4a65da 100644 --- a/core/modules/field_ui/field_ui.admin.inc +++ b/core/modules/field_ui/field_ui.admin.inc @@ -315,11 +315,7 @@ function field_ui_field_overview($entity_type, $bundle) { $field_overview = new FieldOverview($entity_type, $bundle); - $form_state = array(); - $form_state['build_info']['callback'] = array($field_overview, 'form'); - $form_state['build_info']['args'] = array($entity_type, $bundle); - - return drupal_build_form('field_ui_field_overview_form', $form_state); + return drupal_get_callback_form('field_ui_field_overview_form', array($field_overview, 'form'), array($entity_type, $bundle)); } /** @@ -366,11 +362,7 @@ function field_ui_display_overview($entity_type, $bundle, $view_mode) { $display_overview = new DisplayOverview($entity_type, $bundle, $view_mode); - $form_state = array(); - $form_state['build_info']['callback'] = array($display_overview, 'form'); - $form_state['build_info']['args'] = array($entity_type, $bundle, $view_mode); - - return drupal_build_form('field_ui_display_overview_form', $form_state); + return drupal_get_callback_form('field_ui_display_overview_form', array($display_overview, 'form'), array($entity_type, $bundle, $view_mode)); } /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/CallbackBuilderTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/CallbackBuilderTest.php new file mode 100644 index 00000000000..f1a146dd1ce --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Form/CallbackBuilderTest.php @@ -0,0 +1,42 @@ + 'Form builder callbacks', + 'description' => 'Tests form builder callbacks.', + 'group' => 'Form API', + ); + } + + /** + * Tests using a static method to build a form. + */ + function testStaticMethodCallback() { + $this->drupalGet('form-test/callback-builder'); + $this->assertText('The Callbacks::buildForm() method was used for this form.'); + $elements = $this->xpath('//form[@id="form-test-callback-builder-form"]'); + $this->assertTrue(!empty($elements), 'The correct form ID was used even when it is not the callback function name.'); + } + +} diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module index b43372f5cf6..8c17e01b93f 100644 --- a/core/modules/system/tests/modules/form_test/form_test.module +++ b/core/modules/system/tests/modules/form_test/form_test.module @@ -25,6 +25,13 @@ function form_test_menu() { 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); + $items['form-test/callback-builder'] = array( + 'title' => 'Form callback builder test', + 'page callback' => 'drupal_get_callback_form', + 'page arguments' => array('form_test_callback_builder_form', '\Drupal\form_test\Callbacks::buildForm'), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); $items['form-test/validate-required'] = array( 'title' => 'Form #required validation', 'page callback' => 'drupal_get_form', diff --git a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/Callbacks.php b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/Callbacks.php index 6699cd7da37..ac43172d82d 100644 --- a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/Callbacks.php +++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/Callbacks.php @@ -8,7 +8,7 @@ namespace Drupal\form_test; /** - * Simple class for testing methods as element validation callbacks. + * Simple class for testing methods as Form API callbacks. */ class Callbacks { @@ -47,4 +47,13 @@ class Callbacks { form_set_error(''); } } + + /** + * Form constructor for the Form callback builder test form. + */ + public static function buildForm($form, &$form_state) { + $form['element'] = array('#markup' => 'The Callbacks::buildForm() method was used for this form.'); + return $form; + } + }