Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
77.66% |
73 / 94 |
CRAP | |
79.82% |
178 / 223 |
| FormState | |
0.00% |
0 / 1 |
|
77.66% |
73 / 94 |
247.32 | |
79.82% |
178 / 223 |
| setFormState | |
100.00% |
1 / 1 |
3 | |
100.00% |
5 / 5 |
|||
| setAlwaysProcess | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getAlwaysProcess | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setButtons | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getButtons | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setCached | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
| isCached | |
100.00% |
1 / 1 |
2 | |
100.00% |
1 / 1 |
|||
| disableCache | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| setExecuted | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isExecuted | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setGroups | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getGroups | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| setHasFileElement | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| hasFileElement | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setLimitValidationErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getLimitValidationErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setMethod | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isMethodType | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setRequestMethod | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isRequestMethodSafe | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setValidationEnforced | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| isValidationEnforced | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| disableRedirect | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| isRedirectDisabled | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setProcessInput | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isProcessingInput | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setProgrammed | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isProgrammed | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setProgrammedBypassAccessCheck | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| isBypassingProgrammedAccessChecks | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setRebuildInfo | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getRebuildInfo | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| addRebuildInfo | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| setStorage | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getStorage | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| setSubmitHandlers | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getSubmitHandlers | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setSubmitted | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isSubmitted | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setTemporary | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getTemporary | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getTemporaryValue | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| setTemporaryValue | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| hasTemporaryValue | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| setTriggeringElement | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getTriggeringElement | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setValidateHandlers | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getValidateHandlers | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setValidationComplete | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isValidationComplete | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| loadInclude | |
100.00% |
1 / 1 |
4 | |
100.00% |
12 / 12 |
|||
| getCacheableArray | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 9 |
|||
| setCompleteForm | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getCompleteForm | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| get | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| set | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| has | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| setBuildInfo | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getBuildInfo | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| addBuildInfo | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| getUserInput | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setUserInput | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getValues | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getValue | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
| setValues | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| setValue | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| unsetValue | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| hasValue | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
| isValueEmpty | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
| setValueForElement | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setResponse | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getResponse | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setRedirect | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| setRedirectUrl | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getRedirect | |
100.00% |
1 / 1 |
4 | |
100.00% |
7 / 7 |
|||
| setAnyErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| hasAnyErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setErrorByName | |
100.00% |
1 / 1 |
7 | |
100.00% |
17 / 17 |
|||
| setError | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| clearErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| getError | |
100.00% |
1 / 1 |
4 | |
100.00% |
8 / 8 |
|||
| getErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setRebuild | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| isRebuilding | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| prepareCallback | |
100.00% |
1 / 1 |
3 | |
100.00% |
3 / 3 |
|||
| setFormObject | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| getFormObject | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getCleanValueKeys | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| setCleanValueKeys | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| addCleanValueKey | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| cleanValues | |
100.00% |
1 / 1 |
5 | |
100.00% |
10 / 10 |
|||
| setInvalidToken | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| hasInvalidToken | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| moduleLoadInclude | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\Core\Form\FormState. | |
| */ | |
| namespace Drupal\Core\Form; | |
| use Drupal\Component\Utility\NestedArray; | |
| use Drupal\Core\Url; | |
| use Symfony\Component\HttpFoundation\Response; | |
| /** | |
| * Stores information about the state of a form. | |
| */ | |
| class FormState implements FormStateInterface { | |
| /** | |
| * 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 = array( | |
| 'args' => array(), | |
| 'files' => array(), | |
| ); | |
| /** | |
| * Similar to self::$build_info, but pertaining to | |
| * \Drupal\Core\Form\FormBuilderInterface::rebuildForm(). | |
| * | |
| * This property is uncacheable. | |
| * | |
| * @var array | |
| */ | |
| protected $rebuild_info = array(); | |
| /** | |
| * 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 its 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 = array(); | |
| /** | |
| * 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 | |
| */ | |
| 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 = array(); | |
| /** | |
| * 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 = array(); | |
| /** | |
| * A list containing copies of all submit and button elements in the form. | |
| * | |
| * This property is uncacheable. | |
| * | |
| * @var array | |
| */ | |
| protected $buttons = array(); | |
| /** | |
| * 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 = array(); | |
| /** | |
| * 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. | |
| * | |
| * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 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() | |
| */ | |
| protected function isRequestMethodSafe() { | |
| return in_array($this->requestMethod, array('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"] = array( | |
| '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 &getValue($key, $default = NULL) { | |
| $exists = NULL; | |
| $value = &NestedArray::getValue($this->getValues(), (array) $key, $exists); | |
| if (!$exists) { | |
| $value = $default; | |
| } | |
| return $value; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function setValues(array $values) { | |
| $this->values = $values; | |
| return $this; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function setValue($key, $value) { | |
| NestedArray::setValue($this->getValues(), (array) $key, $value, TRUE); | |
| return $this; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function unsetValue($key) { | |
| NestedArray::unsetValue($this->getValues(), (array) $key); | |
| return $this; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function hasValue($key) { | |
| $exists = NULL; | |
| $value = NestedArray::getValue($this->getValues(), (array) $key, $exists); | |
| return $exists && isset($value); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function isValueEmpty($key) { | |
| $exists = NULL; | |
| $value = NestedArray::getValue($this->getValues(), (array) $key, $exists); | |
| return !$exists || empty($value); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function setValueForElement(array $element, $value) { | |
| return $this->setValue($element['#parents'], $value); | |
| } | |
| /** | |
| * {@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(), array $options = array()) { | |
| $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 = array(); | |
| 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: | |
| // array('foo', 'bar', 'baz') | |
| // then the corresponding self::getValues() part will look like this: | |
| // array( | |
| // 'foo' => array( | |
| // 'bar' => array( | |
| // 'baz' => 'button_value', | |
| // ), | |
| // ), | |
| // ) | |
| // 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); | |
| } | |
| } |