.../Core/Render/PlaceholderingRenderCache.php | 5 ++++ core/lib/Drupal/Core/Render/Renderer.php | 4 ++- .../Tests/Core/Render/RendererPlaceholdersTest.php | 35 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/core/lib/Drupal/Core/Render/PlaceholderingRenderCache.php b/core/lib/Drupal/Core/Render/PlaceholderingRenderCache.php index 8b71048..4256283 100644 --- a/core/lib/Drupal/Core/Render/PlaceholderingRenderCache.php +++ b/core/lib/Drupal/Core/Render/PlaceholderingRenderCache.php @@ -126,6 +126,11 @@ public function get(array $elements) { public function set(array &$elements, array $pre_bubbling_elements) { $result = parent::set($elements, $pre_bubbling_elements); + // @todo remove this check when https://www.drupal.org/node/2367555 lands. + if (!$this->requestStack->getCurrentRequest()->isMethodSafe()) { + return FALSE; + } + if ($this->placeholderGenerator->canCreatePlaceholder($pre_bubbling_elements) && $this->placeholderGenerator->shouldAutomaticallyPlaceholder($elements)) { // Overwrite $elements with a placeholder. The Renderer (which called this // method) will update the context with the bubbleable metadata of the diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index 3c13dfd..09a1bf1 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -338,7 +338,9 @@ protected function doRender(&$elements, $is_root_call = FALSE) { // If instructed to create a placeholder, and a #lazy_builder callback is // present (without such a callback, it would be impossible to replace the // placeholder), replace the current element with a placeholder. - if (isset($elements['#create_placeholder']) && $elements['#create_placeholder'] === TRUE) { + // @todo remove the isMethodSafe() check when + // https://www.drupal.org/node/2367555 lands. + if (isset($elements['#create_placeholder']) && $elements['#create_placeholder'] === TRUE && $this->requestStack->getCurrentRequest()->isMethodSafe()) { if (!isset($elements['#lazy_builder'])) { throw new \LogicException('When #create_placeholder is set, a #lazy_builder callback must be present as well.'); } diff --git a/core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php b/core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php index 5fd49a7..133d5f6 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Cache\Cache; use Drupal\Core\Render\Markup; +use Drupal\Core\Render\RenderContext; /** * @coversDefaultClass \Drupal\Core\Render\Renderer @@ -782,6 +783,40 @@ public function testCacheableParentWithPostRequest($test_element, $args) { } /** + * @covers ::render + * @covers ::doRender + * @covers \Drupal\Core\Render\RenderCache::get + * @covers \Drupal\Core\Render\PlaceholderingRenderCache::get + * @covers \Drupal\Core\Render\PlaceholderingRenderCache::set + * @covers ::replacePlaceholders + * + * @dataProvider providerPlaceholders + */ + public function testPlaceholderingDisabledForPostRequests($test_element, $args) { + $this->setUpUnusedCache(); + $this->setUpRequest('POST'); + + $element = $test_element; + + // Render without replacing placeholders, to allow this test to see which + // #attached[placeholders] there are, if any. + $this->renderer->executeInRenderContext(new RenderContext(), function () use (&$element) { + return $this->renderer->render($element); + }); + // Only test cases where the placeholders have been specified manually are + // allowed to have placeholders. This means that of the different situations + // listed in providerPlaceholders(), only type B can have attached + // placeholders. Everything else, whether: + // 1. manual placeholdering + // 2. automatic placeholdering via already-present cacheability metadata + // 3. automatic placeholdering via bubbled cacheability metadata + // All three of those should NOT result in placeholders. + if (!isset($test_element['#attached']['placeholders'])) { + $this->assertFalse(isset($element['#attached']['placeholders']), 'No placeholders created.'); + } + } + + /** * Tests a placeholder that adds another placeholder. * * E.g. when rendering a node in a placeholder the rendering of that node