From 6a6e601d4a77bb8269a66b1d0d9438ae7048609a Mon Sep 17 00:00:00 2001 From: webchick Date: Sat, 23 Aug 2014 14:18:18 -0700 Subject: [PATCH] Issue #2309323 by Berdir, tim.plunkett: Allow #submit and #validate to be specified as methods of the form object. --- core/lib/Drupal/Core/Entity/EntityForm.php | 16 ++----- core/lib/Drupal/Core/Form/FormBuilder.php | 8 ++-- core/lib/Drupal/Core/Form/FormState.php | 11 +++++ .../Drupal/Core/Form/FormStateInterface.php | 14 ++++++ core/lib/Drupal/Core/Form/FormSubmitter.php | 6 +-- core/lib/Drupal/Core/Form/FormValidator.php | 6 +-- .../Core/Installer/Form/SiteSettingsForm.php | 2 +- core/modules/block/src/BlockForm.php | 2 +- core/modules/comment/src/CommentForm.php | 9 +--- .../src/Form/ConfigSingleExportForm.php | 4 +- core/modules/contact/src/MessageForm.php | 9 +--- .../dblog/src/Form/DblogFilterForm.php | 2 +- .../editor/src/Form/EditorImageDialog.php | 2 +- .../editor/src/Form/EditorLinkDialog.php | 2 +- .../src/Form/FieldInstanceEditForm.php | 2 +- core/modules/forum/src/Form/Overview.php | 2 +- .../language/src/Form/LanguageAddForm.php | 8 ++-- .../language/src/Form/LanguageEditForm.php | 4 +- .../locale/src/Form/TranslateFilterForm.php | 2 +- core/modules/node/src/NodeForm.php | 13 ++--- core/modules/path/src/Form/EditForm.php | 2 +- core/modules/path/src/Form/PathFilterForm.php | 2 +- .../search/src/SearchPageListBuilder.php | 6 +-- .../shortcut/src/Form/SetCustomize.php | 5 +- .../src/Controller/FormAjaxController.php | 2 + core/modules/system/src/Form/CronForm.php | 2 +- .../system/src/Form/DateFormatFormBase.php | 2 +- .../system/src/Form/PerformanceForm.php | 2 +- .../Tests/Form/FormDefaultHandlersTest.php | 4 +- .../ajax_test/src/Form/AjaxTestDialogForm.php | 4 +- .../FormTestLimitValidationErrorsForm.php | 14 +++--- .../src/Form/FormTestProgrammaticForm.php | 2 +- .../FormTestRebuildPreserveValuesForm.php | 2 +- .../src/Form/FormTestStorageForm.php | 4 +- .../src/Form/FormTestValidateRequiredForm.php | 2 +- .../taxonomy/src/Form/OverviewTerms.php | 2 +- core/modules/taxonomy/src/VocabularyForm.php | 2 +- core/modules/user/src/Form/UserLoginForm.php | 6 +-- core/modules/user/src/ProfileForm.php | 2 +- .../src/Form/AdvancedSettingsForm.php | 2 +- core/modules/views_ui/src/ViewAddForm.php | 4 +- .../views_ui/src/ViewDuplicateForm.php | 4 +- core/modules/views_ui/src/ViewEditForm.php | 18 ++++--- core/modules/views_ui/src/ViewPreviewForm.php | 2 +- .../Drupal/Tests/Core/Form/FormStateTest.php | 47 +++++++++++++++++++ .../Tests/Core/Form/FormSubmitterTest.php | 11 ++++- 46 files changed, 164 insertions(+), 115 deletions(-) diff --git a/core/lib/Drupal/Core/Entity/EntityForm.php b/core/lib/Drupal/Core/Entity/EntityForm.php index 3ca1d3838a6..3cf5558de3b 100644 --- a/core/lib/Drupal/Core/Entity/EntityForm.php +++ b/core/lib/Drupal/Core/Entity/EntityForm.php @@ -138,7 +138,7 @@ class EntityForm extends FormBase implements EntityFormInterface { $entity = $this->entity; // Add a process callback. - $form['#process'][] = array($this, 'processForm'); + $form['#process'][] = '::processForm'; if (!isset($form['langcode'])) { // If the form did not specify otherwise, default to keeping the existing @@ -210,13 +210,8 @@ class EntityForm extends FormBase implements EntityFormInterface { $actions['submit'] = array( '#type' => 'submit', '#value' => $this->t('Save'), - '#validate' => array( - array($this, 'validate'), - ), - '#submit' => array( - array($this, 'submit'), - array($this, 'save'), - ), + '#validate' => array('::validate'), + '#submit' => array('::submit', '::save'), ); if (!$this->entity->isNew() && $this->entity->hasLinkTemplate('delete-form')) { @@ -317,11 +312,6 @@ class EntityForm extends FormBase implements EntityFormInterface { */ public function buildEntity(array $form, FormStateInterface $form_state) { $entity = clone $this->entity; - // If you submit a form, the form state comes from caching, which forces - // the form object to be the one before caching. Ensure to have the - // form object of the current request. - $form_state['controller'] = $this; - $this->copyFormValuesToEntity($entity, $form, $form_state); // Invoke all specified builders for copying form values to entity diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index 7d7ab24fd4f..bf9aa882c44 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -639,8 +639,8 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS $form += $this->getElementInfo('form'); $form += array('#tree' => FALSE, '#parents' => array()); - $form['#validate'][] = array($form_state['build_info']['callback_object'], 'validateForm'); - $form['#submit'][] = array($form_state['build_info']['callback_object'], 'submitForm'); + $form['#validate'][] = '::validateForm'; + $form['#submit'][] = '::submitForm'; // If no #theme has been set, automatically apply theme suggestions. // theme_form() itself is in #theme_wrappers and not #theme. Therefore, the @@ -767,9 +767,9 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS // Allow for elements to expand to multiple elements, e.g., radios, // checkboxes and files. if (isset($element['#process']) && !$element['#processed']) { - foreach ($element['#process'] as $process) { + foreach ($element['#process'] as $callback) { $complete_form = &$form_state->getCompleteForm(); - $element = call_user_func_array($process, array(&$element, &$form_state, &$complete_form)); + $element = call_user_func_array($form_state->prepareCallback($callback), array(&$element, &$form_state, &$complete_form)); } $element['#processed'] = TRUE; } diff --git a/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php index 038e63f338b..50b75f7c222 100644 --- a/core/lib/Drupal/Core/Form/FormState.php +++ b/core/lib/Drupal/Core/Form/FormState.php @@ -796,6 +796,17 @@ class FormState implements FormStateInterface, \ArrayAccess { return $this; } + + /** + * {@inheritdoc} + */ + public function prepareCallback($callback) { + if (is_string($callback) && substr($callback, 0, 2) == '::') { + $callback = array($this->get('build_info')['callback_object'], substr($callback, 2)); + } + return $callback; + } + /** * Wraps drupal_set_message(). * diff --git a/core/lib/Drupal/Core/Form/FormStateInterface.php b/core/lib/Drupal/Core/Form/FormStateInterface.php index f7abf0e1332..164078a20a1 100644 --- a/core/lib/Drupal/Core/Form/FormStateInterface.php +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php @@ -456,4 +456,18 @@ interface FormStateInterface { */ public function setRebuild($rebuild = TRUE); + /** + * Converts support notations for a form callback to a valid callable. + * + * Specifically, supports methods on the form/callback object as strings when + * they start with ::, for example "::submitForm()". + * + * @param string|array $callback + * The callback. + * + * @return array|string + * A valid callable. + */ + public function prepareCallback($callback); + } diff --git a/core/lib/Drupal/Core/Form/FormSubmitter.php b/core/lib/Drupal/Core/Form/FormSubmitter.php index e99727e6040..ab7e76ef424 100644 --- a/core/lib/Drupal/Core/Form/FormSubmitter.php +++ b/core/lib/Drupal/Core/Form/FormSubmitter.php @@ -105,7 +105,7 @@ class FormSubmitter implements FormSubmitterInterface { $handlers = array(); } - foreach ($handlers as $function) { + foreach ($handlers as $callback) { // Check if a previous _submit handler has set a batch, but make sure we // do not react to a batch that is already being processed (for instance // if a batch operation performs a @@ -114,11 +114,11 @@ class FormSubmitter implements FormSubmitterInterface { // Some previous submit handler has set a batch. To ensure correct // execution order, store the call in a special 'control' batch set. // See _batch_next_set(). - $batch['sets'][] = array('form_submit' => $function); + $batch['sets'][] = array('form_submit' => $callback); $batch['has_form_submits'] = TRUE; } else { - call_user_func_array($function, array(&$form, &$form_state)); + call_user_func_array($form_state->prepareCallback($callback), array(&$form, &$form_state)); } } } diff --git a/core/lib/Drupal/Core/Form/FormValidator.php b/core/lib/Drupal/Core/Form/FormValidator.php index de48d4c0ee6..5efedb089d6 100644 --- a/core/lib/Drupal/Core/Form/FormValidator.php +++ b/core/lib/Drupal/Core/Form/FormValidator.php @@ -79,8 +79,8 @@ class FormValidator implements FormValidatorInterface { $handlers = array(); } - foreach ($handlers as $function) { - call_user_func_array($function, array(&$form, &$form_state)); + foreach ($handlers as $callback) { + call_user_func_array($form_state->prepareCallback($callback), array(&$form, &$form_state)); } } @@ -263,7 +263,7 @@ class FormValidator implements FormValidatorInterface { elseif (isset($elements['#element_validate'])) { foreach ($elements['#element_validate'] as $callback) { $complete_form = &$form_state->getCompleteForm(); - call_user_func_array($callback, array(&$elements, &$form_state, &$complete_form)); + call_user_func_array($form_state->prepareCallback($callback), array(&$elements, &$form_state, &$complete_form)); } } diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php index 1b08b475e09..48fadf64de9 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -104,7 +104,7 @@ class SiteSettingsForm extends FormBase { array('driver'), array($default_driver), ), - '#submit' => array(array($this, 'submitForm')), + '#submit' => array('::submitForm'), ); $form['errors'] = array(); diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php index e289086e4a4..e3d442d4e6f 100644 --- a/core/modules/block/src/BlockForm.php +++ b/core/modules/block/src/BlockForm.php @@ -101,7 +101,7 @@ class BlockForm extends EntityForm { '#title' => t('Theme'), '#default_value' => $theme, '#ajax' => array( - 'callback' => array($this, 'themeSwitch'), + 'callback' => '::themeSwitch', 'wrapper' => 'edit-block-region-wrapper', ), ); diff --git a/core/modules/comment/src/CommentForm.php b/core/modules/comment/src/CommentForm.php index 3ba804d3d7b..075e463f576 100644 --- a/core/modules/comment/src/CommentForm.php +++ b/core/modules/comment/src/CommentForm.php @@ -244,13 +244,8 @@ class CommentForm extends ContentEntityForm { '#type' => 'submit', '#value' => $this->t('Preview'), '#access' => $preview_mode != DRUPAL_DISABLED, - '#validate' => array( - array($this, 'validate'), - ), - '#submit' => array( - array($this, 'submit'), - array($this, 'preview'), - ), + '#validate' => array('::validate'), + '#submit' => array('::submit', '::preview'), ); return $element; diff --git a/core/modules/config/src/Form/ConfigSingleExportForm.php b/core/modules/config/src/Form/ConfigSingleExportForm.php index 579501a4e09..6a22b168541 100644 --- a/core/modules/config/src/Form/ConfigSingleExportForm.php +++ b/core/modules/config/src/Form/ConfigSingleExportForm.php @@ -95,7 +95,7 @@ class ConfigSingleExportForm extends FormBase { '#options' => $config_types, '#default_value' => $config_type, '#ajax' => array( - 'callback' => array($this, 'updateConfigurationType'), + 'callback' => '::updateConfigurationType', 'wrapper' => 'edit-config-type-wrapper', ), ); @@ -109,7 +109,7 @@ class ConfigSingleExportForm extends FormBase { '#prefix' => '
', '#suffix' => '
', '#ajax' => array( - 'callback' => array($this, 'updateExport'), + 'callback' => '::updateExport', 'wrapper' => 'edit-export-wrapper', ), ); diff --git a/core/modules/contact/src/MessageForm.php b/core/modules/contact/src/MessageForm.php index 72aaeb33ca0..ca7be751bb2 100644 --- a/core/modules/contact/src/MessageForm.php +++ b/core/modules/contact/src/MessageForm.php @@ -156,13 +156,8 @@ class MessageForm extends ContentEntityForm { $elements['submit']['#value'] = $this->t('Send message'); $elements['preview'] = array( '#value' => $this->t('Preview'), - '#validate' => array( - array($this, 'validate'), - ), - '#submit' => array( - array($this, 'submit'), - array($this, 'preview'), - ), + '#validate' => array('::validate'), + '#submit' => array('::submit', '::preview'), ); return $elements; } diff --git a/core/modules/dblog/src/Form/DblogFilterForm.php b/core/modules/dblog/src/Form/DblogFilterForm.php index 4804e7ed8bb..140189396e5 100644 --- a/core/modules/dblog/src/Form/DblogFilterForm.php +++ b/core/modules/dblog/src/Form/DblogFilterForm.php @@ -59,7 +59,7 @@ class DblogFilterForm extends FormBase { '#type' => 'submit', '#value' => $this->t('Reset'), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'resetForm')), + '#submit' => array('::resetForm'), ); } return $form; diff --git a/core/modules/editor/src/Form/EditorImageDialog.php b/core/modules/editor/src/Form/EditorImageDialog.php index 66438f9027f..8193cb67e1d 100644 --- a/core/modules/editor/src/Form/EditorImageDialog.php +++ b/core/modules/editor/src/Form/EditorImageDialog.php @@ -189,7 +189,7 @@ class EditorImageDialog extends FormBase { // No regular submit-handler. This form only works via JavaScript. '#submit' => array(), '#ajax' => array( - 'callback' => array($this, 'submitForm'), + 'callback' => '::submitForm', 'event' => 'click', ), ); diff --git a/core/modules/editor/src/Form/EditorLinkDialog.php b/core/modules/editor/src/Form/EditorLinkDialog.php index 47b78c85d77..758b489d14c 100644 --- a/core/modules/editor/src/Form/EditorLinkDialog.php +++ b/core/modules/editor/src/Form/EditorLinkDialog.php @@ -69,7 +69,7 @@ class EditorLinkDialog extends FormBase { // No regular submit-handler. This form only works via JavaScript. '#submit' => array(), '#ajax' => array( - 'callback' => array($this, 'submitForm'), + 'callback' => '::submitForm', 'event' => 'click', ), ); diff --git a/core/modules/field_ui/src/Form/FieldInstanceEditForm.php b/core/modules/field_ui/src/Form/FieldInstanceEditForm.php index 6061d9f1148..bc722483296 100644 --- a/core/modules/field_ui/src/Form/FieldInstanceEditForm.php +++ b/core/modules/field_ui/src/Form/FieldInstanceEditForm.php @@ -157,7 +157,7 @@ class FieldInstanceEditForm extends FormBase { $form['actions']['delete'] = array( '#type' => 'submit', '#value' => $this->t('Delete field'), - '#submit' => array(array($this, 'delete')), + '#submit' => array('::delete'), ); return $form; } diff --git a/core/modules/forum/src/Form/Overview.php b/core/modules/forum/src/Form/Overview.php index 98688ab03a5..126d845cc61 100644 --- a/core/modules/forum/src/Form/Overview.php +++ b/core/modules/forum/src/Form/Overview.php @@ -99,7 +99,7 @@ class Overview extends OverviewTerms { // The form needs to have submit and validate handlers set explicitly. // Use the existing taxonomy overview submit handler. - $form['#submit'] = array(array($this, 'submitForm')); + $form['#submit'] = array('::submitForm'); $form['terms']['#empty'] = $this->t('No containers or forums available. Add container or Add forum.', array( '@container' => $this->url('forum.add_container'), '@forum' => $this->url('forum.add_forum') diff --git a/core/modules/language/src/Form/LanguageAddForm.php b/core/modules/language/src/Form/LanguageAddForm.php index 9b6445cf553..acef8631f81 100644 --- a/core/modules/language/src/Form/LanguageAddForm.php +++ b/core/modules/language/src/Form/LanguageAddForm.php @@ -49,8 +49,8 @@ class LanguageAddForm extends LanguageFormBase { 'select#edit-predefined-langcode' => array('value' => 'custom'), ), ), - '#validate' => array(array($this, 'validatePredefined')), - '#submit' => array(array($this, 'submitForm')), + '#validate' => array('::validatePredefined'), + '#submit' => array('::submitForm'), ); $custom_language_states_conditions = array( @@ -72,8 +72,8 @@ class LanguageAddForm extends LanguageFormBase { $form['custom_language']['submit'] = array( '#type' => 'submit', '#value' => $this->t('Add custom language'), - '#validate' => array(array($this, 'validateCustom')), - '#submit' => array(array($this, 'submitForm')), + '#validate' => array('::validateCustom'), + '#submit' => array('::submitForm'), ); return $form; diff --git a/core/modules/language/src/Form/LanguageEditForm.php b/core/modules/language/src/Form/LanguageEditForm.php index abac06d2cb7..de2213a3899 100644 --- a/core/modules/language/src/Form/LanguageEditForm.php +++ b/core/modules/language/src/Form/LanguageEditForm.php @@ -38,8 +38,8 @@ class LanguageEditForm extends LanguageFormBase { $actions['submit'] = array( '#type' => 'submit', '#value' => $this->t('Save language'), - '#validate' => array(array($this, 'validateCommon')), - '#submit' => array(array($this, 'submitForm')), + '#validate' => array('::validateCommon'), + '#submit' => array('::submitForm'), ); return $actions; } diff --git a/core/modules/locale/src/Form/TranslateFilterForm.php b/core/modules/locale/src/Form/TranslateFilterForm.php index 1a109b53a88..d283724f97c 100644 --- a/core/modules/locale/src/Form/TranslateFilterForm.php +++ b/core/modules/locale/src/Form/TranslateFilterForm.php @@ -74,7 +74,7 @@ class TranslateFilterForm extends TranslateFormBase { $form['filters']['actions']['reset'] = array( '#type' => 'submit', '#value' => $this->t('Reset'), - '#submit' => array(array($this, 'resetForm')), + '#submit' => array('::resetForm'), ); } diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php index 327aee5d18a..a100487a5a5 100644 --- a/core/modules/node/src/NodeForm.php +++ b/core/modules/node/src/NodeForm.php @@ -288,7 +288,7 @@ class NodeForm extends ContentEntityForm { $element['publish']['#value'] = $node->isPublished() ? t('Save and keep published') : t('Save and publish'); } $element['publish']['#weight'] = 0; - array_unshift($element['publish']['#submit'], array($this, 'publish')); + array_unshift($element['publish']['#submit'], '::publish'); // Add a "Unpublish" button. $element['unpublish'] = $element['submit']; @@ -300,7 +300,7 @@ class NodeForm extends ContentEntityForm { $element['unpublish']['#value'] = !$node->isPublished() ? t('Save and keep unpublished') : t('Save and unpublish'); } $element['unpublish']['#weight'] = 10; - array_unshift($element['unpublish']['#submit'], array($this, 'unpublish')); + array_unshift($element['unpublish']['#submit'], '::unpublish'); // If already published, the 'publish' button is primary. if ($node->isPublished()) { @@ -321,13 +321,8 @@ class NodeForm extends ContentEntityForm { '#access' => $preview_mode != DRUPAL_DISABLED && ($node->access('create') || $node->access('update')), '#value' => t('Preview'), '#weight' => 20, - '#validate' => array( - array($this, 'validate'), - ), - '#submit' => array( - array($this, 'submit'), - array($this, 'preview'), - ), + '#validate' => array('::validate'), + '#submit' => array('::submit', '::preview'), ); $element['delete']['#access'] = $node->access('delete'); diff --git a/core/modules/path/src/Form/EditForm.php b/core/modules/path/src/Form/EditForm.php index e86c3ec4227..95d5e205d7f 100644 --- a/core/modules/path/src/Form/EditForm.php +++ b/core/modules/path/src/Form/EditForm.php @@ -44,7 +44,7 @@ class EditForm extends PathFormBase { $form['actions']['delete'] = array( '#type' => 'submit', '#value' => $this->t('Delete'), - '#submit' => array(array($this, 'deleteSubmit')), + '#submit' => array('::deleteSubmit'), ); return $form; } diff --git a/core/modules/path/src/Form/PathFilterForm.php b/core/modules/path/src/Form/PathFilterForm.php index 42e50a45610..30374be54f3 100644 --- a/core/modules/path/src/Form/PathFilterForm.php +++ b/core/modules/path/src/Form/PathFilterForm.php @@ -50,7 +50,7 @@ class PathFilterForm extends FormBase { $form['basic']['reset'] = array( '#type' => 'submit', '#value' => $this->t('Reset'), - '#submit' => array(array($this, 'resetForm')), + '#submit' => array('::resetForm'), ); } return $form; diff --git a/core/modules/search/src/SearchPageListBuilder.php b/core/modules/search/src/SearchPageListBuilder.php index c5b939ac6bb..5e6f1b5d55d 100644 --- a/core/modules/search/src/SearchPageListBuilder.php +++ b/core/modules/search/src/SearchPageListBuilder.php @@ -185,7 +185,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac $form['status']['wipe'] = array( '#type' => 'submit', '#value' => $this->t('Re-index site'), - '#submit' => array(array($this, 'searchAdminReindexSubmit')), + '#submit' => array('::searchAdminReindexSubmit'), ); $items = array(10, 20, 50, 100, 200, 500); @@ -271,8 +271,8 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac $form['search_pages']['add_page']['add_search_submit'] = array( '#type' => 'submit', '#value' => $this->t('Add new page'), - '#validate' => array(array($this, 'validateAddSearchPage')), - '#submit' => array(array($this, 'submitAddSearchPage')), + '#validate' => array('::validateAddSearchPage'), + '#submit' => array('::submitAddSearchPage'), '#limit_validation_errors' => array(array('search_type')), ); diff --git a/core/modules/shortcut/src/Form/SetCustomize.php b/core/modules/shortcut/src/Form/SetCustomize.php index d19381d6dc7..b0aaef36131 100644 --- a/core/modules/shortcut/src/Form/SetCustomize.php +++ b/core/modules/shortcut/src/Form/SetCustomize.php @@ -89,10 +89,7 @@ class SetCustomize extends EntityForm { 'submit' => array( '#value' => t('Save changes'), '#access' => (bool) Element::getVisibleChildren($form['shortcuts']['links']), - '#submit' => array( - array($this, 'submit'), - array($this, 'save'), - ), + '#submit' => array('::submit', '::save'), ), ); } diff --git a/core/modules/system/src/Controller/FormAjaxController.php b/core/modules/system/src/Controller/FormAjaxController.php index 84d1f86445e..5285cfde156 100644 --- a/core/modules/system/src/Controller/FormAjaxController.php +++ b/core/modules/system/src/Controller/FormAjaxController.php @@ -72,9 +72,11 @@ class FormAjaxController implements ContainerInjectionInterface { // up to the #ajax['callback'] function of the element (may or may not be a // button) that triggered the Ajax request to determine what needs to be // rendered. + $callback = NULL; if (!empty($form_state['triggering_element'])) { $callback = $form_state['triggering_element']['#ajax']['callback']; } + $callback = $form_state->prepareCallback($callback); if (empty($callback) || !is_callable($callback)) { throw new HttpException(500, t('Internal Server Error')); } diff --git a/core/modules/system/src/Form/CronForm.php b/core/modules/system/src/Form/CronForm.php index 63a17d1014a..14900ea297f 100644 --- a/core/modules/system/src/Form/CronForm.php +++ b/core/modules/system/src/Form/CronForm.php @@ -92,7 +92,7 @@ class CronForm extends ConfigFormBase { $form['run'] = array( '#type' => 'submit', '#value' => t('Run cron'), - '#submit' => array(array($this, 'submitCron')), + '#submit' => array('::submitCron'), ); $status = '

' . t('Last run: %cron-last ago.', array('%cron-last' => $this->dateFormatter->formatInterval(REQUEST_TIME - $this->state->get('system.cron_last')))) . '

'; diff --git a/core/modules/system/src/Form/DateFormatFormBase.php b/core/modules/system/src/Form/DateFormatFormBase.php index 311f5db7933..a84e571e12b 100644 --- a/core/modules/system/src/Form/DateFormatFormBase.php +++ b/core/modules/system/src/Form/DateFormatFormBase.php @@ -135,7 +135,7 @@ abstract class DateFormatFormBase extends EntityForm { '#default_value' => '', '#field_suffix' => ' ', '#ajax' => array( - 'callback' => array($this, 'dateTimeLookup'), + 'callback' => '::dateTimeLookup', 'event' => 'keyup', 'progress' => array('type' => 'throbber', 'message' => NULL), ), diff --git a/core/modules/system/src/Form/PerformanceForm.php b/core/modules/system/src/Form/PerformanceForm.php index f5261f846a6..ed631f32b5a 100644 --- a/core/modules/system/src/Form/PerformanceForm.php +++ b/core/modules/system/src/Form/PerformanceForm.php @@ -107,7 +107,7 @@ class PerformanceForm extends ConfigFormBase { $form['clear_cache']['clear'] = array( '#type' => 'submit', '#value' => t('Clear all caches'), - '#submit' => array(array($this, 'submitCacheClear')), + '#submit' => array('::submitCacheClear'), ); $form['caching'] = array( diff --git a/core/modules/system/src/Tests/Form/FormDefaultHandlersTest.php b/core/modules/system/src/Tests/Form/FormDefaultHandlersTest.php index 7fa6a7c2df9..51c79f85212 100644 --- a/core/modules/system/src/Tests/Form/FormDefaultHandlersTest.php +++ b/core/modules/system/src/Tests/Form/FormDefaultHandlersTest.php @@ -37,8 +37,8 @@ class FormDefaultHandlersTest extends KernelTestBase implements FormInterface { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { - $form['#validate'][] = array($this, 'customValidateForm'); - $form['#submit'][] = array($this, 'customSubmitForm'); + $form['#validate'][] = '::customValidateForm'; + $form['#submit'][] = '::customSubmitForm'; $form['submit'] = array('#type' => 'submit', '#value' => 'Save'); return $form; } diff --git a/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php b/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php index 22dc4ee616c..21b3ac6bfee 100644 --- a/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php +++ b/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php @@ -42,7 +42,7 @@ class AjaxTestDialogForm extends FormBase { '#name' => 'button1', '#value' => 'Button 1 (modal)', '#ajax' => array( - 'callback' => array($this, 'modal'), + 'callback' => '::modal', ), ); $form['button2'] = array( @@ -50,7 +50,7 @@ class AjaxTestDialogForm extends FormBase { '#name' => 'button2', '#value' => 'Button 2 (non-modal)', '#ajax' => array( - 'callback' => array($this, 'nonModal'), + 'callback' => '::nonModal', ), ); diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestLimitValidationErrorsForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestLimitValidationErrorsForm.php index 8f260be9e70..dab4ac6164a 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestLimitValidationErrorsForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestLimitValidationErrorsForm.php @@ -35,7 +35,7 @@ class FormTestLimitValidationErrorsForm extends FormBase { $form['test'] = array( '#title' => 'Test', '#type' => 'textfield', - '#element_validate' => array(array($this, 'elementValidateLimitValidationErrors')), + '#element_validate' => array('::elementValidateLimitValidationErrors'), ); $form['test_numeric_index'] = array( '#tree' => TRUE, @@ -43,7 +43,7 @@ class FormTestLimitValidationErrorsForm extends FormBase { $form['test_numeric_index'][0] = array( '#title' => 'Test (numeric index)', '#type' => 'textfield', - '#element_validate' => array(array($this, 'elementValidateLimitValidationErrors')), + '#element_validate' => array('::elementValidateLimitValidationErrors'), ); $form['test_substring'] = array( @@ -52,30 +52,30 @@ class FormTestLimitValidationErrorsForm extends FormBase { $form['test_substring']['foo'] = array( '#title' => 'Test (substring) foo', '#type' => 'textfield', - '#element_validate' => array(array($this, 'elementValidateLimitValidationErrors')), + '#element_validate' => array('::elementValidateLimitValidationErrors'), ); $form['test_substring']['foobar'] = array( '#title' => 'Test (substring) foobar', '#type' => 'textfield', - '#element_validate' => array(array($this, 'elementValidateLimitValidationErrors')), + '#element_validate' => array('::elementValidateLimitValidationErrors'), ); $form['actions']['partial'] = array( '#type' => 'submit', '#limit_validation_errors' => array(array('test')), - '#submit' => array(array($this, 'partialSubmitForm')), + '#submit' => array('::partialSubmitForm'), '#value' => t('Partial validate'), ); $form['actions']['partial_numeric_index'] = array( '#type' => 'submit', '#limit_validation_errors' => array(array('test_numeric_index', 0)), - '#submit' => array(array($this, 'partialSubmitForm')), + '#submit' => array('::partialSubmitForm'), '#value' => t('Partial validate (numeric index)'), ); $form['actions']['substring'] = array( '#type' => 'submit', '#limit_validation_errors' => array(array('test_substring', 'foo')), - '#submit' => array(array($this, 'partialSubmitForm')), + '#submit' => array('::partialSubmitForm'), '#value' => t('Partial validate (substring)'), ); $form['actions']['full'] = array( diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestProgrammaticForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestProgrammaticForm.php index 86689a00ca6..baa146bc44c 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestProgrammaticForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestProgrammaticForm.php @@ -74,7 +74,7 @@ class FormTestProgrammaticForm extends FormBase { // Use the same submit handler for this button as for the form itself. // (This must be set explicitly or otherwise the form API will ignore the // #limit_validation_errors property.) - '#submit' => array(array($this, 'submitForm')), + '#submit' => array('::submitForm'), ); $user_input = $form_state->getUserInput(); if (!empty($user_input['field_to_validate']) && $user_input['field_to_validate'] != 'all') { diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestRebuildPreserveValuesForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestRebuildPreserveValuesForm.php index 47f1f392adf..00a95705d30 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestRebuildPreserveValuesForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestRebuildPreserveValuesForm.php @@ -53,7 +53,7 @@ class FormTestRebuildPreserveValuesForm extends FormBase { $form['add_more'] = array( '#type' => 'submit', '#value' => 'Add more', - '#submit' => array(array($this, 'addMoreSubmitForm')), + '#submit' => array('::addMoreSubmitForm'), ); } else { diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php index c7ca2f4bea0..fb231607fdd 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php @@ -63,7 +63,7 @@ class FormTestStorageForm extends FormBase { '#type' => 'textfield', '#title' => 'Value', '#default_value' => $form_state['storage']['thing']['value'], - '#element_validate' => array(array($this, 'elementValidateValueCached')), + '#element_validate' => array('::elementValidateValueCached'), ); $form['continue_button'] = array( '#type' => 'button', @@ -73,7 +73,7 @@ class FormTestStorageForm extends FormBase { $form['continue_submit'] = array( '#type' => 'submit', '#value' => 'Continue submit', - '#submit' => array(array($this, 'continueSubmitForm')), + '#submit' => array('::continueSubmitForm'), ); $form['submit'] = array( '#type' => 'submit', diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestValidateRequiredForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestValidateRequiredForm.php index 35908ad5e26..40803de7e0f 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestValidateRequiredForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestValidateRequiredForm.php @@ -27,7 +27,7 @@ class FormTestValidateRequiredForm extends FormBase { */ public function buildForm(array $form, FormStateInterface $form_state) { $options = array('foo' => 'foo', 'bar' => 'bar'); - $validate = array(array($this, 'elementValidateRequired')); + $validate = array('::elementValidateRequired'); $form['textfield'] = array( '#type' => 'textfield', diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php index d28b53c5b6d..e2eeef0cfc2 100644 --- a/core/modules/taxonomy/src/Form/OverviewTerms.php +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php @@ -339,7 +339,7 @@ class OverviewTerms extends FormBase { ); $form['actions']['reset_alphabetical'] = array( '#type' => 'submit', - '#submit' => array(array($this, 'submitReset')), + '#submit' => array('::submitReset'), '#value' => $this->t('Reset to alphabetical'), ); } diff --git a/core/modules/taxonomy/src/VocabularyForm.php b/core/modules/taxonomy/src/VocabularyForm.php index d34d3e2464d..5a70f8d8b1a 100644 --- a/core/modules/taxonomy/src/VocabularyForm.php +++ b/core/modules/taxonomy/src/VocabularyForm.php @@ -97,7 +97,7 @@ class VocabularyForm extends EntityForm { // the submit button has custom submit handlers. if ($this->moduleHandler->moduleExists('language')) { array_unshift($actions['submit']['#submit'], 'language_configuration_element_submit'); - array_unshift($actions['submit']['#submit'], array($this, 'languageConfigurationSubmit')); + array_unshift($actions['submit']['#submit'], '::languageConfigurationSubmit'); } // We cannot leverage the regular submit handler definition because we // have button-specific ones here. Hence we need to explicitly set it for diff --git a/core/modules/user/src/Form/UserLoginForm.php b/core/modules/user/src/Form/UserLoginForm.php index 1a8736cab20..25511a82ccc 100644 --- a/core/modules/user/src/Form/UserLoginForm.php +++ b/core/modules/user/src/Form/UserLoginForm.php @@ -105,9 +105,9 @@ class UserLoginForm extends FormBase { $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Log in')); - $form['#validate'][] = array($this, 'validateName'); - $form['#validate'][] = array($this, 'validateAuthentication'); - $form['#validate'][] = array($this, 'validateFinal'); + $form['#validate'][] = '::validateName'; + $form['#validate'][] = '::validateAuthentication'; + $form['#validate'][] = '::validateFinal'; return $form; } diff --git a/core/modules/user/src/ProfileForm.php b/core/modules/user/src/ProfileForm.php index 998d29b2a88..e1196931c51 100644 --- a/core/modules/user/src/ProfileForm.php +++ b/core/modules/user/src/ProfileForm.php @@ -37,7 +37,7 @@ class ProfileForm extends AccountForm { $user = $this->currentUser(); $element['delete']['#type'] = 'submit'; $element['delete']['#value'] = $this->t('Cancel account'); - $element['delete']['#submit'] = array(array($this, 'editCancelSubmit')); + $element['delete']['#submit'] = array('::editCancelSubmit'); $element['delete']['#access'] = $account->id() > 1 && (($account->id() == $user->id() && $user->hasPermission('cancel account')) || $user->hasPermission('administer users')); return $element; diff --git a/core/modules/views_ui/src/Form/AdvancedSettingsForm.php b/core/modules/views_ui/src/Form/AdvancedSettingsForm.php index 56254a25071..44a2f36e2a8 100644 --- a/core/modules/views_ui/src/Form/AdvancedSettingsForm.php +++ b/core/modules/views_ui/src/Form/AdvancedSettingsForm.php @@ -46,7 +46,7 @@ class AdvancedSettingsForm extends ConfigFormBase { $form['cache']['clear_cache'] = array( '#type' => 'submit', '#value' => $this->t("Clear Views' cache"), - '#submit' => array(array($this, 'cacheSubmit')), + '#submit' => array('::cacheSubmit'), ); $form['debug'] = array( diff --git a/core/modules/views_ui/src/ViewAddForm.php b/core/modules/views_ui/src/ViewAddForm.php index 8717ff93a10..78fb0490825 100644 --- a/core/modules/views_ui/src/ViewAddForm.php +++ b/core/modules/views_ui/src/ViewAddForm.php @@ -153,9 +153,7 @@ class ViewAddForm extends ViewFormBase { $actions['cancel'] = array( '#type' => 'submit', '#value' => $this->t('Cancel'), - '#submit' => array( - array($this, 'cancel'), - ), + '#submit' => array('::cancel'), '#limit_validation_errors' => array(), ); return $actions; diff --git a/core/modules/views_ui/src/ViewDuplicateForm.php b/core/modules/views_ui/src/ViewDuplicateForm.php index e817e36263b..c081b3066c6 100644 --- a/core/modules/views_ui/src/ViewDuplicateForm.php +++ b/core/modules/views_ui/src/ViewDuplicateForm.php @@ -58,9 +58,7 @@ class ViewDuplicateForm extends ViewFormBase { $actions['submit'] = array( '#type' => 'submit', '#value' => $this->t('Duplicate'), - '#submit' => array( - array($this, 'submit'), - ), + '#submit' => array('::submit'), ); return $actions; } diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php index 6d42b52ba59..1c9522eaf1c 100644 --- a/core/modules/views_ui/src/ViewEditForm.php +++ b/core/modules/views_ui/src/ViewEditForm.php @@ -240,9 +240,7 @@ class ViewEditForm extends ViewFormBase { $actions['cancel'] = array( '#type' => 'submit', '#value' => $this->t('Cancel'), - '#submit' => array( - array($this, 'cancel'), - ), + '#submit' => array('::cancel'), ); if ($this->entity->isLocked()) { $actions['submit']['#access'] = FALSE; @@ -418,7 +416,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Enable !display_title', array('!display_title' => $display_title)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDisplayEnable'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDisplayEnable', '::submitDelayDestination'), '#prefix' => '
  • ', "#suffix" => '
  • ', ); @@ -443,7 +441,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Duplicate !display_title', array('!display_title' => $display_title)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDisplayDuplicate'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDisplayDuplicate', '::submitDelayDestination'), '#prefix' => '
  • ', "#suffix" => '
  • ', ); @@ -453,7 +451,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Delete !display_title', array('!display_title' => $display_title)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDisplayDelete'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDisplayDelete', '::submitDelayDestination'), '#prefix' => '
  • ', "#suffix" => '
  • ', ); @@ -467,7 +465,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Duplicate as !type', array('!type' => $label)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDuplicateDisplayAsType'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDuplicateDisplayAsType', '::submitDelayDestination'), '#prefix' => '
  • ', '#suffix' => '
  • ', ); @@ -478,7 +476,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Undo delete of !display_title', array('!display_title' => $display_title)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDisplayUndoDelete'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDisplayUndoDelete', '::submitDelayDestination'), '#prefix' => '
  • ', "#suffix" => '
  • ', ); @@ -488,7 +486,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Disable !display_title', array('!display_title' => $display_title)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDisplayDisable'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDisplayDisable', '::submitDelayDestination'), '#prefix' => '
  • ', "#suffix" => '
  • ', ); @@ -760,7 +758,7 @@ class ViewEditForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Add !display', array('!display' => $label)), '#limit_validation_errors' => array(), - '#submit' => array(array($this, 'submitDisplayAdd'), array($this, 'submitDelayDestination')), + '#submit' => array('::submitDisplayAdd', '::submitDelayDestination'), '#attributes' => array('class' => array('add-display')), // Allow JavaScript to remove the 'Add ' prefix from the button label when // placing the button in a "Add" dropdown menu. diff --git a/core/modules/views_ui/src/ViewPreviewForm.php b/core/modules/views_ui/src/ViewPreviewForm.php index b5ecd9c402c..9ba3b991688 100644 --- a/core/modules/views_ui/src/ViewPreviewForm.php +++ b/core/modules/views_ui/src/ViewPreviewForm.php @@ -112,7 +112,7 @@ class ViewPreviewForm extends ViewFormBase { '#type' => 'submit', '#value' => $this->t('Update preview'), '#attributes' => array('class' => array('arguments-preview')), - '#submit' => array(array($this, 'submitPreview')), + '#submit' => array('::submitPreview'), '#id' => 'preview-submit', '#ajax' => array( 'path' => 'admin/structure/views/view/' . $view->id() . '/preview/' . $this->displayID, diff --git a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php index 4cd45e770f7..3f391dd65a5 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php @@ -7,7 +7,9 @@ namespace Drupal\Tests\Core\Form; +use Drupal\Core\Form\FormInterface; use Drupal\Core\Form\FormState; +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -218,6 +220,38 @@ class FormStateTest extends UnitTestCase { $this->assertSame($expected, $form_state->getValues()); } + /** + * @covers ::prepareCallback() + */ + public function testPrepareCallbackValidMethod() { + $form_state = new FormState(); + $form_state['build_info']['callback_object'] = new PrepareCallbackTestForm(); + $processed_callback = $form_state->prepareCallback('::buildForm'); + $this->assertEquals(array($form_state['build_info']['callback_object'], 'buildForm'), $processed_callback); + } + + /** + * @covers ::prepareCallback() + */ + public function testPrepareCallbackInValidMethod() { + $form_state = new FormState(); + $form_state['build_info']['callback_object'] = new PrepareCallbackTestForm(); + $processed_callback = $form_state->prepareCallback('not_a_method'); + // The callback was not changed as no such method exists. + $this->assertEquals('not_a_method', $processed_callback); + } + + /** + * @covers ::prepareCallback() + */ + public function testPrepareCallbackArray() { + $form_state = new FormState(); + $form_state['build_info']['callback_object'] = new PrepareCallbackTestForm(); + $callback = array($form_state['build_info']['callback_object'], 'buildForm'); + $processed_callback = $form_state->prepareCallback($callback); + $this->assertEquals($callback, $processed_callback); + } + public function providerTestSetValue() { $data = array(); $data[] = array( @@ -315,3 +349,16 @@ class FormStateTest extends UnitTestCase { } } + +/** + * A test form used for the prepareCallback() tests. + */ +class PrepareCallbackTestForm implements FormInterface { + public function getFormId() { + return 'test_form'; + } + + public function buildForm(array $form, FormStateInterface $form_state) {} + public function validateForm(array &$form, FormStateInterface $form_state) { } + public function submitForm(array &$form, FormStateInterface $form_state) { } +} diff --git a/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php b/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php index 9a7833d92d1..e1c9462e3ed 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php @@ -202,13 +202,16 @@ class FormSubmitterTest extends UnitTestCase { */ public function testExecuteSubmitHandlers() { $form_submitter = $this->getFormSubmitter(); - $mock = $this->getMock('stdClass', array('submit_handler', 'hash_submit')); + $mock = $this->getMock('stdClass', array('submit_handler', 'hash_submit', 'simple_string_submit')); $mock->expects($this->once()) ->method('submit_handler') ->with($this->isType('array'), $this->isInstanceOf('Drupal\Core\Form\FormStateInterface')); $mock->expects($this->once()) ->method('hash_submit') ->with($this->isType('array'), $this->isInstanceOf('Drupal\Core\Form\FormStateInterface')); + $mock->expects($this->once()) + ->method('simple_string_submit') + ->with($this->isType('array'), $this->isInstanceOf('Drupal\Core\Form\FormStateInterface')); $form = array(); $form_state = new FormState(); @@ -220,6 +223,12 @@ class FormSubmitterTest extends UnitTestCase { // $form_state submit handlers will supersede $form handlers. $form_state['submit_handlers'][] = array($mock, 'submit_handler'); $form_submitter->executeSubmitHandlers($form, $form_state); + + // Methods directly on the form object can be specified as a string. + $form_state = new FormState(); + $form_state['build_info']['callback_object'] = $mock; + $form_state['submit_handlers'][] = '::simple_string_submit'; + $form_submitter->executeSubmitHandlers($form, $form_state); } /**