Commit ee6ddbe8 authored by alexpott's avatar alexpott

Issue #2332389 by tim.plunkett: Finish adding methods to FormStateInterface.

parent fe85f9be
...@@ -806,12 +806,9 @@ function install_tasks_to_display($install_state) { ...@@ -806,12 +806,9 @@ function install_tasks_to_display($install_state) {
function install_get_form($form_id, array &$install_state) { function install_get_form($form_id, array &$install_state) {
// Ensure the form will not redirect, since install_run_tasks() uses a custom // Ensure the form will not redirect, since install_run_tasks() uses a custom
// redirection logic. // redirection logic.
$form_state = new FormState(array( $form_state = (new FormState())
'build_info' => array( ->addBuildInfo('args', [&$install_state])
'args' => array(&$install_state), ->disableRedirect();
),
'no_redirect' => TRUE,
));
$form_builder = \Drupal::formBuilder(); $form_builder = \Drupal::formBuilder();
if ($install_state['interactive']) { if ($install_state['interactive']) {
$form = $form_builder->buildForm($form_id, $form_state); $form = $form_builder->buildForm($form_id, $form_state);
...@@ -827,7 +824,7 @@ function install_get_form($form_id, array &$install_state) { ...@@ -827,7 +824,7 @@ function install_get_form($form_id, array &$install_state) {
// values taken from the installation state. // values taken from the installation state.
$install_form_id = $form_builder->getFormId($form_id, $form_state); $install_form_id = $form_builder->getFormId($form_id, $form_state);
if (!empty($install_state['forms'][$install_form_id])) { if (!empty($install_state['forms'][$install_form_id])) {
$form_state->set('values', $install_state['forms'][$install_form_id]); $form_state->setValues($install_state['forms'][$install_form_id]);
} }
$form_builder->submitForm($form_id, $form_state); $form_builder->submitForm($form_id, $form_state);
......
...@@ -356,9 +356,8 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form ...@@ -356,9 +356,8 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form
foreach ($this->getVisibilityConditions() as $condition_id => $condition) { foreach ($this->getVisibilityConditions() as $condition_id => $condition) {
// Allow the condition to validate the form. // Allow the condition to validate the form.
$condition_values = new FormState(array( $condition_values = (new FormState())
'values' => $form_state->getValue(array('visibility', $condition_id)), ->setValues($form_state->getValue(['visibility', $condition_id]));
));
$condition->validateConfigurationForm($form, $condition_values); $condition->validateConfigurationForm($form, $condition_values);
// Update the original form values. // Update the original form values.
$form_state->setValue(array('visibility', $condition_id), $condition_values['values']); $form_state->setValue(array('visibility', $condition_id), $condition_values['values']);
...@@ -389,9 +388,8 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -389,9 +388,8 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['cache'] = $form_state->getValue('cache'); $this->configuration['cache'] = $form_state->getValue('cache');
foreach ($this->getVisibilityConditions() as $condition_id => $condition) { foreach ($this->getVisibilityConditions() as $condition_id => $condition) {
// Allow the condition to submit the form. // Allow the condition to submit the form.
$condition_values = new FormState(array( $condition_values = (new FormState())
'values' => $form_state->getValue(array('visibility', $condition_id)), ->setValues($form_state->getValue(['visibility', $condition_id]));
));
$condition->submitConfigurationForm($form, $condition_values); $condition->submitConfigurationForm($form, $condition_values);
// Update the original form values. // Update the original form values.
$form_state->setValue(array('visibility', $condition_id), $condition_values['values']); $form_state->setValue(array('visibility', $condition_id), $condition_values['values']);
......
...@@ -49,11 +49,7 @@ public function getForm(EntityInterface $entity, $operation = 'default', array $ ...@@ -49,11 +49,7 @@ public function getForm(EntityInterface $entity, $operation = 'default', array $
$form_object = $this->entityManager->getFormObject($entity->getEntityTypeId(), $operation); $form_object = $this->entityManager->getFormObject($entity->getEntityTypeId(), $operation);
$form_object->setEntity($entity); $form_object->setEntity($entity);
$form_state = new FormState($form_state_additions); $form_state = (new FormState())->setFormState($form_state_additions);
$form_state['build_info']['callback_object'] = $form_object;
$form_state['build_info']['base_form_id'] = $form_object->getBaseFormID();
$form_state['build_info'] += array('args' => array());
return $this->formBuilder->buildForm($form_object, $form_state); return $this->formBuilder->buildForm($form_object, $form_state);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
/** /**
* Provides an interface for a Form that has a base form ID. * Provides an interface for a Form that has a base form ID.
* *
* This will become the $form_state['build_info']['base_form_id'] used to * This will become the $form_state->getBaseInfo()['base_form_id'] used to
* generate the name of hook_form_BASE_FORM_ID_alter(). * generate the name of hook_form_BASE_FORM_ID_alter().
*/ */
interface BaseFormIdInterface extends FormInterface { interface BaseFormIdInterface extends FormInterface {
......
...@@ -157,7 +157,7 @@ public function getFormId($form_arg, FormStateInterface &$form_state) { ...@@ -157,7 +157,7 @@ public function getFormId($form_arg, FormStateInterface &$form_state) {
} }
// Add the $form_arg as the callback object and determine the form ID. // Add the $form_arg as the callback object and determine the form ID.
$form_state->addBuildInfo('callback_object', $form_arg); $form_state->setFormObject($form_arg);
if ($form_arg instanceof BaseFormIdInterface) { if ($form_arg instanceof BaseFormIdInterface) {
$form_state->addBuildInfo('base_form_id', $form_arg->getBaseFormID()); $form_state->addBuildInfo('base_form_id', $form_arg->getBaseFormID());
} }
...@@ -188,7 +188,7 @@ public function buildForm($form_id, FormStateInterface &$form_state) { ...@@ -188,7 +188,7 @@ public function buildForm($form_id, FormStateInterface &$form_state) {
$input = $form_state->getUserInput(); $input = $form_state->getUserInput();
if (!isset($input)) { if (!isset($input)) {
$request = $this->requestStack->getCurrentRequest(); $request = $this->requestStack->getCurrentRequest();
$input = $form_state['method'] == 'get' ? $request->query->all() : $request->request->all(); $input = $form_state->isMethodType('get') ? $request->query->all() : $request->request->all();
$form_state->setUserInput($input); $form_state->setUserInput($input);
} }
...@@ -227,7 +227,7 @@ public function buildForm($form_id, FormStateInterface &$form_state) { ...@@ -227,7 +227,7 @@ public function buildForm($form_id, FormStateInterface &$form_state) {
// self::setCache() removes uncacheable $form_state keys (see properties // self::setCache() removes uncacheable $form_state keys (see properties
// in \Drupal\Core\Form\FormState) in order for multi-step forms to work // in \Drupal\Core\Form\FormState) in order for multi-step forms to work
// properly. This means that form processing logic for single-step forms // properly. This means that form processing logic for single-step forms
// using $form_state['cache'] may depend on data stored in those keys // using $form_state->isCached() may depend on data stored in those keys
// during self::retrieveForm()/self::prepareForm(), but form processing // during self::retrieveForm()/self::prepareForm(), but form processing
// should not depend on whether the form is cached or not, so $form_state // should not depend on whether the form is cached or not, so $form_state
// is adjusted to match what it would be after a // is adjusted to match what it would be after a
...@@ -239,7 +239,9 @@ public function buildForm($form_id, FormStateInterface &$form_state) { ...@@ -239,7 +239,9 @@ public function buildForm($form_id, FormStateInterface &$form_state) {
// - temporary: Any assigned data is expected to survives within the same // - temporary: Any assigned data is expected to survives within the same
// page request. // page request.
if ($check_cache) { if ($check_cache) {
$cache_form_state = $form_state->getCacheableArray(array('always_process', 'temporary')); $cache_form_state = $form_state->getCacheableArray();
$cache_form_state['always_process'] = $form_state->getAlwaysProcess();
$cache_form_state['temporary'] = $form_state->getTemporary();
$form_state = $form_state_before_retrieval; $form_state = $form_state_before_retrieval;
$form_state->setFormState($cache_form_state); $form_state->setFormState($cache_form_state);
} }
...@@ -280,6 +282,8 @@ public function buildForm($form_id, FormStateInterface &$form_state) { ...@@ -280,6 +282,8 @@ public function buildForm($form_id, FormStateInterface &$form_state) {
*/ */
public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL) { public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL) {
$form = $this->retrieveForm($form_id, $form_state); $form = $this->retrieveForm($form_id, $form_state);
// All rebuilt forms will be cached.
$form_state->setCached();
// If only parts of the form will be returned to the browser (e.g., Ajax or // If only parts of the form will be returned to the browser (e.g., Ajax or
// RIA clients), re-use the old #build_id to not require client-side code to // RIA clients), re-use the old #build_id to not require client-side code to
...@@ -288,7 +292,8 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form ...@@ -288,7 +292,8 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form
// build's data in the form cache; also allowing the user to go back to an // build's data in the form cache; also allowing the user to go back to an
// earlier build, make changes, and re-submit. // earlier build, make changes, and re-submit.
// @see self::prepareForm() // @see self::prepareForm()
if (isset($old_form['#build_id']) && !empty($form_state['rebuild_info']['copy']['#build_id'])) { $rebuild_info = $form_state->getRebuildInfo();
if (isset($old_form['#build_id']) && !empty($rebuild_info['copy']['#build_id'])) {
$form['#build_id'] = $old_form['#build_id']; $form['#build_id'] = $old_form['#build_id'];
} }
else { else {
...@@ -298,7 +303,7 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form ...@@ -298,7 +303,7 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form
// #action defaults to request_uri(), but in case of Ajax and other partial // #action defaults to request_uri(), but in case of Ajax and other partial
// rebuilds, the form is submitted to an alternate URL, and the original // rebuilds, the form is submitted to an alternate URL, and the original
// #action needs to be retained. // #action needs to be retained.
if (isset($old_form['#action']) && !empty($form_state['rebuild_info']['copy']['#action'])) { if (isset($old_form['#action']) && !empty($rebuild_info['copy']['#action'])) {
$form['#action'] = $old_form['#action']; $form['#action'] = $old_form['#action'];
} }
...@@ -308,13 +313,13 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form ...@@ -308,13 +313,13 @@ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form
// cached is the $form structure before it passes through // cached is the $form structure before it passes through
// self::doBuildForm(), so we need to do it here. // self::doBuildForm(), so we need to do it here.
// @todo For Drupal 8, find a way to avoid this code duplication. // @todo For Drupal 8, find a way to avoid this code duplication.
if (empty($form_state['no_cache'])) { if ($form_state->isCached()) {
$this->setCache($form['#build_id'], $form, $form_state); $this->setCache($form['#build_id'], $form, $form_state);
} }
// Clear out all group associations as these might be different when // Clear out all group associations as these might be different when
// re-rendering the form. // re-rendering the form.
$form_state->set('groups', array()); $form_state->setGroups([]);
// Return a fully built form that is ready for rendering. // Return a fully built form that is ready for rendering.
return $this->doBuildForm($form_id, $form, $form_state); return $this->doBuildForm($form_id, $form, $form_state);
...@@ -338,7 +343,8 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state) ...@@ -338,7 +343,8 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state)
* {@inheritdoc} * {@inheritdoc}
*/ */
public function submitForm($form_arg, FormStateInterface &$form_state) { public function submitForm($form_arg, FormStateInterface &$form_state) {
if (!isset($form_state['build_info']['args'])) { $build_info = $form_state->getBuildInfo();
if (empty($build_info['args'])) {
$args = func_get_args(); $args = func_get_args();
// Remove $form and $form_state from the arguments. // Remove $form and $form_state from the arguments.
unset($args[0], $args[1]); unset($args[0], $args[1]);
...@@ -351,15 +357,15 @@ public function submitForm($form_arg, FormStateInterface &$form_state) { ...@@ -351,15 +357,15 @@ public function submitForm($form_arg, FormStateInterface &$form_state) {
// there). // there).
$form_state->setUserInput($form_state->getValues()); $form_state->setUserInput($form_state->getValues());
$form_state->set('programmed', TRUE); $form_state->setProgrammed();
$form_id = $this->getFormId($form_arg, $form_state); $form_id = $this->getFormId($form_arg, $form_state);
$form = $this->retrieveForm($form_id, $form_state); $form = $this->retrieveForm($form_id, $form_state);
// Programmed forms are always submitted. // Programmed forms are always submitted.
$form_state->set('submitted', TRUE); $form_state->setSubmitted();
// Reset form validation. // Reset form validation.
$form_state->set('must_validate', TRUE); $form_state->setValidationEnforced();
$form_state->clearErrors(); $form_state->clearErrors();
$this->prepareForm($form_id, $form, $form_state); $this->prepareForm($form_id, $form, $form_state);
...@@ -376,9 +382,10 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) { ...@@ -376,9 +382,10 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) {
// We save two copies of the incoming arguments: one for modules to use // We save two copies of the incoming arguments: one for modules to use
// when mapping form ids to constructor functions, and another to pass to // when mapping form ids to constructor functions, and another to pass to
// the constructor function itself. // the constructor function itself.
$args = $form_state['build_info']['args']; $build_info = $form_state->getBuildInfo();
$args = $build_info['args'];
$callback = array($form_state['build_info']['callback_object'], 'buildForm'); $callback = [$form_state->getFormObject(), 'buildForm'];
$form = array(); $form = array();
// Assign a default CSS class name based on $form_id. // Assign a default CSS class name based on $form_id.
...@@ -386,8 +393,8 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) { ...@@ -386,8 +393,8 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) {
// form constructor function to override or remove the default class. // form constructor function to override or remove the default class.
$form['#attributes']['class'][] = Html::getClass($form_id); $form['#attributes']['class'][] = Html::getClass($form_id);
// Same for the base form ID, if any. // Same for the base form ID, if any.
if (isset($form_state['build_info']['base_form_id'])) { if (isset($build_info['base_form_id'])) {
$form['#attributes']['class'][] = Html::getClass($form_state['build_info']['base_form_id']); $form['#attributes']['class'][] = Html::getClass($build_info['base_form_id']);
} }
// We need to pass $form_state by reference in order for forms to modify it, // We need to pass $form_state by reference in order for forms to modify it,
...@@ -410,10 +417,10 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) { ...@@ -410,10 +417,10 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function processForm($form_id, &$form, FormStateInterface &$form_state) { public function processForm($form_id, &$form, FormStateInterface &$form_state) {
$form_state->set('values', array()); $form_state->setValues([]);
// With GET, these forms are always submitted if requested. // With GET, these forms are always submitted if requested.
if ($form_state['method'] == 'get' && !empty($form_state['always_process'])) { if ($form_state->isMethodType('get') && $form_state->getAlwaysProcess()) {
$input = $form_state->getUserInput(); $input = $form_state->getUserInput();
if (!isset($input['form_build_id'])) { if (!isset($input['form_build_id'])) {
$input['form_build_id'] = $form['#build_id']; $input['form_build_id'] = $form['#build_id'];
...@@ -435,7 +442,7 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -435,7 +442,7 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) {
$form = $this->doBuildForm($form_id, $form, $form_state); $form = $this->doBuildForm($form_id, $form, $form_state);
// Only process the input if we have a correct form submission. // Only process the input if we have a correct form submission.
if ($form_state['process_input']) { if ($form_state->isProcessingInput()) {
// Form constructors may explicitly set #token to FALSE when cross site // Form constructors may explicitly set #token to FALSE when cross site
// request forgery is irrelevant to the form, such as search forms. // request forgery is irrelevant to the form, such as search forms.
if (isset($form['#token']) && $form['#token'] === FALSE) { if (isset($form['#token']) && $form['#token'] === FALSE) {
...@@ -447,8 +454,9 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -447,8 +454,9 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) {
// submit button is not taken account. Therefore, check whether there is // submit button is not taken account. Therefore, check whether there is
// exactly one submit button in the form, and if so, automatically use it // exactly one submit button in the form, and if so, automatically use it
// as triggering_element. // as triggering_element.
if ($form_state['programmed'] && !isset($form_state['triggering_element']) && count($form_state['buttons']) == 1) { $buttons = $form_state->getButtons();
$form_state->set('triggering_element', reset($form_state['buttons'])); if ($form_state->isProgrammed() && !$form_state->getTriggeringElement() && count($buttons) == 1) {
$form_state->setTriggeringElement(reset($buttons));
} }
$this->formValidator->validateForm($form_id, $form, $form_state); $this->formValidator->validateForm($form_id, $form, $form_state);
...@@ -462,35 +470,35 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -462,35 +470,35 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) {
Html::resetSeenIds(); Html::resetSeenIds();
} }
if (!$form_state['rebuild'] && !FormState::hasAnyErrors()) { if (!$form_state->isRebuilding() && !FormState::hasAnyErrors()) {
if ($submit_response = $this->formSubmitter->doSubmitForm($form, $form_state)) { if ($submit_response = $this->formSubmitter->doSubmitForm($form, $form_state)) {
return $submit_response; return $submit_response;
} }
} }
// Don't rebuild or cache form submissions invoked via self::submitForm(). // Don't rebuild or cache form submissions invoked via self::submitForm().
if (!empty($form_state['programmed'])) { if ($form_state->isProgrammed()) {
return; return;
} }
// If $form_state['rebuild'] has been set and input has been processed // If $form_state->isRebuilding() has been set and input has been processed
// without validation errors, we are in a multi-step workflow that is not // without validation errors, we are in a multi-step workflow that is not
// yet complete. A new $form needs to be constructed based on the changes // yet complete. A new $form needs to be constructed based on the changes
// made to $form_state during this request. Normally, a submit handler // made to $form_state during this request. Normally, a submit handler
// sets $form_state['rebuild'] if a fully executed form requires another // sets $form_state->isRebuilding() if a fully executed form requires
// step. However, for forms that have not been fully executed (e.g., Ajax // another step. However, for forms that have not been fully executed
// submissions triggered by non-buttons), there is no submit handler to // (e.g., Ajax submissions triggered by non-buttons), there is no submit
// set $form_state['rebuild']. It would not make sense to redisplay the // handler to set $form_state->isRebuilding(). It would not make sense to
// identical form without an error for the user to correct, so we also // redisplay the identical form without an error for the user to correct,
// rebuild error-free non-executed forms, regardless of // so we also rebuild error-free non-executed forms, regardless of
// $form_state['rebuild']. // $form_state->isRebuilding().
// @todo Simplify this logic; considering Ajax and non-HTML front-ends, // @todo Simplify this logic; considering Ajax and non-HTML front-ends,
// along with element-level #submit properties, it makes no sense to // along with element-level #submit properties, it makes no sense to
// have divergent form execution based on whether the triggering element // have divergent form execution based on whether the triggering element
// has #executes_submit_callback set to TRUE. // has #executes_submit_callback set to TRUE.
if (($form_state['rebuild'] || !$form_state['executed']) && !FormState::hasAnyErrors()) { if (($form_state->isRebuilding() || !$form_state->isExecuted()) && !FormState::hasAnyErrors()) {
// Form building functions (e.g., self::handleInputElement()) may use // Form building functions (e.g., self::handleInputElement()) may use
// $form_state['rebuild'] to determine if they are running in the // $form_state->isRebuilding() to determine if they are running in the
// context of a rebuild, so ensure it is set. // context of a rebuild, so ensure it is set.
$form_state->setRebuild(); $form_state->setRebuild();
$form = $this->rebuildForm($form_id, $form_state, $form); $form = $this->rebuildForm($form_id, $form_state, $form);
...@@ -498,13 +506,13 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -498,13 +506,13 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) {
} }
// After processing the form, the form builder or a #process callback may // After processing the form, the form builder or a #process callback may
// have set $form_state['cache'] to indicate that the form and form state // have called $form_state->setCached() to indicate that the form and form
// shall be cached. But the form may only be cached if the 'no_cache' // state shall be cached. But the form may only be cached if
// property is not set to TRUE. Only cache $form as it was prior to // $form_state->disableCache() is not called. Only cache $form as it was
// self::doBuildForm(), because self::doBuildForm() must run for each // prior to self::doBuildForm(), because self::doBuildForm() must run for
// request to accommodate new user input. Rebuilt forms are not cached here, // each request to accommodate new user input. Rebuilt forms are not cached
// because self::rebuildForm() already takes care of that. // here, because self::rebuildForm() already takes care of that.
if (!$form_state['rebuild'] && $form_state['cache'] && empty($form_state['no_cache'])) { if (!$form_state->isRebuilding() && $form_state->isCached()) {
$this->setCache($form['#build_id'], $unprocessed_form, $form_state); $this->setCache($form['#build_id'], $unprocessed_form, $form_state);
} }
} }
...@@ -516,10 +524,9 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -516,10 +524,9 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) {
$user = $this->currentUser(); $user = $this->currentUser();
$form['#type'] = 'form'; $form['#type'] = 'form';
$form_state->set('programmed', isset($form_state['programmed']) ? $form_state['programmed'] : FALSE);
// Fix the form method, if it is 'get' in $form_state, but not in $form. // Fix the form method, if it is 'get' in $form_state, but not in $form.
if ($form_state->get('method') == 'get' && !isset($form['#method'])) { if ($form_state->isMethodType('get') && !isset($form['#method'])) {
$form['#method'] = 'get'; $form['#method'] = 'get';
} }
...@@ -551,7 +558,7 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -551,7 +558,7 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) {
// since tokens are session-bound and forms displayed to anonymous users are // since tokens are session-bound and forms displayed to anonymous users are
// very likely cached, we cannot assign a token for them. // very likely cached, we cannot assign a token for them.
// During installation, there is no $user yet. // During installation, there is no $user yet.
if ($user && $user->isAuthenticated() && !$form_state['programmed']) { if ($user && $user->isAuthenticated() && !$form_state->isProgrammed()) {
// Form constructors may explicitly set #token to FALSE when cross site // Form constructors may explicitly set #token to FALSE when cross site
// request forgery is irrelevant to the form, such as search forms. // request forgery is irrelevant to the form, such as search forms.
if (isset($form['#token']) && $form['#token'] === FALSE) { if (isset($form['#token']) && $form['#token'] === FALSE) {
...@@ -592,22 +599,23 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) { ...@@ -592,22 +599,23 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) {
$form['#validate'][] = '::validateForm'; $form['#validate'][] = '::validateForm';
$form['#submit'][] = '::submitForm'; $form['#submit'][] = '::submitForm';
$build_info = $form_state->getBuildInfo();
// If no #theme has been set, automatically apply theme suggestions. // If no #theme has been set, automatically apply theme suggestions.
// theme_form() itself is in #theme_wrappers and not #theme. Therefore, the // theme_form() itself is in #theme_wrappers and not #theme. Therefore, the
// #theme function only has to care for rendering the inner form elements, // #theme function only has to care for rendering the inner form elements,
// not the form itself. // not the form itself.
if (!isset($form['#theme'])) { if (!isset($form['#theme'])) {
$form['#theme'] = array($form_id); $form['#theme'] = array($form_id);
if (isset($form_state['build_info']['base_form_id'])) { if (isset($build_info['base_form_id'])) {
$form['#theme'][] = $form_state['build_info']['base_form_id']; $form['#theme'][] = $build_info['base_form_id'];
} }
} }
// Invoke hook_form_alter(), hook_form_BASE_FORM_ID_alter(), and // Invoke hook_form_alter(), hook_form_BASE_FORM_ID_alter(), and
// hook_form_FORM_ID_alter() implementations. // hook_form_FORM_ID_alter() implementations.
$hooks = array('form'); $hooks = array('form');
if (isset($form_state['build_info']['base_form_id'])) { if (isset($build_info['base_form_id'])) {
$hooks[] = 'form_' . $form_state['build_info']['base_form_id']; $hooks[] = 'form_' . $build_info['base_form_id'];
} }
$hooks[] = 'form_' . $form_id; $hooks[] = 'form_' . $form_id;
$this->moduleHandler->alter($hooks, $form, $form_state, $form_id); $this->moduleHandler->alter($hooks, $form, $form_state, $form_id);
...@@ -690,11 +698,11 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state ...@@ -690,11 +698,11 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
// for programmed forms coming from self::submitForm(), or if the form_id // for programmed forms coming from self::submitForm(), or if the form_id
// coming from the POST data is set and matches the current form_id. // coming from the POST data is set and matches the current form_id.
$input = $form_state->getUserInput(); $input = $form_state->getUserInput();
if ($form_state['programmed'] || (!empty($input) && (isset($input['form_id']) && ($input['form_id'] == $form_id)))) { if ($form_state->isProgrammed() || (!empty($input) && (isset($input['form_id']) && ($input['form_id'] == $form_id)))) {
$form_state->set('process_input', TRUE); $form_state->setProcessInput();
} }
else { else {
$form_state->set('process_input', FALSE); $form_state->setProcessInput(FALSE);
} }
// All form elements should have an #array_parents property. // All form elements should have an #array_parents property.
...@@ -791,14 +799,14 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state ...@@ -791,14 +799,14 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
// If there is a file element, we need to flip a flag so later the // If there is a file element, we need to flip a flag so later the
// form encoding can be set. // form encoding can be set.
if (isset($element['#type']) && $element['#type'] == 'file') { if (isset($element['#type']) && $element['#type'] == 'file') {
$form_state->set('has_file_element', TRUE); $form_state->setHasFileElement();
} }
// Final tasks for the form element after self::doBuildForm() has run for // Final tasks for the form element after self::doBuildForm() has run for
// all other elements. // all other elements.
if (isset($element['#type']) && $element['#type'] == 'form') { if (isset($element['#type']) && $element['#type'] == 'form') {
// If there is a file element, we set the form encoding. // If there is a file element, we set the form encoding.
if (isset($form_state['has_file_element'])) { if ($form_state->hasFileElement()) {
$element['#attributes']['enctype'] = 'multipart/form-data'; $element['#attributes']['enctype'] = 'multipart/form-data';
} }
...@@ -808,24 +816,26 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state ...@@ -808,24 +816,26 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
// though the user clicked the first button. Therefore, to be as // though the user clicked the first button. Therefore, to be as
// consistent as we can be across browsers, if no 'triggering_element' has // consistent as we can be across browsers, if no 'triggering_element' has
// been identified yet, default it to the first button. // been identified yet, default it to the first button.
if (!$form_state['programmed'] && !isset($form_state['triggering_element']) && !empty($form_state['buttons'])) { $buttons = $form_state->getButtons();
$form_state->set('triggering_element', $form_state['buttons'][0]); if (!$form_state->isProgrammed() && !$form_state->getTriggeringElement() && !empty($buttons)) {
$form_state->setTriggeringElement($buttons[0]);
} }
$triggering_element = $form_state->get('triggering_element'); $triggering_element = $form_state->getTriggeringElement();
// If the triggering element specifies "button-level" validation and // If the triggering element specifies "button-level" validation and
// submit handlers to run instead of the default form-level ones, then add // submit handlers to run instead of the default form-level ones, then add
// those to the form state. // those to the form state.
foreach (array('validate', 'submit') as $type) { if (isset($triggering_element['#validate'])) {
if (isset($triggering_element['#' . $type])) { $form_state->setValidateHandlers($triggering_element['#validate']);
$form_state->set($type . '_handlers', $triggering_element['#' . $type]); }
} if (isset($triggering_element['#submit'])) {
$form_state->setSubmitHandlers($triggering_element['#submit']);
} }
// If the triggering element executes submit handlers, then set the form // If the triggering element executes submit handlers, then set the form
// state key that's needed for those handlers to run. // state key that's needed for those handlers to run.
if (!empty($triggering_element['#executes_submit_callback'])) { if (!empty($triggering_element['#executes_submit_callback'])) {
$form_state->set('submitted', TRUE); $form_state->setSubmitted();
} }
// Special processing if the triggering element is a button. // Special processing if the triggering element is a button.
...@@ -899,7 +909,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$ ...@@ -899,7 +909,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
// #access=FALSE on an element usually allow access for some users, so forms // #access=FALSE on an element usually allow access for some users, so forms
// submitted with self::submitForm() may bypass access restriction and be // submitted with self::submitForm() may bypass access restriction and be
// treated as high-privilege users instead. // treated as high-privilege users instead.
$process_input = empty($element['#disabled']) && (($form_state['programmed'] && $form_state['programmed_bypass_access_check']) || ($form_state['process_input'] && (!isset($element['#access']) || $element['#access']))); $process_input = empty($element['#disabled']) && (($form_state->isProgrammed() && $form_state->isBypassingProgrammedAccessChecks()) || ($form_state->isProcessingInput() && (!isset($element['#access']) || $element['#access'])));
// Set the element's #value property. // Set the element's #value property.
if (!isset($element['#value']) && !array_key_exists('#value', $element)) { if (!isset($element['#value']) && !array_key_exists('#value', $element)) {
...@@ -925,7 +935,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$ ...@@ -925,7 +935,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
// use default values for the latter, if required. Programmatically // use default values for the latter, if required. Programmatically
// submitted forms can submit explicit NULL values when calling // submitted forms can submit explicit NULL values when calling
// self::submitForm() so we do not modify FormState::$input for them. // self::submitForm() so we do not modify FormState::$input for them.
if (!$input_exists && !$form_state['rebuild'] && !$form_state['programmed']) { if (!$input_exists && !$form_state->isRebuilding() && !$form_state->isProgrammed()) {
// Add the necessary parent keys to FormState::$input and sets the // Add the necessary parent keys to FormState::$input and sets the
// element's input value to NULL. // element's input value to NULL.
NestedArray::setValue($form_state->getUserInput(), $element['#parents'], NULL); NestedArray::setValue($form_state->getUserInput(), $element['#parents'], NULL);
...@@ -967,7 +977,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$ ...@@ -967,7 +977,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
if ($process_input) { if ($process_input) {
// Detect if the element triggered the submission via Ajax. // Detect if the element triggered the submission via Ajax.
if ($this->elementTriggeredScriptedSubmission($element, $form_state)) { if ($this->elementTriggeredScriptedSubmission($element, $form_state)) {
$form_state->set('triggering_element', $element); $form_state->setTriggeringElement($element);
} }
// If the form was submitted by the browser rather than via Ajax, then it // If the form was submitted by the browser rather than via Ajax, then it
...@@ -979,11 +989,11 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$ ...@@ -979,11 +989,11 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
// form_state_values_clean() and for the self::doBuildForm() code that // form_state_values_clean() and for the self::doBuildForm() code that
// handles a form submission containing no button information in // handles a form submission containing no button information in
// \Drupal::request()->request. // \Drupal::request()->request.
$buttons = $form_state->get('buttons'); $buttons = $form_state->getButtons();
$buttons[] = $element; $buttons[] = $element;
$form_state->set('buttons', $buttons); $form_state->setButtons($buttons);
if ($this->buttonWasClicked($element, $form_state)) { if ($this->buttonWasClicked($element, $form_state)) {
$form_state->set('triggering_element', $element); $form_state->setTriggeringElement($element);
} }
} }
} }
...@@ -1031,10 +1041,10 @@ protected function elementTriggeredScriptedSubmission($element, FormStateInterfa ...@@ -1031,10 +1041,10 @@ protected function elementTriggeredScriptedSubmission($element, FormStateInterfa
* textfield (self::doBuildForm() has extra code for that). * textfield (self::doBuildForm() has extra code for that).
* *
* Because this function contains only part of the logic needed to determine * Because this function contains only part of the logic needed to determine
* $form_state['triggering_element'], it should not be called from anywhere * $form_state->getTriggeringElement(), it should not be called from anywhere
* other than within the Form API. Form validation and submit handlers needing * other than within the Form API. Form validation and submit handlers needing
* to know which button was clicked should get that information from * to know which button was clicked should get that information from
* $form_state['triggering_element']. * $form_state->getTriggeringElement().
*/ */
protected function buttonWasClicked($element, FormStateInterface &$form_state) { protected function buttonWasClicked($element, FormStateInterface &$form_state) {
// First detect normal 'vanilla' button clicks. Traditionally, all standard // First detect normal 'vanilla' button clicks. Traditionally, all standard
......
...@@ -42,7 +42,7 @@ public function getFormId($form_arg, FormStateInterface &$form_state); ...@@ -42,7 +42,7 @@ public function getFormId($form_arg, FormStateInterface &$form_state);
* function. For example, the node_edit form requires that a node object is * function. For example, the node_edit form requires that a node object is
* passed in here when it is called. These are available to implementations * passed in here when it is called. These are available to implementations
* of hook_form_alter() and hook_form_FORM_ID_alter() as the array * of hook_form_alter() and hook_form_FORM_ID_alter() as the array
* $form_state['build_info']['args']. * $form_state->getBuildInfo()['args'].
* *
* @return array * @return array
* The form array. * The form array.
...@@ -79,10 +79,10 @@ public function buildForm($form_id, FormStateInterface &$form_state); ...@@ -79,10 +79,10 @@ public function buildForm($form_id, FormStateInterface &$form_state);
* This is the key function for making multi-step forms advance from step to * This is the key function for making multi-step forms advance from step to
* step. It is called by self::processForm() when all us