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.
17 class FormTestStorageForm extends FormBase {
22 public function getFormId() {
23 return 'form_test_storage_form';
29 public function buildForm(array $form, FormStateInterface $form_state) {
30 if ($form_state->isRebuilding()) {
31 $form_state->setUserInput([]);
34 $storage = $form_state->getStorage();
35 if (empty($storage)) {
36 $user_input = $form_state->getUserInput();
37 if (empty($user_input)) {
38 $_SESSION['constructions'] = 0;
40 // Put the initial thing into the storage
47 $form_state->setStorage($storage);
49 // Count how often the form is constructed.
50 $_SESSION['constructions']++;
51 drupal_set_message("Form constructions: " . $_SESSION['constructions']);
54 '#type' => 'textfield',
56 '#default_value' => $storage['thing']['title'],
60 '#type' => 'textfield',
62 '#default_value' => $storage['thing']['value'],
63 '#element_validate' => ['::elementValidateValueCached'],
65 $form['continue_button'] = [
68 // Rebuilds the form without keeping the values.
70 $form['continue_submit'] = [
72 '#value' => 'Continue submit',
73 '#submit' => ['::continueSubmitForm'],
80 // @todo Remove this in https://www.drupal.org/node/2524408, because form
81 // cache immutability is no longer necessary, because we no longer cache
82 // forms during safe HTTP methods. In the meantime, because
83 // Drupal\system\Tests\Form still has test coverage for a poisoned form
84 // cache following a GET request, trick $form_state into caching the form
85 // to keep that test working until we either remove it or change it in
87 if ($this->getRequest()->get('immutable')) {
88 $form_state->addBuildInfo('immutable', TRUE);
89 if ($this->getRequest()->get('cache') && $this->getRequest()->isMethodSafe()) {
90 $form_state->setRequestMethod('FAKE');
91 $form_state->setCached();
101 public function validateForm(array &$form, FormStateInterface $form_state) {
102 if ($this->getRequest()->get('cache')) {
103 // Manually activate caching, so we can test that the storage keeps working
104 // when it's enabled.
105 $form_state->setCached();
110 * Form element validation handler for 'value' element.
112 * Tests updating of cached form storage during validation.
114 public function elementValidateValueCached($element, FormStateInterface $form_state) {
115 // If caching is enabled and we receive a certain value, change the storage.
116 // This presumes that another submitted form value triggers a validation error
117 // elsewhere in the form. Form API should still update the cached form storage
119 if ($this->getRequest()->get('cache') && $form_state->getValue('value') == 'change_title') {
120 $form_state->set(['thing', 'changed'], TRUE);
127 public function continueSubmitForm(array &$form, FormStateInterface $form_state) {
128 $form_state->set(['thing', 'title'], $form_state->getValue('title'));
129 $form_state->set(['thing', 'value'], $form_state->getValue('value'));
130 $form_state->setRebuild();
136 public function submitForm(array &$form, FormStateInterface $form_state) {
137 drupal_set_message("Title: " . Html::escape($form_state->getValue('title')));
138 drupal_set_message("Form constructions: " . $_SESSION['constructions']);
139 if ($form_state->has(['thing', 'changed'])) {
140 drupal_set_message("The thing has been changed.");
142 $form_state->setRedirect('<front>');