diff --git a/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php b/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php index 5edec7f0e5dc24dcdf52fc50425eb6825322189d..ae174d54a7efaf62709a580310f67dee653c9c4f 100644 --- a/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php +++ b/core/modules/layout_builder/src/Cache/LayoutBuilderIsActiveCacheContext.php @@ -4,15 +4,17 @@ use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Cache\Context\CalculatedCacheContextInterface; +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\layout_builder\OverridesSectionStorageInterface; +use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface; /** * Determines whether Layout Builder is active for a given entity type or not. * * Cache context ID: 'layout_builder_is_active:%entity_type_id', e.g. - * 'layout_builder_is_active:node' (to vary by whether the Node entity type has - * Layout Builder enabled). + * 'layout_builder_is_active:node' (to vary by whether custom layout overrides + * are allowed for the Node entity specified by the route parameter). * * @internal * Tagged services are internal. @@ -81,8 +83,14 @@ public function getCacheableMetadata($entity_type_id = NULL) { */ protected function getDisplay($entity_type_id) { if ($entity = $this->routeMatch->getParameter($entity_type_id)) { - if ($entity instanceof OverridesSectionStorageInterface) { - return $entity->getDefaultSectionStorage(); + if ($entity instanceof FieldableEntityInterface) { + // @todo Expand to work for all view modes in + // https://www.drupal.org/node/2907413. + $view_mode = 'full'; + $display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode); + if ($display instanceof LayoutEntityDisplayInterface) { + return $display; + } } } } diff --git a/core/modules/layout_builder/tests/src/Unit/LayoutBuilderIsActiveCacheContextTest.php b/core/modules/layout_builder/tests/src/Unit/LayoutBuilderIsActiveCacheContextTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f62e0428950b95a99b778596446859957102c06f --- /dev/null +++ b/core/modules/layout_builder/tests/src/Unit/LayoutBuilderIsActiveCacheContextTest.php @@ -0,0 +1,110 @@ +<?php + +namespace Drupal\Tests\layout_builder\Unit; + +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Entity\FieldableEntityInterface; +use Drupal\Core\Entity\Query\QueryInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\layout_builder\Cache\LayoutBuilderIsActiveCacheContext; +use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface; +use Drupal\Tests\UnitTestCase; +use Prophecy\Argument; + +/** + * @coversDefaultClass \Drupal\layout_builder\Cache\LayoutBuilderIsActiveCacheContext + * + * @group layout_builder + */ +class LayoutBuilderIsActiveCacheContextTest extends UnitTestCase { + + /** + * @covers ::getContext + */ + public function testGetContextMissingEntityTypeId() { + $route_match = $this->prophesize(RouteMatchInterface::class); + $cache_context = new LayoutBuilderIsActiveCacheContext($route_match->reveal()); + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Missing entity type ID'); + $cache_context->getContext(); + } + + /** + * @covers ::getContext + * @covers ::getDisplay + */ + public function testGetContextNonFieldableEntity() { + $route_match = $this->prophesize(RouteMatchInterface::class); + $route_match->getParameter('not_a_fieldable_entity')->willReturn('something that is not a fieldable entity'); + + $cache_context = new LayoutBuilderIsActiveCacheContext($route_match->reveal()); + $expected = '0'; + $actual = $cache_context->getContext('not_a_fieldable_entity'); + $this->assertSame($expected, $actual); + } + + /** + * @covers ::getContext + * @covers ::getDisplay + * + * @dataProvider providerTestGetContext + */ + public function testGetContext($is_overridden, $expected) { + $entity_display = $this->prophesize(LayoutEntityDisplayInterface::class); + $entity_display->isOverridable()->willReturn($is_overridden); + + $entity_type_id = 'a_fieldable_entity_type'; + $fieldable_entity = $this->prophesize(FieldableEntityInterface::class); + $fieldable_entity->getEntityTypeId()->willReturn($entity_type_id); + $fieldable_entity->bundle()->willReturn('the_bundle_id'); + + $route_match = $this->prophesize(RouteMatchInterface::class); + $route_match->getParameter($entity_type_id)->willReturn($fieldable_entity->reveal()); + + // \Drupal\Core\Entity\Entity\EntityViewDisplay::collectRenderDisplay() is a + // static method and can not be mocked on its own. All of the expectations + // of that method are mocked in the next code block. + $entity_query = $this->prophesize(QueryInterface::class); + $entity_query->condition(Argument::cetera())->willReturn($entity_query); + $entity_query->execute()->willReturn([ + 'a_fieldable_entity_type.the_bundle_id.full' => 'a_fieldable_entity_type.the_bundle_id.full', + ]); + $entity_storage = $this->prophesize(EntityStorageInterface::class); + $entity_storage->getQuery('AND')->willReturn($entity_query->reveal()); + $entity_storage->loadMultiple(Argument::type('array'))->willReturn([ + 'a_fieldable_entity_type.the_bundle_id.full' => $entity_display->reveal(), + ]); + $entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class); + $entity_type_manager->getStorage('entity_view_display')->willReturn($entity_storage->reveal()); + $module_handler = $this->prophesize(ModuleHandlerInterface::class); + + $container = new ContainerBuilder(); + $container->set('entity_type.manager', $entity_type_manager->reveal()); + $container->set('module_handler', $module_handler->reveal()); + \Drupal::setContainer($container); + + $cache_context = new LayoutBuilderIsActiveCacheContext($route_match->reveal()); + $actual = $cache_context->getContext($entity_type_id); + $this->assertSame($expected, $actual); + } + + /** + * Provides test data for ::testGetContext(). + */ + public function providerTestGetContext() { + $data = []; + $data['overridden'] = [ + TRUE, + '1', + ]; + $data['not overridden'] = [ + FALSE, + '0', + ]; + return $data; + } + +}