Commit b0894cea authored by Dries's avatar Dries

- Patch #812016 by effulgentsia, chx, redndahead, Damien Tournoud: themes...

- Patch #812016 by effulgentsia, chx, redndahead, Damien Tournoud: themes cannot always participate in drupal_alter().
parent ee691c59
......@@ -4592,13 +4592,19 @@ function _drupal_bootstrap_full() {
// Initialize $_GET['q'] prior to invoking hook_init().
drupal_path_initialize();
// Set a custom theme for the current page, if there is one. We need to run
// this before invoking hook_init(), since any modules which initialize the
// theme system will prevent a custom theme from being correctly set later.
menu_set_custom_theme();
// Let all modules take action before menu system handles the request
// Let all modules take action before the menu system handles the request.
// We do not want this while running update.php.
if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
// Prior to invoking hook_init(), initialize the theme (potentially a custom
// one for this page), so that:
// - Modules with hook_init() implementations that call theme() or
// theme_get_registry() don't initialize the incorrect theme.
// - The theme can have hook_*_alter() implementations affect page building
// (e.g., hook_form_alter(), hook_node_view_alter(), hook_page_alter()),
// ahead of when rendering starts.
menu_set_custom_theme();
drupal_theme_initialize();
module_invoke_all('init');
}
}
......
......@@ -221,8 +221,8 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
}
}
if (function_exists($registry_callback)) {
$registry_callback($theme, $base_theme, $theme_engine);
if (isset($registry_callback)) {
_theme_registry_callback($registry_callback, array($theme, $base_theme, $theme_engine));
}
}
......@@ -233,26 +233,30 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
* The theme registry array if it has been stored in memory, NULL otherwise.
*/
function theme_get_registry() {
return _theme_set_registry();
static $theme_registry = NULL;
if (!isset($theme_registry)) {
list($callback, $arguments) = _theme_registry_callback();
$theme_registry = call_user_func_array($callback, $arguments);
}
return $theme_registry;
}
/**
* Store the theme registry in memory.
*
* @param $registry
* A registry array as returned by _theme_build_registry()
* Set the callback that will be used by theme_get_registry() to fetch the registry.
*
* @return
* The theme registry array stored in memory
* @param $callback
* The name of the callback function.
* @param $arguments
* The arguments to pass to the function.
*/
function _theme_set_registry($registry = NULL) {
static $theme_registry = NULL;
if (isset($registry)) {
$theme_registry = $registry;
function _theme_registry_callback($callback = NULL, array $arguments = array()) {
static $stored;
if (isset($callback)) {
$stored = array($callback, $arguments);
}
return $theme_registry;
return $stored;
}
/**
......@@ -271,7 +275,6 @@ function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL)
$cache = cache_get("theme_registry:$theme->name", 'cache');
if (isset($cache->data)) {
$registry = $cache->data;
_theme_set_registry($registry);
}
else {
// If not, build one and cache it.
......@@ -280,9 +283,9 @@ function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL)
// complete set of theme hooks.
if (module_load_all(NULL)) {
_theme_save_registry($theme, $registry);
_theme_set_registry($registry);
}
}
return $registry;
}
/**
......
......@@ -88,8 +88,7 @@ function _drupal_maintenance_theme() {
* This builds the registry when the site needs to bypass any database calls.
*/
function _theme_load_offline_registry($theme, $base_theme = NULL, $theme_engine = NULL) {
$registry = _theme_build_registry($theme, $base_theme, $theme_engine);
_theme_set_registry($registry);
return _theme_build_registry($theme, $base_theme, $theme_engine);
}
/**
......
......@@ -66,6 +66,14 @@ class ThemeUnitTest extends DrupalWebTestCase {
$_GET['q'] = $q;
$this->assertTrue(in_array('page__front', $suggestions), t('Front page template was suggested.'));
}
/**
* Ensures theme hook_*_alter() implementations can run before anything is rendered.
*/
function testAlter() {
$this->drupalGet('theme-test/alter');
$this->assertText('The altered data is test_theme_theme_test_alter_alter was invoked.', t('The theme was able to implement an alter hook during page building before anything was rendered.'));
}
}
/**
......@@ -181,3 +189,30 @@ class ThemeHookInitUnitTest extends DrupalWebTestCase {
$this->assertRaw('bartik/css/style.css', t("The default theme's CSS appears on the page when the theme system is initialized in hook_init()."));
}
}
/**
* Tests autocompletion not loading registry.
*/
class ThemeFastTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Theme fast initialization',
'description' => 'Test that autocompletion does not load the registry.',
'group' => 'Theme'
);
}
function setUp() {
parent::setUp('theme_test');
$this->account = $this->drupalCreateUser(array('access user profiles'));
}
/**
* Tests access to user autocompletion and verify the correct results.
*/
function testUserAutocomplete() {
$this->drupalLogin($this->account);
$this->drupalGet('user/autocomplete/' . $this->account->name);
$this->assertText('registry not initialized', t('The registry was not initialized'));
}
}
......@@ -12,6 +12,13 @@ function theme_test_menu() {
'theme callback' => '_theme_custom_theme',
'type' => MENU_CALLBACK,
);
$items['theme-test/alter'] = array(
'title' => 'Suggestion',
'page callback' => '_theme_test_alter',
'access arguments' => array('access content'),
'theme callback' => '_theme_custom_theme',
'type' => MENU_CALLBACK,
);
$items['theme-test/hook-init'] = array(
'page callback' => 'theme_test_hook_init_page_callback',
'access callback' => TRUE,
......@@ -24,6 +31,7 @@ function theme_test_menu() {
* Implements hook_init().
*/
function theme_test_init() {
if (arg(0) == 'theme-test' && arg(1) == 'hook-init') {
// First, force the theme registry to be rebuilt on this page request. This
// allows us to test a full initialization of the theme system in the code
// below.
......@@ -33,6 +41,26 @@ function theme_test_init() {
// to test that even when the theme system is initialized this early, it is
// still capable of returning output and theming the page as a whole.
$GLOBALS['theme_test_output'] = theme('more_link', array('url' => 'user', 'title' => 'Themed output generated in hook_init()'));
}
}
/**
* Implements hook_exit().
*/
function theme_test_exit() {
if (arg(0) == 'user') {
// Register a fake registry loading callback. If it gets called by
// theme_get_registry(), the registry has not been initialized yet.
_theme_registry_callback('_theme_test_load_registry', array());
print theme_get_registry() ? 'registry initialized' : 'registry not initialized';
}
}
/**
* Fake registry loading callback.
*/
function _theme_test_load_registry() {
return array();
}
/**
......@@ -49,6 +77,19 @@ function _theme_custom_theme() {
return 'test_theme';
}
/**
* Page callback, calls drupal_alter().
*
* This is for testing that the theme can have hook_*_alter() implementations
* that run during page callback execution, even before theme() is called for
* the first time.
*/
function _theme_test_alter() {
$data = 'foo';
drupal_alter('theme_test_alter', $data);
return "The altered data is $data.";
}
/**
* Page callback, calls a theme hook suggestion.
*/
......
......@@ -9,3 +9,14 @@ function test_theme_breadcrumb__suggestion($variables) {
// when the suggestion has an implementation.
return 'test_theme_breadcrumb__suggestion: ' . $variables['theme_test_preprocess_breadcrumb'];
}
/**
* Tests a theme implementing an alter hook.
*
* The confusing function name here is due to this being an implementation of
* the alter hook invoked when the 'theme_test' module calls
* drupal_alter('theme_test_alter').
*/
function test_theme_theme_test_alter_alter(&$data) {
$data = 'test_theme_theme_test_alter_alter was invoked';
}
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