Issue #2309323 by Berdir, tim.plunkett: Allow #submit and #validate to be specified as methods of the form object.

8.0.x
webchick 2014-08-23 14:18:18 -07:00
parent 37586d9773
commit 6a6e601d4a
46 changed files with 164 additions and 115 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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().
*

View File

@ -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);
}

View File

@ -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));
}
}
}

View File

@ -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));
}
}

View File

@ -104,7 +104,7 @@ class SiteSettingsForm extends FormBase {
array('driver'),
array($default_driver),
),
'#submit' => array(array($this, 'submitForm')),
'#submit' => array('::submitForm'),
);
$form['errors'] = array();

View File

@ -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',
),
);

View File

@ -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;

View File

@ -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' => '<div id="edit-config-type-wrapper">',
'#suffix' => '</div>',
'#ajax' => array(
'callback' => array($this, 'updateExport'),
'callback' => '::updateExport',
'wrapper' => 'edit-export-wrapper',
),
);

View File

@ -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;
}

View File

@ -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;

View File

@ -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',
),
);

View File

@ -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',
),
);

View File

@ -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;
}

View File

@ -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. <a href="@container">Add container</a> or <a href="@forum">Add forum</a>.', array(
'@container' => $this->url('forum.add_container'),
'@forum' => $this->url('forum.add_forum')

View File

@ -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;

View File

@ -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;
}

View File

@ -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'),
);
}

View File

@ -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');

View File

@ -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;
}

View File

@ -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;

View File

@ -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')),
);

View File

@ -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'),
),
);
}

View File

@ -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'));
}

View File

@ -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 = '<p>' . t('Last run: %cron-last ago.', array('%cron-last' => $this->dateFormatter->formatInterval(REQUEST_TIME - $this->state->get('system.cron_last')))) . '</p>';

View File

@ -135,7 +135,7 @@ abstract class DateFormatFormBase extends EntityForm {
'#default_value' => '',
'#field_suffix' => ' <small id="edit-date-format-suffix"></small>',
'#ajax' => array(
'callback' => array($this, 'dateTimeLookup'),
'callback' => '::dateTimeLookup',
'event' => 'keyup',
'progress' => array('type' => 'throbber', 'message' => NULL),
),

View File

@ -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(

View File

@ -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;
}

View File

@ -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',
),
);

View File

@ -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(

View File

@ -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') {

View File

@ -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 {

View File

@ -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',

View File

@ -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',

View File

@ -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'),
);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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(

View File

@ -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;

View File

@ -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;
}

View File

@ -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' => '<li class="enable">',
"#suffix" => '</li>',
);
@ -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' => '<li class="duplicate">',
"#suffix" => '</li>',
);
@ -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' => '<li class="delete">',
"#suffix" => '</li>',
);
@ -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' => '<li class="duplicate">',
'#suffix' => '</li>',
);
@ -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' => '<li class="undo-delete">',
"#suffix" => '</li>',
);
@ -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' => '<li class="disable">',
"#suffix" => '</li>',
);
@ -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.

View File

@ -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,

View File

@ -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) { }
}

View File

@ -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);
}
/**