diff --git a/src/Entity/PageViewBuilder.php b/src/Entity/PageViewBuilder.php index aa6ded5..26e21b6 100644 --- a/src/Entity/PageViewBuilder.php +++ b/src/Entity/PageViewBuilder.php @@ -64,16 +64,10 @@ public static function createInstance(ContainerInterface $container, EntityTypeI public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) { $build = []; /** @var \Drupal\page_manager\PageInterface $entity */ - if ($display_variant = $entity->getVariant($this->routeMatch->getParameter('variant_id'))) { + if ($display_variant = $entity->getExecutable()->getRuntimeVariant($this->routeMatch->getParameter('variant_id'))) { if ($display_variant instanceof RefinableCacheableDependencyInterface) { $display_variant->addCacheableDependency($entity); } - // @todo This is duplicating the setting of contexts in - // \Drupal\page_manager\Routing\VariantRouteFilter, which is bad. - if ($display_variant instanceof ContextAwareVariantInterface) { - $contexts = $entity->getExecutable()->getContexts(); - $display_variant->setContexts($contexts); - } $build = $display_variant->build(); } return $build; diff --git a/src/PageExecutable.php b/src/PageExecutable.php index 190684f..63ec5b8 100644 --- a/src/PageExecutable.php +++ b/src/PageExecutable.php @@ -8,6 +8,7 @@ namespace Drupal\page_manager; use Drupal\Component\Plugin\Context\ContextInterface; +use Drupal\Core\Display\ContextAwareVariantInterface; use Drupal\page_manager\Event\PageManagerContextEvent; use Drupal\page_manager\Event\PageManagerEvents; @@ -65,6 +66,17 @@ public function addContext($name, ContextInterface $value) { } /** + * {@inheritdoc} + */ + public function getRuntimeVariant($variant_id) { + $variant = $this->getPage()->getVariant($variant_id); + if ($variant instanceof ContextAwareVariantInterface) { + $variant->setContexts($this->getContexts()); + } + return $variant; + } + + /** * Wraps the event dispatcher. * * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface diff --git a/src/PageExecutableInterface.php b/src/PageExecutableInterface.php index e1bd96c..4d64f17 100644 --- a/src/PageExecutableInterface.php +++ b/src/PageExecutableInterface.php @@ -46,4 +46,15 @@ public function getContexts(); */ public function addContext($name, ContextInterface $value); + /** + * Gets a runtime representation of a variant. + * + * @param string $variant_id + * The variant ID. + * + * @return \Drupal\Core\Display\VariantInterface + * The variant object. + */ + public function getRuntimeVariant($variant_id); + } diff --git a/src/Routing/VariantRouteFilter.php b/src/Routing/VariantRouteFilter.php index 0745f29..c0858e4 100644 --- a/src/Routing/VariantRouteFilter.php +++ b/src/Routing/VariantRouteFilter.php @@ -75,7 +75,6 @@ public function applies(Route $route) { */ public function filter(RouteCollection $collection, Request $request) { $new_collection = NULL; - $page = NULL; // Only prepare the request if the collection is non-empty. if ($collection->count()) { @@ -87,14 +86,9 @@ public function filter(RouteCollection $collection, Request $request) { $defaults = $route->getDefaults(); if (isset($defaults['page_manager_page']) && isset($defaults['variant_id'])) { /** @var \Drupal\page_manager\PageInterface $page */ - $page = $page ?: $this->pageStorage->load($defaults['page_manager_page']); - $contexts = $page->getExecutable()->getContexts(); - - $variant = $page->getVariant($defaults['variant_id']); - if ($variant instanceof ContextAwareVariantInterface) { - $variant->setContexts($contexts); - } + $page = $this->pageStorage->load($defaults['page_manager_page']); + $variant = $page->getExecutable()->getRuntimeVariant($defaults['variant_id']); if ($variant->access()) { $new_collection = new RouteCollection(); $new_collection->add($name, $route); diff --git a/tests/src/Unit/VariantRouteFilterTest.php b/tests/src/Unit/VariantRouteFilterTest.php index 1cd649a..fc30ea2 100644 --- a/tests/src/Unit/VariantRouteFilterTest.php +++ b/tests/src/Unit/VariantRouteFilterTest.php @@ -138,14 +138,14 @@ public function testFilterDeniedAccess() { $route = new Route('/path/with/{slug}', ['page_manager_page' => 'a_page', 'variant_id' => 'a_variant']); $route_collection->add('a_route', $route); - $executable = $this->prophesize(PageExecutableInterface::class); - $variant = $this->prophesize(VariantInterface::class); $variant->access()->willReturn(FALSE); + $executable = $this->prophesize(PageExecutableInterface::class); + $executable->getRuntimeVariant('a_variant')->willReturn($variant); + $page = $this->prophesize(PageInterface::class); $page->getExecutable()->willReturn($executable->reveal()); - $page->getVariant('a_variant')->willReturn($variant); $this->finalMatcher->finalMatch($route_collection, $request)->willReturn([]); $this->paramConverterManager->convert([])->willReturn([]); @@ -166,16 +166,14 @@ public function testFilterAllowedAccess() { $route = new Route('/path/with/{slug}', ['page_manager_page' => 'a_page', 'variant_id' => 'a_variant']); $route_collection->add('a_route', $route); - $executable = $this->prophesize(PageExecutableInterface::class); - $executable->getContexts()->willReturn([]); - $variant = $this->prophesize(ContextAwareVariantInterface::class); $variant->access()->willReturn(TRUE); - $variant->setContexts([])->shouldBeCalled(); + + $executable = $this->prophesize(PageExecutableInterface::class); + $executable->getRuntimeVariant('a_variant')->willReturn($variant); $page = $this->prophesize(PageInterface::class); $page->getExecutable()->willReturn($executable->reveal()); - $page->getVariant('a_variant')->willReturn($variant); $this->finalMatcher->finalMatch($route_collection, $request)->willReturn([]); $this->paramConverterManager->convert([])->willReturn([]); @@ -198,17 +196,15 @@ public function testFilterAllowedAccessTwoRoutes() { $route_collection->add('route_1', $route1); $route_collection->add('route_2', $route2); - $executable = $this->prophesize(PageExecutableInterface::class); - $executable->getContexts()->willReturn([]); - $variant = $this->prophesize(ContextAwareVariantInterface::class); $variant->access()->willReturn(TRUE); - $variant->setContexts([])->shouldBeCalled(); + + $executable = $this->prophesize(PageExecutableInterface::class); + $executable->getRuntimeVariant('variant_1')->willReturn($variant); + $executable->getRuntimeVariant('variant_2')->shouldNotBeCalled(); $page = $this->prophesize(PageInterface::class); $page->getExecutable()->willReturn($executable->reveal()); - $page->getVariant('variant_1')->willReturn($variant); - $page->getVariant('variant_2')->shouldNotBeCalled(); $this->finalMatcher->finalMatch($route_collection, $request)->willReturn([]); $this->paramConverterManager->convert([])->willReturn([]); @@ -232,23 +228,25 @@ public function testFilterAllowedAccessSecondRoute() { $route_collection->add('route_1', $route1); $route_collection->add('route_2', $route2); - $executable = $this->prophesize(PageExecutableInterface::class); - $executable->getContexts()->willReturn([]); - $variant1 = $this->prophesize(VariantInterface::class); $variant1->access()->willReturn(FALSE); $variant2 = $this->prophesize(VariantInterface::class); $variant2->access()->willReturn(TRUE); - $page = $this->prophesize(PageInterface::class); - $page->getExecutable()->willReturn($executable->reveal()); - $page->getVariant('variant_1')->willReturn($variant1); - $page->getVariant('variant_2')->willReturn($variant2); + $executable = $this->prophesize(PageExecutableInterface::class); + $executable->getRuntimeVariant('variant_1')->willReturn($variant1); + $executable->getRuntimeVariant('variant_2')->willReturn($variant2); + + $page1 = $this->prophesize(PageInterface::class); + $page1->getExecutable()->willReturn($executable->reveal()); + + $page2 = $this->prophesize(PageInterface::class); + $page2->getExecutable()->willReturn($executable->reveal()); $this->finalMatcher->finalMatch($route_collection, $request)->willReturn([]); $this->paramConverterManager->convert([])->willReturn([]); - $this->pageStorage->load('page_1')->willReturn($page->reveal()); - $this->pageStorage->load('page_2')->shouldNotBeCalled(); + $this->pageStorage->load('page_1')->willReturn($page1->reveal())->shouldBeCalled(); + $this->pageStorage->load('page_2')->willReturn($page2->reveal())->shouldBeCalled(); $result = $this->routeFilter->filter($route_collection, $request); $expected = ['route_2' => $route2];