public function FormBuilder::processForm in Drupal 9
Same name and namespace in other branches
- 8 core/lib/Drupal/Core/Form/FormBuilder.php \Drupal\Core\Form\FormBuilder::processForm()
Processes a form submission.
This function is the heart of form API. The form gets built, validated and in appropriate cases, submitted and rebuilt.
Parameters
string $form_id: The unique string identifying the current form.
array $form: An associative array containing the structure of the form.
\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form. This includes the current persistent storage data for the form, and any data passed along by earlier steps when displaying a multi-step form. Additional information, like the sanitized \Drupal::request()->request data, is also accumulated here.
Return value
\Symfony\Component\HttpFoundation\RedirectResponse|null
Overrides FormBuilderInterface::processForm
2 calls to FormBuilder::processForm()
- FormBuilder::buildForm in core/
lib/ Drupal/ Core/ Form/ FormBuilder.php - Builds and processes a form for a given form ID.
- FormBuilder::submitForm in core/
lib/ Drupal/ Core/ Form/ FormBuilder.php - Retrieves, populates, and processes a form.
File
- core/
lib/ Drupal/ Core/ Form/ FormBuilder.php, line 551
Class
- FormBuilder
- Provides form building and processing.
Namespace
Drupal\Core\FormCode
public function processForm($form_id, &$form, FormStateInterface &$form_state) {
$form_state
->setValues([]);
// With GET, these forms are always submitted if requested.
if ($form_state
->isMethodType('get') && $form_state
->getAlwaysProcess()) {
$input = $form_state
->getUserInput();
if (!isset($input['form_build_id'])) {
$input['form_build_id'] = $form['#build_id'];
}
if (!isset($input['form_id'])) {
$input['form_id'] = $form_id;
}
if (!isset($input['form_token']) && isset($form['#token'])) {
$input['form_token'] = $this->csrfToken
->get($form['#token']);
}
$form_state
->setUserInput($input);
}
// self::doBuildForm() finishes building the form by calling element
// #process functions and mapping user input, if any, to #value properties,
// and also storing the values in $form_state->getValues(). We need to
// retain the unprocessed $form in case it needs to be cached.
$unprocessed_form = $form;
$form = $this
->doBuildForm($form_id, $form, $form_state);
// Only process the input if we have a correct form submission.
if ($form_state
->isProcessingInput()) {
// Form values for programmed form submissions typically do not include a
// value for the submit button. But without a triggering element, a
// potentially existing #limit_validation_errors property on the primary
// submit button is not taken account. Therefore, check whether there is
// exactly one submit button in the form, and if so, automatically use it
// as triggering_element.
$buttons = $form_state
->getButtons();
if ($form_state
->isProgrammed() && !$form_state
->getTriggeringElement() && count($buttons) == 1) {
$form_state
->setTriggeringElement(reset($buttons));
}
$this->formValidator
->validateForm($form_id, $form, $form_state);
// If there are no errors and the form is not rebuilding, submit the form.
if (!$form_state
->isRebuilding() && !FormState::hasAnyErrors()) {
$submit_response = $this->formSubmitter
->doSubmitForm($form, $form_state);
// If this form was cached, delete it from the cache after submission.
if ($form_state
->isCached()) {
$this
->deleteCache($form['#build_id']);
}
// If the form submission directly returned a response, return it now.
if ($submit_response) {
return $submit_response;
}
}
// Don't rebuild or cache form submissions invoked via self::submitForm().
if ($form_state
->isProgrammed()) {
return;
}
// 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 yet complete. A new $form needs to be constructed based on
// the changes made to $form_state during this request. Normally, a submit
// handler sets $form_state->isRebuilding() if a fully executed form
// requires another step. However, for forms that have not been fully
// executed (e.g., Ajax submissions triggered by non-buttons), there is no
// submit handler to set $form_state->isRebuilding(). It would not make
// sense to redisplay the identical form without an error for the user to
// correct, so we also rebuild error-free non-executed forms, regardless
// of $form_state->isRebuilding().
// @todo Simplify this logic; considering Ajax and non-HTML front-ends,
// along with element-level #submit properties, it makes no sense to
// have divergent form execution based on whether the triggering element
// has #executes_submit_callback set to TRUE.
if (($form_state
->isRebuilding() || !$form_state
->isExecuted()) && !FormState::hasAnyErrors()) {
// Form building functions (e.g., self::handleInputElement()) may use
// $form_state->isRebuilding() to determine if they are running in the
// context of a rebuild, so ensure it is set.
$form_state
->setRebuild();
$form = $this
->rebuildForm($form_id, $form_state, $form);
}
}
// After processing the form, the form builder or a #process callback may
// have called $form_state->setCached() to indicate that the form and form
// state shall be cached. But the form may only be cached if
// $form_state->disableCache() is not called. Only cache $form as it was
// prior to self::doBuildForm(), because self::doBuildForm() must run for
// each request to accommodate new user input. Rebuilt forms are not cached
// here, because self::rebuildForm() already takes care of that.
if (!$form_state
->isRebuilding() && $form_state
->isCached()) {
$this
->setCache($form['#build_id'], $unprocessed_form, $form_state);
}
}