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); | |
} | |
} |