3 namespace Drupal\Core\Theme;
5 use Drupal\Core\Routing\RouteMatchInterface;
8 * Provides a class which determines the active theme of the page.
10 * It therefore uses ThemeNegotiatorInterface objects which are passed in
11 * using the 'theme_negotiator' tag.
13 class ThemeNegotiator implements ThemeNegotiatorInterface {
16 * Holds arrays of theme negotiators, keyed by priority.
20 protected $negotiators = [];
23 * Holds the array of theme negotiators sorted by priority.
25 * Set to NULL if the array needs to be re-calculated.
29 protected $sortedNegotiators;
32 * The access checker for themes.
34 * @var \Drupal\Core\Theme\ThemeAccessCheck
36 protected $themeAccess;
39 * Constructs a new ThemeNegotiator.
41 * @param \Drupal\Core\Theme\ThemeAccessCheck $theme_access
42 * The access checker for themes.
44 public function __construct(ThemeAccessCheck $theme_access) {
45 $this->themeAccess = $theme_access;
49 * Adds a active theme negotiation service.
51 * @param \Drupal\Core\Theme\ThemeNegotiatorInterface $negotiator
52 * The theme negotiator to add.
53 * @param int $priority
54 * Priority of the theme negotiator.
56 public function addNegotiator(ThemeNegotiatorInterface $negotiator, $priority) {
57 $this->negotiators[$priority][] = $negotiator;
58 // Force the negotiators to be re-sorted.
59 $this->sortedNegotiators = NULL;
63 * Returns the sorted array of theme negotiators.
65 * @return array|\Drupal\Core\Theme\ThemeNegotiatorInterface[]
66 * An array of theme negotiator objects.
68 protected function getSortedNegotiators() {
69 if (!isset($this->sortedNegotiators)) {
70 // Sort the negotiators according to priority.
71 krsort($this->negotiators);
72 // Merge nested negotiators from $this->negotiators into
73 // $this->sortedNegotiators.
74 $this->sortedNegotiators = [];
75 foreach ($this->negotiators as $builders) {
76 $this->sortedNegotiators = array_merge($this->sortedNegotiators, $builders);
79 return $this->sortedNegotiators;
85 public function applies(RouteMatchInterface $route_match) {
92 public function determineActiveTheme(RouteMatchInterface $route_match) {
93 foreach ($this->getSortedNegotiators() as $negotiator) {
94 if ($negotiator->applies($route_match)) {
95 $theme = $negotiator->determineActiveTheme($route_match);
96 if ($theme !== NULL && $this->themeAccess->checkAccess($theme)) {