3 namespace Drupal\form_test\Form;
5 use Drupal\Component\Utility\Html;
6 use Drupal\Core\Form\FormBase;
7 use Drupal\Core\Form\FormStateInterface;
10 * A multistep form for testing the form storage.
12 * It uses two steps for editing a virtual "thing". Any changes to it are saved
13 * in the form storage and have to be present during any step. By setting the
14 * request parameter "cache" the form can be tested with caching enabled, as
15 * it would be the case, if the form would contain some #ajax callbacks.
19 class FormTestStorageForm extends FormBase {
24 public function getFormId() {
25 return 'form_test_storage_form';
31 public function buildForm(array $form, FormStateInterface $form_state) {
32 if ($form_state->isRebuilding()) {
33 $form_state->setUserInput([]);
36 $storage = $form_state->getStorage();
37 if (empty($storage)) {
38 $user_input = $form_state->getUserInput();
39 if (empty($user_input)) {
40 $_SESSION['constructions'] = 0;
42 // Put the initial thing into the storage
49 $form_state->setStorage($storage);
51 // Count how often the form is constructed.
52 $_SESSION['constructions']++;
53 drupal_set_message("Form constructions: " . $_SESSION['constructions']);
56 '#type' => 'textfield',
58 '#default_value' => $storage['thing']['title'],
62 '#type' => 'textfield',
64 '#default_value' => $storage['thing']['value'],
65 '#element_validate' => ['::elementValidateValueCached'],
67 $form['continue_button'] = [
70 // Rebuilds the form without keeping the values.
72 $form['continue_submit'] = [
74 '#value' => 'Continue submit',
75 '#submit' => ['::continueSubmitForm'],
82 // @todo Remove this in https://www.drupal.org/node/2524408, because form
83 // cache immutability is no longer necessary, because we no longer cache
84 // forms during safe HTTP methods. In the meantime, because
85 // Drupal\system\Tests\Form still has test coverage for a poisoned form
86 // cache following a GET request, trick $form_state into caching the form
87 // to keep that test working until we either remove it or change it in
89 if ($this->getRequest()->get('immutable')) {
90 $form_state->addBuildInfo('immutable', TRUE);
91 if ($this->getRequest()->get('cache') && $this->getRequest()->isMethodCacheable()) {
92 $form_state->setRequestMethod('FAKE');
93 $form_state->setCached();
103 public function validateForm(array &$form, FormStateInterface $form_state) {
104 if ($this->getRequest()->get('cache')) {
105 // Manually activate caching, so we can test that the storage keeps working
106 // when it's enabled.
107 $form_state->setCached();
112 * Form element validation handler for 'value' element.
114 * Tests updating of cached form storage during validation.
116 public function elementValidateValueCached($element, FormStateInterface $form_state) {
117 // If caching is enabled and we receive a certain value, change the storage.
118 // This presumes that another submitted form value triggers a validation error
119 // elsewhere in the form. Form API should still update the cached form storage
121 if ($this->getRequest()->get('cache') && $form_state->getValue('value') == 'change_title') {
122 $form_state->set(['thing', 'changed'], TRUE);
129 public function continueSubmitForm(array &$form, FormStateInterface $form_state) {
130 $form_state->set(['thing', 'title'], $form_state->getValue('title'));
131 $form_state->set(['thing', 'value'], $form_state->getValue('value'));
132 $form_state->setRebuild();
138 public function submitForm(array &$form, FormStateInterface $form_state) {
139 drupal_set_message("Title: " . Html::escape($form_state->getValue('title')));
140 drupal_set_message("Form constructions: " . $_SESSION['constructions']);
141 if ($form_state->has(['thing', 'changed'])) {
142 drupal_set_message("The thing has been changed.");
144 $form_state->setRedirect('<front>');