From 038e65153847cd7111ec478672efa908daf86431 Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Thu, 25 Jan 2024 10:00:41 +0000 Subject: [PATCH] Issue #3190542 by godotislate, clayfreeman, tim.plunkett, neclimdul, smustgrave, acbramley: Layout Builder overrides section storage sets local tasks block cache max-age to 0 on content entity pages without overrides enabled (cherry picked from commit 40a48863628158744b9b16c54efbd7364be1de5e) --- .../OverridesSectionStorage.php | 10 +- .../Functional/LayoutBuilderLocalTaskTest.php | 111 ++++++++++++++++++ .../src/Functional/LayoutSectionTest.php | 2 +- .../src/Unit/OverridesSectionStorageTest.php | 2 +- 4 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 core/modules/layout_builder/tests/src/Functional/LayoutBuilderLocalTaskTest.php diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php index e762ac839711..4f020bab8de5 100644 --- a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php +++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php @@ -188,7 +188,9 @@ public function deriveContextsFromRoute($value, $definition, $name, array $defau * The route defaults array. * * @return \Drupal\Core\Entity\EntityInterface|null - * The entity for the route, or NULL if none exist. + * The entity for the route, or NULL if none exist. The entity is not + * guaranteed to be fieldable, or contain the necessary field for this + * section storage plugin. * * @see \Drupal\layout_builder\SectionStorageInterface::deriveContextsFromRoute() * @see \Drupal\Core\ParamConverter\ParamConverterInterface::convert() @@ -206,9 +208,7 @@ private function extractEntityFromRoute($value, array $defaults) { } $entity = $this->entityRepository->getActive($entity_type_id, $entity_id); - if ($entity instanceof FieldableEntityInterface && $entity->hasField(static::FIELD_NAME)) { - return $entity; - } + return ($entity instanceof FieldableEntityInterface) ? $entity : NULL; } /** @@ -359,6 +359,8 @@ public function access($operation, AccountInterface $account = NULL, $return_as_ // Access also depends on the default being enabled. $result = $result->andIf($this->getDefaultSectionStorage()->access($operation, $account, TRUE)); + // Access also depends on the default layout being overridable. + $result = $result->andIf(AccessResult::allowedIf($this->getDefaultSectionStorage()->isOverridable())->addCacheableDependency($this->getDefaultSectionStorage())); $result = $this->handleTranslationAccess($result, $operation, $account); return $return_as_object ? $result : $result->isAllowed(); } diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderLocalTaskTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderLocalTaskTest.php new file mode 100644 index 000000000000..1e485554ec67 --- /dev/null +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderLocalTaskTest.php @@ -0,0 +1,111 @@ +<?php + +namespace Drupal\Tests\layout_builder\Functional; + +use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests Layout Builder local tasks. + * + * @group layout_builder + */ +class LayoutBuilderLocalTaskTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'layout_builder', + 'block', + 'node', + ]; + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->drupalPlaceBlock('local_tasks_block'); + } + + /** + * Tests the cacheability of local tasks with Layout Builder module installed. + */ + public function testLocalTaskLayoutBuilderInstalledCacheability() { + // Create only one bundle and do not enable layout builder on its display. + $this->drupalCreateContentType([ + 'type' => 'bundle_no_lb_display', + ]); + + LayoutBuilderEntityViewDisplay::load('node.bundle_no_lb_display.default') + ->disableLayoutBuilder() + ->save(); + + $node = $this->drupalCreateNode([ + 'type' => 'bundle_no_lb_display', + ]); + + $assert_session = $this->assertSession(); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + ])); + + $this->drupalGet('node/' . $node->id()); + $assert_session->responseHeaderEquals('X-Drupal-Cache-Max-Age', '-1 (Permanent)'); + $assert_session->statusCodeEquals(200); + } + + /** + * Tests the cacheability of local tasks with multiple content types. + */ + public function testLocalTaskMultipleContentTypesCacheability() { + // Test when there are two content types, one with a display having Layout + // Builder enabled with overrides, and another with display not having + // Layout Builder enabled. + $this->drupalCreateContentType([ + 'type' => 'bundle_no_lb_display', + ]); + LayoutBuilderEntityViewDisplay::load('node.bundle_no_lb_display.default') + ->disableLayoutBuilder() + ->save(); + + $node_without_lb = $this->drupalCreateNode([ + 'type' => 'bundle_no_lb_display', + ]); + + $this->drupalCreateContentType([ + 'type' => 'bundle_with_overrides', + ]); + LayoutBuilderEntityViewDisplay::load('node.bundle_with_overrides.default') + ->enableLayoutBuilder() + ->setOverridable() + ->save(); + + $node_with_overrides = $this->drupalCreateNode([ + 'type' => 'bundle_with_overrides', + ]); + + $assert_session = $this->assertSession(); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + ])); + + $this->drupalGet('node/' . $node_without_lb->id()); + $assert_session->responseHeaderEquals('X-Drupal-Cache-Max-Age', '-1 (Permanent)'); + $assert_session->statusCodeEquals(200); + + $this->drupalGet('node/' . $node_with_overrides->id()); + $assert_session->responseHeaderEquals('X-Drupal-Cache-Max-Age', '-1 (Permanent)'); + $assert_session->statusCodeEquals(200); + } + +} diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php index 3bbc2410dc59..f04478f8b008 100644 --- a/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php +++ b/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php @@ -236,7 +236,7 @@ public function testLayoutUrlNoSectionField() { $node->save(); $this->drupalGet($node->toUrl('canonical')->toString() . '/layout'); - $this->assertSession()->statusCodeEquals(404); + $this->assertSession()->statusCodeEquals(403); } /** diff --git a/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php b/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php index fbab039a0c9c..6510e6289340 100644 --- a/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php +++ b/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php @@ -134,7 +134,7 @@ public function providerTestExtractEntityFromRoute() { [], ]; $data['with value, without layout'] = [ - FALSE, + TRUE, 'my_entity_type', 'my_entity_type.entity_without_layout', [], -- GitLab