diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index d966801..5aaae76 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -313,8 +313,12 @@ public function buildForm($form_id, FormStateInterface &$form_state) { */ public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL) { $form = $this->retrieveForm($form_id, $form_state); - // All rebuilt forms will be cached. - $form_state->setCached(); + + // We don't allow to set state on GET requests. + if ($form_state->isMethodType('POST')) { + // All POST rebuilt forms will be cached. + $form_state->setCached(); + } // If only parts of the form will be returned to the browser (e.g., Ajax or // RIA clients), or if the form already had a new build ID regenerated when diff --git a/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php index 294846a..92e2eb3 100644 --- a/core/lib/Drupal/Core/Form/FormState.php +++ b/core/lib/Drupal/Core/Form/FormState.php @@ -476,7 +476,7 @@ public function getButtons() { */ public function setCached($cache = TRUE) { // We determine whether this is the initial rendering of the form. - if ($this->isMethodType('GET') && !$this->isSubmitted()) { + if ($this->isMethodType('GET')) { throw new \LogicException('Initial form rendering is not allowed to cache the form.'); } $this->cache = (bool) $cache; @@ -487,7 +487,7 @@ public function setCached($cache = TRUE) { * {@inheritdoc} */ public function isCached() { - return empty($this->no_cache) && $this->cache && $this->isMethodType('POST'); + return empty($this->no_cache) && $this->cache; } /** diff --git a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php index 9e53645..c02555b 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php @@ -310,11 +310,51 @@ public function testRebuildForm() { $form_state->addRebuildInfo('copy', ['#build_id' => TRUE]); $this->formBuilder->processForm($form_id, $form, $form_state); $this->assertSame($original_build_id, $form['#build_id']); + $this->assertTrue($form_state->isCached()); // Rebuild the form again, and assert that there is a new build ID. $form_state->setRebuildInfo([]); $form = $this->formBuilder->buildForm($form_arg, $form_state); $this->assertNotSame($original_build_id, $form['#build_id']); + $this->assertTrue($form_state->isCached()); + } + + /** + * Tests the rebuildForm() method for a GET submission. + */ + public function testRebuildFormOnGetRequest() { + $form_id = 'test_form_id'; + $expected_form = $form_id(); + + // The form will be built four times. + $form_arg = $this->getMock('Drupal\Core\Form\FormInterface'); + $form_arg->expects($this->exactly(2)) + ->method('getFormId') + ->will($this->returnValue($form_id)); + $form_arg->expects($this->exactly(4)) + ->method('buildForm') + ->will($this->returnValue($expected_form)); + + // Do an initial build of the form and track the build ID. + $form_state = new FormState(); + $form_state->setMethod('GET'); + $form = $this->formBuilder->buildForm($form_arg, $form_state); + $original_build_id = $form['#build_id']; + + // Rebuild the form, and assert that the build ID has not changed. + $form_state->setRebuild(); + $input['form_id'] = $form_id; + $form_state->setUserInput($input); + $form_state->addRebuildInfo('copy', ['#build_id' => TRUE]); + $this->formBuilder->processForm($form_id, $form, $form_state); + $this->assertSame($original_build_id, $form['#build_id']); + $this->assertFalse($form_state->isCached()); + + // Rebuild the form again, and assert that there is a new build ID. + $form_state->setRebuildInfo([]); + $form = $this->formBuilder->buildForm($form_arg, $form_state); + $this->assertNotSame($original_build_id, $form['#build_id']); + $this->assertFalse($form_state->isCached()); } /** diff --git a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php index fe73b5f..aac4094 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php @@ -427,7 +427,7 @@ public function testIsCached($cache_key, $no_cache_key, $expected) { $this->assertSame($expected, $form_state->isCached()); $form_state->setMethod('GET'); - $this->assertSame(FALSE, $form_state->isCached()); + $this->assertSame($expected, $form_state->isCached()); } /** @@ -491,19 +491,6 @@ public function testSetCachedGet() { } /** - * @covers ::setCached - */ - public function testSetCachedGetWithSubmission() { - $form_state = new FormState(); - $form_state->setMethod('GET'); - $form_state->setSubmitted(); - $form_state->setCached(); - - // GET form submissions should not be cached. - $this->assertFalse($form_state->isCached()); - } - - /** * @covers ::isMethodType * @covers ::setMethod *