function FormBuilder::rebuildForm

Same name in other branches
  1. 9 core/lib/Drupal/Core/Form/FormBuilder.php \Drupal\Core\Form\FormBuilder::rebuildForm()
  2. 8.9.x core/lib/Drupal/Core/Form/FormBuilder.php \Drupal\Core\Form\FormBuilder::rebuildForm()
  3. 11.x core/lib/Drupal/Core/Form/FormBuilder.php \Drupal\Core\Form\FormBuilder::rebuildForm()
2 calls to FormBuilder::rebuildForm()
FormBuilder::buildForm in core/lib/Drupal/Core/Form/FormBuilder.php
FormBuilder::processForm in core/lib/Drupal/Core/Form/FormBuilder.php

File

core/lib/Drupal/Core/Form/FormBuilder.php, line 374

Class

FormBuilder
Provides form building and processing.

Namespace

Drupal\Core\Form

Code

public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL) {
    $form = $this->retrieveForm($form_id, $form_state);
    // Only GET and POST are valid form methods. If the form receives its input
    // via POST, then $form_state must be persisted when it is rebuilt between
    // submissions. If the form receives its input via GET, then persisting
    // state is forbidden by $form_state->setCached(), and the form must use
    // the URL itself to transfer its state across steps. Although $form_state
    // throws an exception based on the request method rather than the form's
    // method, we base the decision to cache on the form method, because:
    // - It's the form method that defines what the form needs to do to manage
    //   its state.
    // - rebuildForm() should only be called after successful input processing,
    //   which means the request method matches the form method, and if not,
    //   there's some other error, so it's ok if an exception is thrown.
    if ($form_state->isMethodType('POST')) {
        $form_state->setCached();
    }
    // \Drupal\Component\Utility\Html::getUniqueId() maintains a cache of
    // element IDs it has seen, so it can prevent duplicates. We want to be
    // sure we reset that cache when a form is processed, so scenarios that
    // result in the form being built behind the scenes and again for the
    // browser don't increment all the element IDs needlessly.
    if (!FormState::hasAnyErrors()) {
        // We only reset HTML ID's when there are no validation errors as this can
        // cause ID collisions with other forms on the page otherwise.
        Html::resetSeenIds();
    }
    // If only parts of the form will be returned to the browser (e.g., Ajax or
    // RIA clients), or if the form already had a new build ID regenerated when
    // it was retrieved from the form cache, reuse the existing #build_id.
    // Otherwise, a new #build_id is generated, to not clobber the previous
    // build's data in the form cache; also allowing the user to go back to an
    // earlier build, make changes, and re-submit.
    // @see self::prepareForm()
    $rebuild_info = $form_state->getRebuildInfo();
    $enforce_old_build_id = isset($old_form['#build_id']) && !empty($rebuild_info['copy']['#build_id']);
    $old_form_is_mutable_copy = isset($old_form['#build_id_old']);
    if ($enforce_old_build_id || $old_form_is_mutable_copy) {
        $form['#build_id'] = $old_form['#build_id'];
        if ($old_form_is_mutable_copy) {
            $form['#build_id_old'] = $old_form['#build_id_old'];
        }
    }
    else {
        if (isset($old_form['#build_id'])) {
            $form['#build_id_old'] = $old_form['#build_id'];
        }
        $form['#build_id'] = 'form-' . Crypt::randomBytesBase64();
    }
    // #action defaults to $request->getRequestUri(), but in case of Ajax and
    // other partial rebuilds, the form is submitted to an alternate URL, and
    // the original #action needs to be retained.
    if (isset($old_form['#action']) && !empty($rebuild_info['copy']['#action'])) {
        $form['#action'] = $old_form['#action'];
    }
    $this->prepareForm($form_id, $form, $form_state);
    // Caching is normally done in self::processForm(), but what needs to be
    // cached is the $form structure before it passes through
    // self::doBuildForm(), so we need to do it here.
    // @todo For Drupal 8, find a way to avoid this code duplication.
    if ($form_state->isCached()) {
        $this->setCache($form['#build_id'], $form, $form_state);
    }
    // Clear out all group associations as these might be different when
    // re-rendering the form.
    $form_state->setGroups([]);
    // Return a fully built form that is ready for rendering.
    return $this->doBuildForm($form_id, $form, $form_state);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.