diff --git a/core/core.services.yml b/core/core.services.yml index 66a46c6603..181ab27423 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -479,7 +479,7 @@ services: arguments: ['@app.root', '@module_handler', '@cache.discovery'] theme.negotiator: class: Drupal\Core\Theme\ThemeNegotiator - arguments: ['@access_check.theme', '@class_resolver'] + arguments: ['@access_check.theme', '@current_route_match'] tags: - { name: service_id_collector, tag: theme_negotiator } theme.negotiator.default: diff --git a/core/lib/Drupal/Core/Theme/ChainThemeNegotiatorInterface.php b/core/lib/Drupal/Core/Theme/ChainThemeNegotiatorInterface.php new file mode 100644 index 0000000000..d5e87343e4 --- /dev/null +++ b/core/lib/Drupal/Core/Theme/ChainThemeNegotiatorInterface.php @@ -0,0 +1,35 @@ +themeAccess = $theme_access; - $this->negotiators = $negotiators; - $this->classResolver = $class_resolver; + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public function addNegotiator(ThemeNegotiatorInterface $negotiator, $priority) { + $this->negotiators[$priority][] = $negotiator; + // Force the negotiators to be re-sorted. + $this->sortedNegotiators = NULL; + } + + /** + * Returns the sorted array of theme negotiators. + * + * @return array|\Drupal\Core\Theme\ThemeNegotiatorInterface[] + * An array of theme negotiator objects. + */ + protected function getSortedNegotiators() { + if (!isset($this->sortedNegotiators)) { + // Sort the negotiators according to priority. + krsort($this->negotiators); + // Merge nested negotiators from $this->negotiators into + // $this->sortedNegotiators. + $this->sortedNegotiators = array(); + foreach ($this->negotiators as $builders) { + $this->sortedNegotiators = array_merge($this->sortedNegotiators, $builders); + } + } + return $this->sortedNegotiators; } /** @@ -73,4 +106,11 @@ public function determineActiveTheme(RouteMatchInterface $route_match) { } } + /** + * {@inheritdoc} + */ + public function getActiveTheme() { + return $this->determineActiveTheme($this->routeMatch); + } + } diff --git a/core/tests/Drupal/Tests/Core/Theme/ThemeNegotiatorTest.php b/core/tests/Drupal/Tests/Core/Theme/ThemeNegotiatorTest.php index 1e2303d7c4..0a8d2fb50e 100644 --- a/core/tests/Drupal/Tests/Core/Theme/ThemeNegotiatorTest.php +++ b/core/tests/Drupal/Tests/Core/Theme/ThemeNegotiatorTest.php @@ -44,13 +44,18 @@ class ThemeNegotiatorTest extends UnitTestCase { protected $themeNegotiator; /** - * {@inheritdoc} + * The current route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface */ + protected $routeMatch; + protected function setUp() { $this->themeAccessCheck = $this->getMockBuilder('\Drupal\Core\Theme\ThemeAccessCheck') ->disableOriginalConstructor() ->getMock(); - $this->container = new ContainerBuilder(); + $this->routeMatch = new RouteMatch('test_route', new Route('/test-route'), array(), array()); + $this->themeNegotiator = new ThemeNegotiator($this->themeAccessCheck, $this->routeMatch); } /** @@ -75,8 +80,7 @@ public function testDetermineActiveTheme() { ->method('checkAccess') ->will($this->returnValue(TRUE)); - $route_match = new RouteMatch('test_route', new Route('/test-route'), [], []); - $theme = $this->createThemeNegotiator($negotiators)->determineActiveTheme($route_match); + $theme = $this->themeNegotiator->determineActiveTheme($this->routeMatch); $this->assertEquals('example_test', $theme); } @@ -115,8 +119,7 @@ public function testDetermineActiveThemeWithPriority() { ->method('checkAccess') ->will($this->returnValue(TRUE)); - $route_match = new RouteMatch('test_route', new Route('/test-route'), [], []); - $theme = $this->createThemeNegotiator(array_keys($negotiators))->determineActiveTheme($route_match); + $theme = $this->themeNegotiator->determineActiveTheme($this->routeMatch); $this->assertEquals('example_test', $theme); } @@ -163,8 +166,7 @@ public function testDetermineActiveThemeWithAccessCheck() { ->with('example_test2') ->will($this->returnValue(TRUE)); - $route_match = new RouteMatch('test_route', new Route('/test-route'), [], []); - $theme = $this->createThemeNegotiator(array_keys($negotiators))->determineActiveTheme($route_match); + $theme = $this->themeNegotiator->determineActiveTheme($this->routeMatch); $this->assertEquals('example_test2', $theme); } @@ -204,8 +206,7 @@ public function testDetermineActiveThemeWithNotApplyingNegotiator() { ->method('checkAccess') ->will($this->returnValue(TRUE)); - $route_match = new RouteMatch('test_route', new Route('/test-route'), [], []); - $theme = $this->createThemeNegotiator(array_keys($negotiators))->determineActiveTheme($route_match); + $theme = $this->themeNegotiator->determineActiveTheme($this->routeMatch); $this->assertEquals('example_test2', $theme); }