diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index 1f74692..350286f 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -19,6 +19,7 @@ use Drupal\Core\Form\Exception\BrokenPostRequestException; use Drupal\Core\Render\Element; use Drupal\Core\Render\ElementInfoManagerInterface; +use Drupal\Core\Site\Settings; use Drupal\Core\Theme\ThemeManagerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -603,8 +604,7 @@ public function processForm($form_id, &$form, FormStateInterface &$form_state) { } /** - * #lazy_builder callback; this renders a placeholder that's used in a form - * action to use the current request's url + * #lazy_builder callback; renders a form action URL. * * @return array * A renderable array representing the form action. @@ -613,7 +613,7 @@ public function renderPlaceholderFormAction() { return [ '#type' => 'markup', '#markup' => $this->buildFormAction(), - '#cache' => ['max-age' => 0], + '#cache' => ['contexts' => ['url']], ]; } @@ -627,13 +627,15 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) { // Only update the action if it is not already set. if (!isset($form['#action'])) { - $placeholder = hash('sha1', $form_id); + // Generate a placeholder and a render array to replace it. + $placeholder = hash('sha1', 'form_action'); $placeholder_render_array = [ '#lazy_builder' => ['form_builder:renderPlaceholderFormAction', []], ]; - // Attach the lazy builder to the form and add the placeholder in the form - // action so the #lazy_builder callback knows what to replace. + // Instead of setting an actual action URL, we set the placeholder, which + // will be replaced at the very last moment. This ensures forms with + // dynamically generated action URLs don't break cacheability. $form['#attached']['placeholders'][$placeholder] = $placeholder_render_array; $form['#action'] = $placeholder; } diff --git a/core/modules/block/src/Tests/BlockFormInBlockTest.php b/core/modules/block/src/Tests/BlockFormInBlockTest.php index 203776b..ea2fbdd 100644 --- a/core/modules/block/src/Tests/BlockFormInBlockTest.php +++ b/core/modules/block/src/Tests/BlockFormInBlockTest.php @@ -39,12 +39,8 @@ class BlockFormInBlockTest extends WebTestBase { protected $normalUser; /** - * The block used by this test. - * - * @var \Drupal\block\BlockInterface + * {@inheritdoc} */ - protected $block; - protected function setUp() { parent::setUp(); @@ -57,11 +53,11 @@ protected function setUp() { $this->drupalLogin($this->normalUser); // Enable our test block. - $this->block = $this->drupalPlaceBlock('test_form_in_block'); + $this->drupalPlaceBlock('test_form_in_block'); } /** - * Test to see if form in block's redirect isn't cached + * Test to see if form in block's redirect isn't cached. */ function testCachePerPage() { $form_values = ['email' => 'test@example.com']; @@ -71,9 +67,9 @@ function testCachePerPage() { $this->assertResponse(200); $this->assertText('Your .com email address.', 'form found'); + // Make sure that we're currently still on /test-page after submitting the + // form. $this->drupalPostForm(NULL, $form_values, t('Submit')); - - // Make sure that we're currently still on /test-page $this->assertUrl('test-page'); $this->assertText(t('Your email address is @email', ['@email' => 'test@example.com'])); @@ -82,13 +78,50 @@ function testCachePerPage() { $this->assertResponse(200); $this->assertText('Your .com email address.', 'form found'); + // Make sure that submitting the form didn't redirect us to the first page + // we submitted the form from after submitting the form from + // /test-render-title. $this->drupalPostForm(NULL, $form_values, t('Submit')); - - // Make sure that submitting the form didn't redirect us to the first - // page we submitted the form from. $this->assertUrl('test-render-title'); $this->assertText(t('Your email address is @email', ['@email' => 'test@example.com'])); + } + + /** + * When there are two forms on the same page, that + */ + public function testMultipleFormsPerPage() { + $this->drupalPlaceBlock('test_favorite_animal_in_block'); + + // Go to "test-page" and test if the block are enabled. + $this->drupalGet('test-page'); + $this->assertResponse(200); + $this->assertText('Your .com email address.', 'form found'); + $this->assertText('Your favorite animal.', 'Favorite Animal form found'); + + // Make sure that we're currently still on /test-page after submitting the + // form. + $this->drupalPostForm(NULL, ['email' => 'test@example.com'], t('Submit')); + $this->assertUrl('test-page'); + $this->assertText(t('Your email address is @email', ['@email' => 'test@example.com'])); + + // Make sure that we're currently still on /test-page after submitting the + // second form. + $this->drupalPostForm(NULL, ['favorite_animal' => 'Llama'], t('Submit your chosen animal')); + $this->assertUrl('test-page'); + $this->assertText(t('Your favorite animal is: @favorite_animal', ['@favorite_animal' => 'Llama'])); + // Go to a different page and see if the blocks are enabled there as well. + $this->drupalGet('test-render-title'); + $this->assertResponse(200); + $this->assertText('Your .com email address.', 'form found'); + $this->assertText('Your favorite animal.', 'Favorite Animal form found'); + + // Make sure that submitting the form didn't redirect us to the first page + // we submitted the form from after submitting the form from + // /test-render-title. + $this->drupalPostForm(NULL, ['favorite_animal' => 'kitten'], t('Submit your chosen animal')); + $this->assertUrl('test-render-title'); + $this->assertText(t('Your favorite animal is: @favorite_animal', ['@favorite_animal' => 'kitten'])); } } diff --git a/core/modules/block/tests/modules/block_test/src/Form/FavoriteAnimalTestForm.php b/core/modules/block/tests/modules/block_test/src/Form/FavoriteAnimalTestForm.php new file mode 100644 index 0000000..2e40675 --- /dev/null +++ b/core/modules/block/tests/modules/block_test/src/Form/FavoriteAnimalTestForm.php @@ -0,0 +1,46 @@ + 'textfield', + '#title' => $this->t('Your favorite animal.') + ]; + + $form['submit_animal'] = [ + '#type' => 'submit', + '#value' => $this->t('Submit your chosen animal'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + drupal_set_message($this->t('Your favorite animal is: @favorite_animal', ['@favorite_animal' => $form['favorite_animal']['#value']])); + } + +} diff --git a/core/modules/block/tests/modules/block_test/src/Form/TestForm.php b/core/modules/block/tests/modules/block_test/src/Form/TestForm.php index de0f6af..c0a0694 100644 --- a/core/modules/block/tests/modules/block_test/src/Form/TestForm.php +++ b/core/modules/block/tests/modules/block_test/src/Form/TestForm.php @@ -23,7 +23,6 @@ public function getFormId() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { - $form['email'] = [ '#type' => 'email', '#title' => $this->t('Your .com email address.') diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Block/FavoriteAnimalFormBlock.php b/core/modules/block/tests/modules/block_test/src/Plugin/Block/FavoriteAnimalFormBlock.php new file mode 100644 index 0000000..9129686 --- /dev/null +++ b/core/modules/block/tests/modules/block_test/src/Plugin/Block/FavoriteAnimalFormBlock.php @@ -0,0 +1,29 @@ +getForm('Drupal\block_test\Form\FavoriteAnimalTestForm'); + } + +} diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestFormBlock.php b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestFormBlock.php index ea503b6..feeb9df 100644 --- a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestFormBlock.php +++ b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestFormBlock.php @@ -23,9 +23,7 @@ class TestFormBlock extends BlockBase { * {@inheritdoc} */ public function build() { - $form = \Drupal::formBuilder()->getForm('Drupal\block_test\Form\TestForm'); - - return $form; + return \Drupal::formBuilder()->getForm('Drupal\block_test\Form\TestForm'); } }