Commit 08ce5a70 authored by alexpott's avatar alexpott

Issue #2448847 by dawehner, arlinsandbulte: [regression] Themes unable to...

Issue #2448847 by dawehner, arlinsandbulte: [regression] Themes unable to implement hook_theme_registry_alter()
parent 4b812ec9
...@@ -1092,7 +1092,9 @@ services: ...@@ -1092,7 +1092,9 @@ services:
class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry
theme.manager: theme.manager:
class: Drupal\Core\Theme\ThemeManager class: Drupal\Core\Theme\ThemeManager
arguments: ['@app.root', '@theme.registry', '@theme.negotiator', '@theme.initialization', '@request_stack', '@module_handler'] arguments: ['@app.root', '@theme.negotiator', '@theme.initialization', '@request_stack', '@module_handler']
calls:
- [setThemeRegistry, ['@theme.registry']]
theme.initialization: theme.initialization:
class: Drupal\Core\Theme\ThemeInitialization class: Drupal\Core\Theme\ThemeInitialization
arguments: ['@app.root', '@theme_handler', '@state'] arguments: ['@app.root', '@theme_handler', '@state']
...@@ -1101,6 +1103,8 @@ services: ...@@ -1101,6 +1103,8 @@ services:
arguments: ['@app.root', '@cache.default', '@lock', '@module_handler', '@theme_handler', '@theme.initialization'] arguments: ['@app.root', '@cache.default', '@lock', '@module_handler', '@theme_handler', '@theme.initialization']
tags: tags:
- { name: needs_destruction } - { name: needs_destruction }
calls:
- [setThemeManager, ['@theme.manager']]
authentication: authentication:
class: Drupal\Core\Authentication\AuthenticationManager class: Drupal\Core\Authentication\AuthenticationManager
tags: tags:
......
...@@ -130,6 +130,13 @@ class Registry implements DestructableInterface { ...@@ -130,6 +130,13 @@ class Registry implements DestructableInterface {
*/ */
protected $themeHandler; protected $themeHandler;
/**
* The theme manager.
*
* @var \Drupal\Core\Theme\ThemeManagerInterface
*/
protected $themeManager;
/** /**
* Constructs a \Drupal\Core\Theme\Registry object. * Constructs a \Drupal\Core\Theme\Registry object.
* *
...@@ -158,6 +165,16 @@ public function __construct($root, CacheBackendInterface $cache, LockBackendInte ...@@ -158,6 +165,16 @@ public function __construct($root, CacheBackendInterface $cache, LockBackendInte
$this->themeInitialization = $theme_initialization; $this->themeInitialization = $theme_initialization;
} }
/**
* Sets the theme manager.
*
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
* The theme manager.
*/
public function setThemeManager(ThemeManagerInterface $theme_manager) {
$this->themeManager = $theme_manager;
}
/** /**
* Initializes a theme with a certain name. * Initializes a theme with a certain name.
* *
...@@ -173,7 +190,7 @@ protected function init($theme_name = NULL) { ...@@ -173,7 +190,7 @@ protected function init($theme_name = NULL) {
} }
// Unless instantiated for a specific theme, use globals. // Unless instantiated for a specific theme, use globals.
if (!isset($theme_name)) { if (!isset($theme_name)) {
$this->theme = \Drupal::theme()->getActiveTheme(); $this->theme = $this->themeManager->getActiveTheme();
} }
// Instead of the active theme, a specific theme was requested. // Instead of the active theme, a specific theme was requested.
else { else {
...@@ -326,9 +343,9 @@ protected function build() { ...@@ -326,9 +343,9 @@ protected function build() {
// Finally, hooks provided by the theme itself. // Finally, hooks provided by the theme itself.
$this->processExtension($cache, $this->theme->getName(), 'theme', $this->theme->getName(), $this->theme->getPath()); $this->processExtension($cache, $this->theme->getName(), 'theme', $this->theme->getName(), $this->theme->getPath());
// Let modules alter the registry. // Let modules and themes alter the registry.
$this->moduleHandler->alter('theme_registry', $cache); $this->moduleHandler->alter('theme_registry', $cache);
// @todo Do we want to allow themes to take part? $this->themeManager->alterForTheme($this->theme, 'theme_registry', $cache);
// @todo Implement more reduction of the theme registry entry. // @todo Implement more reduction of the theme registry entry.
// Optimize the registry to not have empty arrays for functions. // Optimize the registry to not have empty arrays for functions.
......
...@@ -62,8 +62,6 @@ class ThemeManager implements ThemeManagerInterface { ...@@ -62,8 +62,6 @@ class ThemeManager implements ThemeManagerInterface {
* *
* @param string $root * @param string $root
* The app root. * The app root.
* @param \Drupal\Core\Theme\Registry $theme_registry
* The theme registry.
* @param \Drupal\Core\Theme\ThemeNegotiatorInterface $theme_negotiator * @param \Drupal\Core\Theme\ThemeNegotiatorInterface $theme_negotiator
* The theme negotiator. * The theme negotiator.
* @param \Drupal\Core\Theme\ThemeInitialization $theme_initialization * @param \Drupal\Core\Theme\ThemeInitialization $theme_initialization
...@@ -72,15 +70,27 @@ class ThemeManager implements ThemeManagerInterface { ...@@ -72,15 +70,27 @@ class ThemeManager implements ThemeManagerInterface {
* The request stack. * The request stack.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
*/ */
public function __construct($root, Registry $theme_registry, ThemeNegotiatorInterface $theme_negotiator, ThemeInitialization $theme_initialization, RequestStack $request_stack, ModuleHandlerInterface $module_handler) { public function __construct($root, ThemeNegotiatorInterface $theme_negotiator, ThemeInitialization $theme_initialization, RequestStack $request_stack, ModuleHandlerInterface $module_handler) {
$this->root = $root; $this->root = $root;
$this->themeNegotiator = $theme_negotiator; $this->themeNegotiator = $theme_negotiator;
$this->themeRegistry = $theme_registry;
$this->themeInitialization = $theme_initialization; $this->themeInitialization = $theme_initialization;
$this->requestStack = $request_stack; $this->requestStack = $request_stack;
$this->moduleHandler = $module_handler; $this->moduleHandler = $module_handler;
} }
/**
* Sets the theme registry.
*
* @param \Drupal\Core\Theme\Registry $theme_registry
* The theme registry.
*
* @return $this
*/
public function setThemeRegistry(Registry $theme_registry) {
$this->themeRegistry = $theme_registry;
return $this;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -402,7 +412,7 @@ protected function initTheme(RouteMatchInterface $route_match = NULL) { ...@@ -402,7 +412,7 @@ protected function initTheme(RouteMatchInterface $route_match = NULL) {
* *
* @todo Should we cache some of these information? * @todo Should we cache some of these information?
*/ */
public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) { public function alterForTheme(ActiveTheme $theme, $type, &$data, &$context1 = NULL, &$context2 = NULL) {
// Most of the time, $type is passed as a string, so for performance, // Most of the time, $type is passed as a string, so for performance,
// normalize it to that. When passed as an array, usually the first item in // normalize it to that. When passed as an array, usually the first item in
// the array is a generic type, and additional items in the array are more // the array is a generic type, and additional items in the array are more
...@@ -419,7 +429,6 @@ public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) { ...@@ -419,7 +429,6 @@ public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
} }
$theme_keys = array(); $theme_keys = array();
$theme = $this->getActiveTheme();
foreach ($theme->getBaseThemes() as $base) { foreach ($theme->getBaseThemes() as $base) {
$theme_keys[] = $base->getName(); $theme_keys[] = $base->getName();
} }
...@@ -446,4 +455,12 @@ public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) { ...@@ -446,4 +455,12 @@ public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
} }
} }
/**
* {@inheritdoc}
*/
public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
$theme = $this->getActiveTheme();
$this->alterForTheme($theme, $type, $data, $context1, $context2);
}
} }
...@@ -69,6 +69,8 @@ public function setActiveTheme(ActiveTheme $active_theme); ...@@ -69,6 +69,8 @@ public function setActiveTheme(ActiveTheme $active_theme);
/** /**
* Passes alterable variables to specific $theme_TYPE_alter() implementations. * Passes alterable variables to specific $theme_TYPE_alter() implementations.
* *
* It also invokes alter hooks for all base themes.
*
* $theme specifies the theme name of the active theme and all its base * $theme specifies the theme name of the active theme and all its base
* themes. * themes.
* *
...@@ -122,4 +124,24 @@ public function setActiveTheme(ActiveTheme $active_theme); ...@@ -122,4 +124,24 @@ public function setActiveTheme(ActiveTheme $active_theme);
*/ */
public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL); public function alter($type, &$data, &$context1 = NULL, &$context2 = NULL);
/**
* Provides an alter hook for a specific theme.
*
* Similar to ::alter, it also invokes the alter hooks for the base themes.
*
* @param \Drupal\Core\Theme\ActiveTheme $theme
* A manually specified theme.
* @param string|array $type
* A string describing the type of the alterable $data.
* @param mixed $data
* The variable that will be passed to $theme_TYPE_alter() implementations
* @param mixed $context1
* (optional) An additional variable that is passed by reference.
* @param mixed $context2
* (optional) An additional variable that is passed by reference.
*
* @see ::alter
*/
public function alterForTheme(ActiveTheme $theme, $type, &$data, &$context1 = NULL, &$context2 = NULL);
} }
...@@ -23,7 +23,7 @@ class RegistryTest extends KernelTestBase { ...@@ -23,7 +23,7 @@ class RegistryTest extends KernelTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('theme_test'); public static $modules = array('theme_test', 'system');
protected $profile = 'testing'; protected $profile = 'testing';
/** /**
...@@ -72,8 +72,11 @@ public function testMultipleSubThemes() { ...@@ -72,8 +72,11 @@ public function testMultipleSubThemes() {
$theme_handler->install(['test_basetheme', 'test_subtheme', 'test_subsubtheme']); $theme_handler->install(['test_basetheme', 'test_subtheme', 'test_subsubtheme']);
$registry_subsub_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_subsubtheme'); $registry_subsub_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_subsubtheme');
$registry_subsub_theme->setThemeManager(\Drupal::theme());
$registry_sub_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_subtheme'); $registry_sub_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_subtheme');
$registry_sub_theme->setThemeManager(\Drupal::theme());
$registry_base_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_basetheme'); $registry_base_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_basetheme');
$registry_base_theme->setThemeManager(\Drupal::theme());
$preprocess_functions = $registry_subsub_theme->get()['theme_test_template_test']['preprocess functions']; $preprocess_functions = $registry_subsub_theme->get()['theme_test_template_test']['preprocess functions'];
$this->assertIdentical([ $this->assertIdentical([
...@@ -96,4 +99,20 @@ public function testMultipleSubThemes() { ...@@ -96,4 +99,20 @@ public function testMultipleSubThemes() {
'test_basetheme_preprocess_theme_test_template_test', 'test_basetheme_preprocess_theme_test_template_test',
], $preprocess_functions); ], $preprocess_functions);
} }
/**
* Tests that the theme registry can be altered by themes.
*/
public function testThemeRegistryAlterByTheme() {
/** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
$theme_handler = \Drupal::service('theme_handler');
$theme_handler->install(['test_theme']);
$theme_handler->setDefault('test_theme');
$registry = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_theme');
$registry->setThemeManager(\Drupal::theme());
$this->assertEqual('value', $registry->get()['theme_test_template_test']['variables']['additional']);
}
} }
...@@ -94,3 +94,10 @@ function test_theme_theme_test_function_suggestions__theme_override($variables) ...@@ -94,3 +94,10 @@ function test_theme_theme_test_function_suggestions__theme_override($variables)
function test_theme_theme_test_function_suggestions__module_override($variables) { function test_theme_theme_test_function_suggestions__module_override($variables) {
return 'Theme function overridden based on new theme suggestion provided by a module.'; return 'Theme function overridden based on new theme suggestion provided by a module.';
} }
/**
* Implements hook_theme_registry_alter().
*/
function test_theme_theme_registry_alter(&$registry) {
$registry['theme_test_template_test']['variables']['additional'] = 'value';
}
...@@ -59,6 +59,13 @@ class RegistryTest extends UnitTestCase { ...@@ -59,6 +59,13 @@ class RegistryTest extends UnitTestCase {
*/ */
protected $themeInitialization; protected $themeInitialization;
/**
* The theme manager.
*
* @var \Drupal\Core\Theme\ThemeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $themeManager;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -70,6 +77,7 @@ protected function setUp() { ...@@ -70,6 +77,7 @@ protected function setUp() {
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface'); $this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
$this->themeInitialization = $this->getMock('Drupal\Core\Theme\ThemeInitializationInterface'); $this->themeInitialization = $this->getMock('Drupal\Core\Theme\ThemeInitializationInterface');
$this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
$this->setupTheme(); $this->setupTheme();
} }
...@@ -124,6 +132,7 @@ public function testGetRegistryForModule() { ...@@ -124,6 +132,7 @@ public function testGetRegistryForModule() {
protected function setupTheme($theme_name = NULL) { protected function setupTheme($theme_name = NULL) {
$this->registry = new TestRegistry($this->root, $this->cache, $this->lock, $this->moduleHandler, $this->themeHandler, $this->themeInitialization, $theme_name); $this->registry = new TestRegistry($this->root, $this->cache, $this->lock, $this->moduleHandler, $this->themeHandler, $this->themeInitialization, $theme_name);
$this->registry->setThemeManager($this->themeManager);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment