You are here

class FormState in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Form/FormState.php \Drupal\Core\Form\FormState

Stores information about the state of a form.

Hierarchy

Expanded class hierarchy of FormState

71 files declare their use of FormState
AggregatorPluginSettingsBaseTest.php in core/modules/aggregator/tests/src/Unit/Plugin/AggregatorPluginSettingsBaseTest.php
AreaDisplayLinkTest.php in core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php
AreaEntityTest.php in core/modules/views/tests/src/Kernel/Handler/AreaEntityTest.php
ArgumentValidateTest.php in core/modules/user/tests/src/Kernel/Views/ArgumentValidateTest.php
batch.inc in core/includes/batch.inc
Batch processing API for processes to run in multiple HTTP requests.

... See full list

File

core/lib/Drupal/Core/Form/FormState.php, line 12

Namespace

Drupal\Core\Form
View source
class FormState implements FormStateInterface {
  use FormStateValuesTrait;

  /**
   * Tracks if any errors have been set on any form.
   *
   * @var bool
   */
  protected static $anyErrors = FALSE;

  /**
   * The complete form structure.
   *
   * #process, #after_build, #element_validate, and other handlers being invoked
   * on a form element may use this reference to access other information in the
   * form the element is contained in.
   *
   * @see self::getCompleteForm()
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $complete_form;

  /**
   * An associative array of information stored by Form API that is necessary to
   * build and rebuild the form from cache when the original context may no
   * longer be available:
   *   - callback: The actual callback to be used to retrieve the form array.
   *     Can be any callable. If none is provided $form_id is used as the name
   *     of a function to call instead.
   *   - args: A list of arguments to pass to the form constructor.
   *   - files: An optional array defining include files that need to be loaded
   *     for building the form. Each array entry may be the path to a file or
   *     another array containing values for the parameters 'type', 'module' and
   *     'name' as needed by module_load_include(). The files listed here are
   *     automatically loaded by \Drupal::formBuilder()->getCache(). By default
   *     the current menu router item's 'file' definition is added, if any. Use
   *     self::loadInclude() to add include files from a form constructor.
   *   - form_id: Identification of the primary form being constructed and
   *     processed.
   *   - base_form_id: Identification for a base form, as declared in the form
   *     class's \Drupal\Core\Form\BaseFormIdInterface::getBaseFormId() method.
   *   - immutable: If this flag is set to TRUE, a new form build id is
   *     generated when the form is loaded from the cache. If it is subsequently
   *     saved to the cache again, it will have another cache id and therefore
   *     the original form and form-state will remain unaltered. This is
   *     important when page caching is enabled in order to prevent form state
   *     from leaking between anonymous users.
   *
   * @var array
   */
  protected $build_info = [
    'args' => [],
    'files' => [],
  ];

  /**
   * Similar to self::$build_info, but pertaining to
   * \Drupal\Core\Form\FormBuilderInterface::rebuildForm().
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $rebuild_info = [];

  /**
   * Normally, after the entire form processing is completed and submit handlers
   * have run, a form is considered to be done and
   * \Drupal\Core\Form\FormSubmitterInterface::redirectForm() will redirect the
   * user to a new page using a GET request (so a browser refresh does not
   * re-submit the form). However, if 'rebuild' has been set to TRUE, then a new
   * copy of the form is immediately built and sent to the browser, instead of a
   * redirect. This is used for multi-step forms, such as wizards and
   * confirmation forms. Normally, self::$rebuild is set by a submit handler,
   * since it is usually logic within a submit handler that determines whether a
   * form is done or requires another step. However, a validation handler may
   * already set self::$rebuild to cause the form processing to bypass submit
   * handlers and rebuild the form instead, even if there are no validation
   * errors.
   *
   * This property is uncacheable.
   *
   * @see self::setRebuild()
   *
   * @var bool
   */
  protected $rebuild = FALSE;

  /**
   * If set to TRUE the form will skip calling form element value callbacks,
   * except for a select list of callbacks provided by Drupal core that are
   * known to be safe.
   *
   * This property is uncacheable.
   *
   * @see self::setInvalidToken()
   *
   * @var bool
   */
  protected $invalidToken = FALSE;

  /**
   * Used when a form needs to return some kind of a
   * \Symfony\Component\HttpFoundation\Response object, e.g., a
   * \Symfony\Component\HttpFoundation\BinaryFileResponse when triggering a
   * file download. If you use self::setRedirect() or self::setRedirectUrl(),
   * it will be used to build a
   * \Symfony\Component\HttpFoundation\RedirectResponse and will populate this
   * key.
   *
   * @var \Symfony\Component\HttpFoundation\Response|null
   */
  protected $response;

  /**
   * Used to redirect the form on submission.
   *
   * @see self::getRedirect()
   *
   * This property is uncacheable.
   *
   * @var \Drupal\Core\Url|\Symfony\Component\HttpFoundation\RedirectResponse|null
   */
  protected $redirect;

  /**
   * If set to TRUE the form will NOT perform a redirect, even if
   * self::$redirect is set.
   *
   * This property is uncacheable.
   *
   * @var bool
   */
  protected $no_redirect;

  /**
   * The HTTP form method to use for finding the input for this form.
   *
   * May be 'POST' or 'GET'. Defaults to 'POST'. Note that 'GET' method forms do
   * not use form ids so are always considered to be submitted, which can have
   * unexpected effects. The 'GET' method should only be used on forms that do
   * not change data, as that is exclusively the domain of 'POST.'
   *
   * This property is uncacheable.
   *
   * @var string
   */
  protected $method = 'POST';

  /**
   * The HTTP method used by the request building or processing this form.
   *
   * May be any valid HTTP method. Defaults to 'GET', because even though
   * $method is 'POST' for most forms, the form's initial build is usually
   * performed as part of a GET request.
   *
   * This property is uncacheable.
   *
   * @var string
   */
  protected $requestMethod = 'GET';

  /**
   * If set to TRUE the original, unprocessed form structure will be cached,
   * which allows the entire form to be rebuilt from cache. A typical form
   * workflow involves two page requests; first, a form is built and rendered
   * for the user to fill in. Then, the user fills the form in and submits it,
   * triggering a second page request in which the form must be built and
   * processed. By default, $form and $form_state are built from scratch during
   * each of these page requests. Often, it is necessary or desired to persist
   * the $form and $form_state variables from the initial page request to the
   * one that processes the submission. 'cache' can be set to TRUE to do this.
   * A prominent example is an Ajax-enabled form, in which
   * \Drupal\Core\Render\Element\RenderElement::processAjaxForm()
   * enables form caching for all forms that include an element with the #ajax
   * property. (The Ajax handler has no way to build the form itself, so must
   * rely on the cached version.) Note that the persistence of $form and
   * $form_state happens automatically for (multi-step) forms having the
   * self::$rebuild flag set, regardless of the value for self::$cache.
   *
   * @var bool
   */
  protected $cache = FALSE;

  /**
   * If set to TRUE the form will NOT be cached, even if 'cache' is set.
   *
   * @var bool
   */
  protected $no_cache;

  /**
   * An associative array of values submitted to the form.
   *
   * The validation functions and submit functions use this array for nearly all
   * their decision making. (Note that #tree determines whether the values are a
   * flat array or an array whose structure parallels the $form array. See
   * \Drupal\Core\Render\Element\FormElement for more information.)
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $values = [];

  /**
   * An associative array of form value keys to be removed by cleanValues().
   *
   * Any values that are temporary but must still be displayed as values in
   * the rendered form should be added to this array using addCleanValueKey().
   * Initialized with internal Form API values.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $cleanValueKeys = [
    'form_id',
    'form_token',
    'form_build_id',
    'op',
  ];

  /**
   * The array of values as they were submitted by the user.
   *
   * These are raw and unvalidated, so should not be used without a thorough
   * understanding of security implications. In almost all cases, code should
   * use the data in the 'values' array exclusively. The most common use of this
   * key is for multi-step forms that need to clear some of the user input when
   * setting 'rebuild'. The values correspond to \Drupal::request()->request or
   * \Drupal::request()->query, depending on the 'method' chosen.
   *
   * This property is uncacheable.
   *
   * @var array|null
   *   The submitted user input array, or NULL if no input was submitted yet.
   */
  protected $input;

  /**
   * If TRUE and the method is GET, a form_id is not necessary.
   *
   * This property is uncacheable.
   *
   * @var bool
   */
  protected $always_process;

  /**
   * Ordinarily, a form is only validated once, but there are times when a form
   * is resubmitted internally and should be validated again. Setting this to
   * TRUE will force that to happen. This is most likely to occur during Ajax
   * operations.
   *
   * This property is uncacheable.
   *
   * @var bool
   */
  protected $must_validate;

  /**
   * If TRUE, the form was submitted programmatically, usually invoked via
   * \Drupal\Core\Form\FormBuilderInterface::submitForm(). Defaults to FALSE.
   *
   * @var bool
   */
  protected $programmed = FALSE;

  /**
   * If TRUE, programmatic form submissions are processed without taking #access
   * into account. Set this to FALSE when submitting a form programmatically
   * with values that may have been input by the user executing the current
   * request; this will cause #access to be respected as it would on a normal
   * form submission. Defaults to TRUE.
   *
   * @var bool
   */
  protected $programmed_bypass_access_check = TRUE;

  /**
   * TRUE signifies correct form submission. This is always TRUE for programmed
   * forms coming from \Drupal\Core\Form\FormBuilderInterface::submitForm() (see
   * 'programmed' key), or if the form_id coming from the
   * \Drupal::request()->request data is set and matches the current form_id.
   *
   * @var bool
   */
  protected $process_input;

  /**
   * If TRUE, the form has been submitted. Defaults to FALSE.
   *
   * This property is uncacheable.
   *
   * @var bool
   */
  protected $submitted = FALSE;

  /**
   * If TRUE, the form was submitted and has been processed and executed.
   *
   * This property is uncacheable.
   *
   * @var bool
   */
  protected $executed = FALSE;

  /**
   * The form element that triggered submission, which may or may not be a
   * button (in the case of Ajax forms). This key is often used to distinguish
   * between various buttons in a submit handler, and is also used in Ajax
   * handlers.
   *
   * This property is uncacheable.
   *
   * @var array|null
   */
  protected $triggering_element;

  /**
   * If TRUE, there is a file element and Form API will set the appropriate
   * 'enctype' HTML attribute on the form.
   *
   * @var bool
   */
  protected $has_file_element;

  /**
   * Contains references to details elements to render them within vertical tabs.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $groups = [];

  /**
   * This is not a special key, and no specific support is provided for it in
   * the Form API. By tradition it was the location where application-specific
   * data was stored for communication between the submit, validation, and form
   * builder functions, especially in a multi-step-style form. Form
   * implementations may use any key(s) within $form_state (other than the keys
   * listed here and other reserved ones used by Form API internals) for this
   * kind of storage. The recommended way to ensure that the chosen key doesn't
   * conflict with ones used by the Form API or other modules is to use the
   * module name as the key name or a prefix for the key name. For example, the
   * entity form classes use $this->entity in entity forms, or
   * $form_state->getFormObject()->getEntity() outside the controller, to store
   * information about the entity being edited, and this information stays
   * available across successive clicks of the "Preview" button (if available)
   * as well as when the "Save" button is finally clicked.
   *
   * @var array
   */
  protected $storage = [];

  /**
   * A list containing copies of all submit and button elements in the form.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $buttons = [];

  /**
   * Holds temporary data accessible during the current page request only.
   *
   * All $form_state properties that are not reserved keys (see
   * other properties marked as uncacheable) persist throughout a multistep form
   * sequence. Form API provides this key for modules to communicate information
   * across form-related functions during a single page request. It may be used
   * to temporarily save data that does not need to or should not be cached
   * during the whole form workflow; e.g., data that needs to be accessed during
   * the current form build process only. There is no use-case for this
   * functionality in Drupal core.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $temporary = [];

  /**
   * Tracks if the form has finished validation.
   *
   * This property is uncacheable.
   *
   * @var bool
   */
  protected $validation_complete = FALSE;

  /**
   * Contains errors for this form.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $errors = [];

  /**
   * Stores which errors should be limited during validation.
   *
   * An array of "sections" within which user input must be valid. If the
   * element is within one of these sections, the error must be recorded.
   * Otherwise, it can be suppressed. self::$limit_validation_errors can be an
   * empty array, in which case all errors are suppressed. For example, a
   * "Previous" button might want its submit action to be triggered even if none
   * of the submitted values are valid.
   *
   * This property is uncacheable.
   *
   * @var array|null
   */
  protected $limit_validation_errors;

  /**
   * Stores the gathered validation handlers.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $validate_handlers = [];

  /**
   * Stores the gathered submission handlers.
   *
   * This property is uncacheable.
   *
   * @var array
   */
  protected $submit_handlers = [];

  /**
   * {@inheritdoc}
   */
  public function setFormState(array $form_state_additions) {
    foreach ($form_state_additions as $key => $value) {
      if (property_exists($this, $key)) {
        $this->{$key} = $value;
      }
      else {
        $this
          ->set($key, $value);
      }
    }
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setAlwaysProcess($always_process = TRUE) {
    $this->always_process = (bool) $always_process;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getAlwaysProcess() {
    return $this->always_process;
  }

  /**
   * {@inheritdoc}
   */
  public function setButtons(array $buttons) {
    $this->buttons = $buttons;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getButtons() {
    return $this->buttons;
  }

  /**
   * {@inheritdoc}
   */
  public function setCached($cache = TRUE) {

    // Persisting $form_state is a side-effect disallowed during a "safe" HTTP
    // method.
    if ($cache && $this
      ->isRequestMethodSafe()) {
      throw new \LogicException(sprintf('Form state caching on %s requests is not allowed.', $this->requestMethod));
    }
    $this->cache = (bool) $cache;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isCached() {
    return empty($this->no_cache) && $this->cache;
  }

  /**
   * {@inheritdoc}
   */
  public function disableCache() {
    $this->no_cache = TRUE;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setExecuted() {
    $this->executed = TRUE;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isExecuted() {
    return $this->executed;
  }

  /**
   * {@inheritdoc}
   */
  public function setGroups(array $groups) {
    $this->groups = $groups;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function &getGroups() {
    return $this->groups;
  }

  /**
   * {@inheritdoc}
   */
  public function setHasFileElement($has_file_element = TRUE) {
    $this->has_file_element = (bool) $has_file_element;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function hasFileElement() {
    return $this->has_file_element;
  }

  /**
   * {@inheritdoc}
   */
  public function setLimitValidationErrors($limit_validation_errors) {
    $this->limit_validation_errors = $limit_validation_errors;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getLimitValidationErrors() {
    return $this->limit_validation_errors;
  }

  /**
   * {@inheritdoc}
   */
  public function setMethod($method) {
    $this->method = strtoupper($method);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isMethodType($method_type) {
    return $this->method === strtoupper($method_type);
  }

  /**
   * {@inheritdoc}
   */
  public function setRequestMethod($method) {
    $this->requestMethod = strtoupper($method);
    return $this;
  }

  /**
   * Checks whether the request method is a "safe" HTTP method.
   *
   * Link below defines GET and HEAD as "safe" methods, meaning they SHOULD NOT
   * have side-effects, such as persisting $form_state changes.
   *
   * @return bool
   *
   * @see \Symfony\Component\HttpFoundation\Request::isMethodSafe()
   * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
   */
  protected function isRequestMethodSafe() {
    return in_array($this->requestMethod, [
      'GET',
      'HEAD',
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function setValidationEnforced($must_validate = TRUE) {
    $this->must_validate = (bool) $must_validate;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isValidationEnforced() {
    return $this->must_validate;
  }

  /**
   * {@inheritdoc}
   */
  public function disableRedirect($no_redirect = TRUE) {
    $this->no_redirect = (bool) $no_redirect;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isRedirectDisabled() {
    return $this->no_redirect;
  }

  /**
   * {@inheritdoc}
   */
  public function setProcessInput($process_input = TRUE) {
    $this->process_input = (bool) $process_input;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isProcessingInput() {
    return $this->process_input;
  }

  /**
   * {@inheritdoc}
   */
  public function setProgrammed($programmed = TRUE) {
    $this->programmed = (bool) $programmed;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isProgrammed() {
    return $this->programmed;
  }

  /**
   * {@inheritdoc}
   */
  public function setProgrammedBypassAccessCheck($programmed_bypass_access_check = TRUE) {
    $this->programmed_bypass_access_check = (bool) $programmed_bypass_access_check;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isBypassingProgrammedAccessChecks() {
    return $this->programmed_bypass_access_check;
  }

  /**
   * {@inheritdoc}
   */
  public function setRebuildInfo(array $rebuild_info) {
    $this->rebuild_info = $rebuild_info;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getRebuildInfo() {
    return $this->rebuild_info;
  }

  /**
   * {@inheritdoc}
   */
  public function addRebuildInfo($property, $value) {
    $rebuild_info = $this
      ->getRebuildInfo();
    $rebuild_info[$property] = $value;
    $this
      ->setRebuildInfo($rebuild_info);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setStorage(array $storage) {
    $this->storage = $storage;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function &getStorage() {
    return $this->storage;
  }

  /**
   * {@inheritdoc}
   */
  public function setSubmitHandlers(array $submit_handlers) {
    $this->submit_handlers = $submit_handlers;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getSubmitHandlers() {
    return $this->submit_handlers;
  }

  /**
   * {@inheritdoc}
   */
  public function setSubmitted() {
    $this->submitted = TRUE;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isSubmitted() {
    return $this->submitted;
  }

  /**
   * {@inheritdoc}
   */
  public function setTemporary(array $temporary) {
    $this->temporary = $temporary;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getTemporary() {
    return $this->temporary;
  }

  /**
   * {@inheritdoc}
   */
  public function &getTemporaryValue($key) {
    $value =& NestedArray::getValue($this->temporary, (array) $key);
    return $value;
  }

  /**
   * {@inheritdoc}
   */
  public function setTemporaryValue($key, $value) {
    NestedArray::setValue($this->temporary, (array) $key, $value, TRUE);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function hasTemporaryValue($key) {
    $exists = NULL;
    NestedArray::getValue($this->temporary, (array) $key, $exists);
    return $exists;
  }

  /**
   * {@inheritdoc}
   */
  public function setTriggeringElement($triggering_element) {
    $this->triggering_element = $triggering_element;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function &getTriggeringElement() {
    return $this->triggering_element;
  }

  /**
   * {@inheritdoc}
   */
  public function setValidateHandlers(array $validate_handlers) {
    $this->validate_handlers = $validate_handlers;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getValidateHandlers() {
    return $this->validate_handlers;
  }

  /**
   * {@inheritdoc}
   */
  public function setValidationComplete($validation_complete = TRUE) {
    $this->validation_complete = (bool) $validation_complete;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isValidationComplete() {
    return $this->validation_complete;
  }

  /**
   * {@inheritdoc}
   */
  public function loadInclude($module, $type, $name = NULL) {
    if (!isset($name)) {
      $name = $module;
    }
    $build_info = $this
      ->getBuildInfo();
    if (!isset($build_info['files']["{$module}:{$name}.{$type}"])) {

      // Only add successfully included files to the form state.
      if ($result = $this
        ->moduleLoadInclude($module, $type, $name)) {
        $build_info['files']["{$module}:{$name}.{$type}"] = [
          'type' => $type,
          'module' => $module,
          'name' => $name,
        ];
        $this
          ->setBuildInfo($build_info);
        return $result;
      }
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheableArray() {
    return [
      'build_info' => $this
        ->getBuildInfo(),
      'response' => $this
        ->getResponse(),
      'programmed' => $this
        ->isProgrammed(),
      'programmed_bypass_access_check' => $this
        ->isBypassingProgrammedAccessChecks(),
      'process_input' => $this
        ->isProcessingInput(),
      'has_file_element' => $this
        ->hasFileElement(),
      'storage' => $this
        ->getStorage(),
      // Use the properties directly, since self::isCached() combines them and
      // cannot be relied upon.
      'cache' => $this->cache,
      'no_cache' => $this->no_cache,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function setCompleteForm(array &$complete_form) {
    $this->complete_form =& $complete_form;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function &getCompleteForm() {
    return $this->complete_form;
  }

  /**
   * {@inheritdoc}
   */
  public function &get($property) {
    $value =& NestedArray::getValue($this->storage, (array) $property);
    return $value;
  }

  /**
   * {@inheritdoc}
   */
  public function set($property, $value) {
    NestedArray::setValue($this->storage, (array) $property, $value, TRUE);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function has($property) {
    $exists = NULL;
    NestedArray::getValue($this->storage, (array) $property, $exists);
    return $exists;
  }

  /**
   * {@inheritdoc}
   */
  public function setBuildInfo(array $build_info) {
    $this->build_info = $build_info;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getBuildInfo() {
    return $this->build_info;
  }

  /**
   * {@inheritdoc}
   */
  public function addBuildInfo($property, $value) {
    $build_info = $this
      ->getBuildInfo();
    $build_info[$property] = $value;
    $this
      ->setBuildInfo($build_info);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function &getUserInput() {
    return $this->input;
  }

  /**
   * {@inheritdoc}
   */
  public function setUserInput(array $user_input) {
    $this->input = $user_input;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function &getValues() {
    return $this->values;
  }

  /**
   * {@inheritdoc}
   */
  public function setResponse(Response $response) {
    $this->response = $response;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getResponse() {
    return $this->response;
  }

  /**
   * {@inheritdoc}
   */
  public function setRedirect($route_name, array $route_parameters = [], array $options = []) {
    $url = new Url($route_name, $route_parameters, $options);
    return $this
      ->setRedirectUrl($url);
  }

  /**
   * {@inheritdoc}
   */
  public function setRedirectUrl(Url $url) {
    $this->redirect = $url;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getRedirect() {

    // Skip redirection for form submissions invoked via
    // \Drupal\Core\Form\FormBuilderInterface::submitForm().
    if ($this
      ->isProgrammed()) {
      return FALSE;
    }

    // Skip redirection if rebuild is activated.
    if ($this
      ->isRebuilding()) {
      return FALSE;
    }

    // Skip redirection if it was explicitly disallowed.
    if ($this
      ->isRedirectDisabled()) {
      return FALSE;
    }
    return $this->redirect;
  }

  /**
   * Sets the global status of errors.
   *
   * @param bool $errors
   *   TRUE if any form has any errors, FALSE otherwise.
   */
  protected static function setAnyErrors($errors = TRUE) {
    static::$anyErrors = $errors;
  }

  /**
   * {@inheritdoc}
   */
  public static function hasAnyErrors() {
    return static::$anyErrors;
  }

  /**
   * {@inheritdoc}
   */
  public function setErrorByName($name, $message = '') {
    if ($this
      ->isValidationComplete()) {
      throw new \LogicException('Form errors cannot be set after form validation has finished.');
    }
    $errors = $this
      ->getErrors();
    if (!isset($errors[$name])) {
      $record = TRUE;
      $limit_validation_errors = $this
        ->getLimitValidationErrors();
      if ($limit_validation_errors !== NULL) {
        $record = FALSE;
        foreach ($limit_validation_errors as $section) {

          // Exploding by '][' reconstructs the element's #parents. If the
          // reconstructed #parents begin with the same keys as the specified
          // section, then the element's values are within the part of
          // $form_state->getValues() that the clicked button requires to be
          // valid, so errors for this element must be recorded. As the exploded
          // array will all be strings, we need to cast every value of the
          // section array to string.
          if (array_slice(explode('][', $name), 0, count($section)) === array_map('strval', $section)) {
            $record = TRUE;
            break;
          }
        }
      }
      if ($record) {
        $errors[$name] = $message;
        $this->errors = $errors;
        static::setAnyErrors();
      }
    }
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setError(array &$element, $message = '') {
    $this
      ->setErrorByName(implode('][', $element['#parents']), $message);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function clearErrors() {
    $this->errors = [];
    static::setAnyErrors(FALSE);
  }

  /**
   * {@inheritdoc}
   */
  public function getError(array $element) {
    if ($errors = $this
      ->getErrors()) {
      $parents = [];
      foreach ($element['#parents'] as $parent) {
        $parents[] = $parent;
        $key = implode('][', $parents);
        if (isset($errors[$key])) {
          return $errors[$key];
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getErrors() {
    return $this->errors;
  }

  /**
   * {@inheritdoc}
   */
  public function setRebuild($rebuild = TRUE) {
    $this->rebuild = $rebuild;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function isRebuilding() {
    return $this->rebuild;
  }

  /**
   * {@inheritdoc}
   */
  public function prepareCallback($callback) {
    if (is_string($callback) && substr($callback, 0, 2) == '::') {
      $callback = [
        $this
          ->getFormObject(),
        substr($callback, 2),
      ];
    }
    return $callback;
  }

  /**
   * {@inheritdoc}
   */
  public function setFormObject(FormInterface $form_object) {
    $this
      ->addBuildInfo('callback_object', $form_object);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormObject() {
    return $this
      ->getBuildInfo()['callback_object'];
  }

  /**
   * {@inheritdoc}
   */
  public function getCleanValueKeys() {
    return $this->cleanValueKeys;
  }

  /**
   * {@inheritdoc}
   */
  public function setCleanValueKeys(array $cleanValueKeys) {
    $this->cleanValueKeys = $cleanValueKeys;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function addCleanValueKey($cleanValueKey) {
    $keys = $this
      ->getCleanValueKeys();
    $this
      ->setCleanValueKeys(array_merge((array) $keys, [
      $cleanValueKey,
    ]));
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function cleanValues() {
    foreach ($this
      ->getCleanValueKeys() as $value) {
      $this
        ->unsetValue($value);
    }

    // Remove button values.
    // \Drupal::formBuilder()->doBuildForm() collects all button elements in a
    // form. We remove the button value separately for each button element.
    foreach ($this
      ->getButtons() as $button) {

      // Remove this button's value from the submitted form values by finding
      // the value corresponding to this button.
      // We iterate over the #parents of this button and move a reference to
      // each parent in self::getValues(). For example, if #parents is:
      // @code
      //   array('foo', 'bar', 'baz')
      // @endcode
      // then the corresponding self::getValues() part will look like this:
      // @code
      // array(
      //   'foo' => array(
      //     'bar' => array(
      //       'baz' => 'button_value',
      //     ),
      //   ),
      // )
      // @endcode
      // We start by (re)moving 'baz' to $last_parent, so we are able unset it
      // at the end of the iteration. Initially, $values will contain a
      // reference to self::getValues(), but in the iteration we move the
      // reference to self::getValue('foo'), and finally to
      // self::getValue(array('foo', 'bar')), which is the level where we
      // can unset 'baz' (that is stored in $last_parent).
      $parents = $button['#parents'];
      $last_parent = array_pop($parents);
      $key_exists = NULL;
      $values =& NestedArray::getValue($this
        ->getValues(), $parents, $key_exists);
      if ($key_exists && is_array($values)) {
        unset($values[$last_parent]);
      }
    }
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setInvalidToken($invalid_token) {
    $this->invalidToken = (bool) $invalid_token;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function hasInvalidToken() {
    return $this->invalidToken;
  }

  /**
   * Wraps ModuleHandler::loadInclude().
   */
  protected function moduleLoadInclude($module, $type, $name = NULL) {
    return \Drupal::moduleHandler()
      ->loadInclude($module, $type, $name);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FormState::$always_process protected property If TRUE and the method is GET, a form_id is not necessary.
FormState::$anyErrors protected static property Tracks if any errors have been set on any form.
FormState::$build_info protected property An associative array of information stored by Form API that is necessary to build and rebuild the form from cache when the original context may no longer be available:
FormState::$buttons protected property A list containing copies of all submit and button elements in the form.
FormState::$cache protected property If set to TRUE the original, unprocessed form structure will be cached, which allows the entire form to be rebuilt from cache. A typical form workflow involves two page requests; first, a form is built and rendered for the user to fill in. Then, the…
FormState::$cleanValueKeys protected property An associative array of form value keys to be removed by cleanValues().
FormState::$complete_form protected property The complete form structure.
FormState::$errors protected property Contains errors for this form.
FormState::$executed protected property If TRUE, the form was submitted and has been processed and executed.
FormState::$groups protected property Contains references to details elements to render them within vertical tabs.
FormState::$has_file_element protected property If TRUE, there is a file element and Form API will set the appropriate 'enctype' HTML attribute on the form.
FormState::$input protected property The array of values as they were submitted by the user.
FormState::$invalidToken protected property If set to TRUE the form will skip calling form element value callbacks, except for a select list of callbacks provided by Drupal core that are known to be safe.
FormState::$limit_validation_errors protected property Stores which errors should be limited during validation.
FormState::$method protected property The HTTP form method to use for finding the input for this form.
FormState::$must_validate protected property Ordinarily, a form is only validated once, but there are times when a form is resubmitted internally and should be validated again. Setting this to TRUE will force that to happen. This is most likely to occur during Ajax operations.
FormState::$no_cache protected property If set to TRUE the form will NOT be cached, even if 'cache' is set.
FormState::$no_redirect protected property If set to TRUE the form will NOT perform a redirect, even if self::$redirect is set.
FormState::$process_input protected property TRUE signifies correct form submission. This is always TRUE for programmed forms coming from \Drupal\Core\Form\FormBuilderInterface::submitForm() (see 'programmed' key), or if the form_id coming from the \Drupal::request()->request data…
FormState::$programmed protected property If TRUE, the form was submitted programmatically, usually invoked via \Drupal\Core\Form\FormBuilderInterface::submitForm(). Defaults to FALSE.
FormState::$programmed_bypass_access_check protected property If TRUE, programmatic form submissions are processed without taking #access into account. Set this to FALSE when submitting a form programmatically with values that may have been input by the user executing the current request; this will cause #access…
FormState::$rebuild protected property Normally, after the entire form processing is completed and submit handlers have run, a form is considered to be done and \Drupal\Core\Form\FormSubmitterInterface::redirectForm() will redirect the user to a new page using a GET request (so a browser…
FormState::$rebuild_info protected property Similar to self::$build_info, but pertaining to \Drupal\Core\Form\FormBuilderInterface::rebuildForm().
FormState::$redirect protected property Used to redirect the form on submission.
FormState::$requestMethod protected property The HTTP method used by the request building or processing this form.
FormState::$response protected property Used when a form needs to return some kind of a \Symfony\Component\HttpFoundation\Response object, e.g., a \Symfony\Component\HttpFoundation\BinaryFileResponse when triggering a file download. If you use self::setRedirect() or…
FormState::$storage protected property This is not a special key, and no specific support is provided for it in the Form API. By tradition it was the location where application-specific data was stored for communication between the submit, validation, and form builder functions, especially…
FormState::$submitted protected property If TRUE, the form has been submitted. Defaults to FALSE.
FormState::$submit_handlers protected property Stores the gathered submission handlers.
FormState::$temporary protected property Holds temporary data accessible during the current page request only.
FormState::$triggering_element protected property The form element that triggered submission, which may or may not be a button (in the case of Ajax forms). This key is often used to distinguish between various buttons in a submit handler, and is also used in Ajax handlers.
FormState::$validate_handlers protected property Stores the gathered validation handlers.
FormState::$validation_complete protected property Tracks if the form has finished validation.
FormState::$values protected property An associative array of values submitted to the form.
FormState::addBuildInfo public function Adds a value to the build info. Overrides FormStateInterface::addBuildInfo
FormState::addCleanValueKey public function Adds a key to the array of form values that will be cleaned. Overrides FormStateInterface::addCleanValueKey
FormState::addRebuildInfo public function Adds a value to the rebuild info. Overrides FormStateInterface::addRebuildInfo
FormState::cleanValues public function Removes internal Form API elements and buttons from submitted form values. Overrides FormStateInterface::cleanValues
FormState::clearErrors public function Clears all errors against all form elements made by self::setErrorByName(). Overrides FormStateInterface::clearErrors
FormState::disableCache public function Prevents the form from being cached. Overrides FormStateInterface::disableCache
FormState::disableRedirect public function Prevents the form from redirecting. Overrides FormStateInterface::disableRedirect
FormState::get public function Gets any arbitrary property. Overrides FormStateInterface::get
FormState::getAlwaysProcess public function Determines if this form should always be processed. Overrides FormStateInterface::getAlwaysProcess
FormState::getBuildInfo public function Returns the build info for the form. Overrides FormStateInterface::getBuildInfo
FormState::getButtons public function Returns the submit and button elements for the form. Overrides FormStateInterface::getButtons
FormState::getCacheableArray public function Returns an array representation of the cacheable portion of the form state. Overrides FormStateInterface::getCacheableArray
FormState::getCleanValueKeys public function Gets the keys of the form values that will be cleaned. Overrides FormStateInterface::getCleanValueKeys
FormState::getCompleteForm public function Returns a reference to the complete form array. Overrides FormStateInterface::getCompleteForm
FormState::getError public function Returns the error message filed against the given form element. Overrides FormStateInterface::getError
FormState::getErrors public function Returns an associative array of all errors. Overrides FormStateInterface::getErrors
FormState::getFormObject public function Returns the form object that is responsible for building this form. Overrides FormStateInterface::getFormObject
FormState::getGroups public function Returns references to details elements to render them within vertical tabs. Overrides FormStateInterface::getGroups
FormState::getLimitValidationErrors public function Retrieves the limited validation error sections. Overrides FormStateInterface::getLimitValidationErrors
FormState::getRebuildInfo public function Gets the rebuild info. Overrides FormStateInterface::getRebuildInfo
FormState::getRedirect public function Gets the value to use for redirecting after the form has been executed. Overrides FormStateInterface::getRedirect
FormState::getResponse public function Gets a response for this form. Overrides FormStateInterface::getResponse
FormState::getStorage public function Returns the entire set of arbitrary data. Overrides FormStateInterface::getStorage
FormState::getSubmitHandlers public function Gets the submit handlers. Overrides FormStateInterface::getSubmitHandlers
FormState::getTemporary public function Gets temporary data. Overrides FormStateInterface::getTemporary
FormState::getTemporaryValue public function Gets an arbitrary value from temporary storage. Overrides FormStateInterface::getTemporaryValue
FormState::getTriggeringElement public function Gets the form element that triggered submission. Overrides FormStateInterface::getTriggeringElement
FormState::getUserInput public function Returns the form values as they were submitted by the user. Overrides FormStateInterface::getUserInput
FormState::getValidateHandlers public function Gets the validate handlers. Overrides FormStateInterface::getValidateHandlers
FormState::getValues public function Implements \Drupal\Core\Form\FormStateInterface::getValues() Overrides FormStateValuesTrait::getValues
FormState::has public function Determines if an arbitrary property is present. Overrides FormStateInterface::has
FormState::hasAnyErrors public static function Determines if any forms have any errors. Overrides FormStateInterface::hasAnyErrors
FormState::hasFileElement public function Returns whether this form has a file element. Overrides FormStateInterface::hasFileElement
FormState::hasInvalidToken public function Determines if the form has an invalid token. Overrides FormStateInterface::hasInvalidToken
FormState::hasTemporaryValue public function Determines if a temporary value is present. Overrides FormStateInterface::hasTemporaryValue
FormState::isBypassingProgrammedAccessChecks public function Determines if this form submission should bypass #access. Overrides FormStateInterface::isBypassingProgrammedAccessChecks
FormState::isCached public function Determines if the form should be cached. Overrides FormStateInterface::isCached
FormState::isExecuted public function Determines if the form was submitted and has been processed and executed. Overrides FormStateInterface::isExecuted
FormState::isMethodType public function Returns the HTTP form method. Overrides FormStateInterface::isMethodType
FormState::isProcessingInput public function Determines if the form input will be processed. Overrides FormStateInterface::isProcessingInput
FormState::isProgrammed public function Returns if this form was submitted programmatically. Overrides FormStateInterface::isProgrammed
FormState::isRebuilding public function Determines if the form should be rebuilt after processing. Overrides FormStateInterface::isRebuilding
FormState::isRedirectDisabled public function Determines if redirecting has been prevented. Overrides FormStateInterface::isRedirectDisabled
FormState::isRequestMethodSafe protected function Checks whether the request method is a "safe" HTTP method.
FormState::isSubmitted public function Determines if the form has been submitted. Overrides FormStateInterface::isSubmitted
FormState::isValidationComplete public function Determines if validation has been completed. Overrides FormStateInterface::isValidationComplete
FormState::isValidationEnforced public function Checks if validation is enforced. Overrides FormStateInterface::isValidationEnforced
FormState::loadInclude public function Ensures an include file is loaded whenever the form is processed. Overrides FormStateInterface::loadInclude
FormState::moduleLoadInclude protected function Wraps ModuleHandler::loadInclude().
FormState::prepareCallback public function Converts support notations for a form callback to a valid callable. Overrides FormStateInterface::prepareCallback
FormState::set public function Sets a value to an arbitrary property. Overrides FormStateInterface::set
FormState::setAlwaysProcess public function Sets this form to always be processed. Overrides FormStateInterface::setAlwaysProcess
FormState::setAnyErrors protected static function Sets the global status of errors.
FormState::setBuildInfo public function Sets the build info for the form. Overrides FormStateInterface::setBuildInfo
FormState::setButtons public function Stores the submit and button elements for the form. Overrides FormStateInterface::setButtons
FormState::setCached public function Sets this form to be cached. Overrides FormStateInterface::setCached
FormState::setCleanValueKeys public function Sets the keys of the form values that will be cleaned. Overrides FormStateInterface::setCleanValueKeys
FormState::setCompleteForm public function Stores the complete form array. Overrides FormStateInterface::setCompleteForm
FormState::setError public function Flags an element as having an error. Overrides FormStateInterface::setError
FormState::setErrorByName public function Files an error against a form element. Overrides FormStateInterface::setErrorByName
FormState::setExecuted public function Sets that the form was submitted and has been processed and executed. Overrides FormStateInterface::setExecuted
FormState::setFormObject public function Sets the form object that is responsible for building this form. Overrides FormStateInterface::setFormObject
FormState::setFormState public function Sets the value of the form state. Overrides FormStateInterface::setFormState
FormState::setGroups public function Sets references to details elements to render them within vertical tabs. Overrides FormStateInterface::setGroups
FormState::setHasFileElement public function Sets that this form has a file element. Overrides FormStateInterface::setHasFileElement
FormState::setInvalidToken public function Flags the form state as having or not an invalid token. Overrides FormStateInterface::setInvalidToken
FormState::setLimitValidationErrors public function Sets the limited validation error sections. Overrides FormStateInterface::setLimitValidationErrors
FormState::setMethod public function Sets the HTTP method to use for the form's submission. Overrides FormStateInterface::setMethod
FormState::setProcessInput public function Sets that the form should process input. Overrides FormStateInterface::setProcessInput
FormState::setProgrammed public function Sets that this form was submitted programmatically. Overrides FormStateInterface::setProgrammed
FormState::setProgrammedBypassAccessCheck public function Sets if this form submission should bypass #access. Overrides FormStateInterface::setProgrammedBypassAccessCheck
FormState::setRebuild public function Sets the form to be rebuilt after processing. Overrides FormStateInterface::setRebuild
FormState::setRebuildInfo public function Sets the rebuild info. Overrides FormStateInterface::setRebuildInfo
FormState::setRedirect public function Sets the redirect for the form. Overrides FormStateInterface::setRedirect
FormState::setRedirectUrl public function Sets the redirect URL for the form. Overrides FormStateInterface::setRedirectUrl
FormState::setRequestMethod public function Sets the HTTP method used by the request that is building the form. Overrides FormStateInterface::setRequestMethod
FormState::setResponse public function Sets a response for this form. Overrides FormStateInterface::setResponse
FormState::setStorage public function Sets the entire set of arbitrary data. Overrides FormStateInterface::setStorage
FormState::setSubmitHandlers public function Sets the submit handlers. Overrides FormStateInterface::setSubmitHandlers
FormState::setSubmitted public function Sets that the form has been submitted. Overrides FormStateInterface::setSubmitted
FormState::setTemporary public function Sets temporary data. Overrides FormStateInterface::setTemporary
FormState::setTemporaryValue public function Sets an arbitrary value in temporary storage. Overrides FormStateInterface::setTemporaryValue
FormState::setTriggeringElement public function Sets the form element that triggered submission. Overrides FormStateInterface::setTriggeringElement
FormState::setUserInput public function Sets the form values as though they were submitted by a user. Overrides FormStateInterface::setUserInput
FormState::setValidateHandlers public function Sets the validate handlers. Overrides FormStateInterface::setValidateHandlers
FormState::setValidationComplete public function Sets that validation has been completed. Overrides FormStateInterface::setValidationComplete
FormState::setValidationEnforced public function Enforces that validation is run. Overrides FormStateInterface::setValidationEnforced
FormStateValuesTrait::getValue public function Implements \Drupal\Core\Form\FormStateInterface::getValue()
FormStateValuesTrait::hasValue public function Implements \Drupal\Core\Form\FormStateInterface::hasValue()
FormStateValuesTrait::isValueEmpty public function Implements \Drupal\Core\Form\FormStateInterface::isValueEmpty()
FormStateValuesTrait::setValue public function Implements \Drupal\Core\Form\FormStateInterface::setValue()
FormStateValuesTrait::setValueForElement public function Implements \Drupal\Core\Form\FormStateInterface::setValueForElement()
FormStateValuesTrait::setValues public function Implements \Drupal\Core\Form\FormStateInterface::setValues()
FormStateValuesTrait::unsetValue public function Implements \Drupal\Core\Form\FormStateInterface::unsetValue()