diff --git a/core/includes/theme.inc b/core/includes/theme.inc index d54746e..4f1fb61 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -836,11 +836,11 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) { * phase, and are executed (if they exist), in the following * order (HOOK indicates the profile, module, theme engine or theme name, * THEME_HOOK indicates the name of the specific theme hook called): - * - HOOK_theme_prepare(&$variables, $context): Prepare a set of variables + * - HOOK_theme_prepare(&$variables, $hook): Prepare a set of variables * for all theme hook implementations. - * - HOOK_theme_prepare_THEME_HOOK(&$variables, $context): Prepare a set of + * - HOOK_theme_prepare_THEME_HOOK(&$variables): Prepare a set of * variables for a specific theme hook implementation. - * - HOOK_theme_prepare_alter(&$variables, $context): Alter a set of prepared + * - HOOK_theme_prepare_alter(&$variables, $hook): Alter a set of prepared * variables for all theme hook implementations. * - HOOK_theme_prepare_THEME_HOOK_alter(&$variables, $context): Alter a set of * prepared variables for a specific theme hook implementation. @@ -881,10 +881,6 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) { * to the function or template implementing the theme hook. Alternatively, * this can be a renderable array, in which case, its properties are mapped to * variables expected by the theme hook implementations. - * @param array $context - * An associative array of data used as context in hook_theme_prepare(). This - * array is used internally and is not available as a "variable" in theme - * functions or templates. * * @return string|false * An HTML string representing the themed output or FALSE if the passed $hook @@ -897,7 +893,7 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) { * * @throws Exception */ -function theme($hook, $variables = array(), $context = array()) { +function theme($hook, $variables = array()) { static $default_attributes; // If called before all modules are loaded, we do not necessarily have a full // theme registry to work with, and therefore cannot process the theme @@ -986,10 +982,6 @@ function theme($hook, $variables = array(), $context = array()) { elseif (!empty($info['render element'])) { $variables += array($info['render element'] => array()); } - // Supply original caller info. - $variables += array( - 'theme_hook_original' => $original_hook, - ); // Set base hook for later use. For example if '#theme' => 'node__article' // is called, we run hook_theme_suggestions_node_alter() rather than @@ -1002,6 +994,12 @@ function theme($hook, $variables = array(), $context = array()) { $base_theme_hook = $hook; } + // Supply original caller info. + $variables += array( + 'theme_hook' => $base_theme_hook, + 'theme_hook_original' => $original_hook, + ); + // Invoke hook_theme_suggestions_HOOK(). $suggestions = Drupal::moduleHandler()->invokeAll('theme_suggestions_' . $base_theme_hook, array($variables)); // If theme() was invoked with a direct theme suggestion like @@ -1045,17 +1043,10 @@ function theme($hook, $variables = array(), $context = array()) { } } - // Provide default context. - $context += array( - 'theme_hook' => $hook, - 'original_theme_hook' => $original_hook, - 'suggestions' => $suggestions, - ); - - // A list of hooks that we'll fire for the given theme hook. + // A list of hooks that will be invoked for the given theme hook. $prepare_hooks = array( 'theme_prepare', - 'theme_prepare_' . $hook, + 'theme_prepare_' . $base_theme_hook, ); // If the original theme hook is not the same as the base theme hook, then // invoke the original theme hook suggestion after the base theme hook. @@ -1066,22 +1057,20 @@ function theme($hook, $variables = array(), $context = array()) { // Invokes hook_theme_prepare(), hook_theme_prepare_THEME_HOOK() for enabled // modules. foreach ($prepare_hooks as $prepare_hook) { - // Provide immutable context for each hook. - $context_clone = $context; - $variables = NestedArray::mergeDeep($variables, (array) Drupal::moduleHandler()->invokeAll($prepare_hook, array($context_clone))); + $variables = NestedArray::mergeDeep($variables, (array) Drupal::moduleHandler()->invokeAll($prepare_hook, array($variables, $base_theme_hook))); } - // Invokes hook_theme_prepare(), hook_theme_prepare_THEME_ID() for the active + // Invokes hook_theme_prepare(), hook_theme_prepare_THEME_HOOK() for the active // theme, which takes precedence over modules. // @todo Replace with Drupal::themeHandler()->invoke() once implemented. // @see https://drupal.org/node/2029819 foreach ($prepare_hooks as $prepare_hook) { - // Provide immutable context for each hook. - $context_clone = $context; - $variables = NestedArray::mergeDeep($variables, (array) Drupal::moduleHandler()->themeInvoke($prepare_hook, array($context_clone))); + $variables = NestedArray::mergeDeep($variables, (array) theme_invoke($prepare_hook, array($variables, $base_theme_hook))); } - // Invokes preprocess functions (deprecated). + // Invokes hook_preprocess() and hook_preprocess_HOOK() implementations. This + // phase is deprecated and is run in between hook_theme_prepare[_THEME_HOOK]() + // and hook_theme_prepare[_THEME_HOOK]_alter(). if (isset($info['preprocess functions'])) { foreach ($info['preprocess functions'] as $preprocessor_function) { if (function_exists($preprocessor_function)) { @@ -1095,9 +1084,7 @@ function theme($hook, $variables = array(), $context = array()) { // @todo Add Drupal::themeHandler()->alter() invocations once implemented. // @see https://drupal.org/node/2029819 foreach ($prepare_hooks as $prepare_hook) { - // Provide immutable context for each hook. - $context_clone = $context; - Drupal::moduleHandler()->alter($prepare_hook, $variables, $context_clone); + Drupal::moduleHandler()->alter($prepare_hook, $variables, $base_theme_hook); } // Generate the output using either a function or a template. @@ -1585,6 +1572,39 @@ function theme_disable($theme_list) { } /** + * Rudimentary and temporary method for invoking theme hooks. + * + * @param string $hook + * The hook name to invoke. + * @param array $args + * The array of arguments to pass to hook invocation. + * + * @return mixed + * The value returned varies on which hook is invoked. + * + * @todo Remove once a proper Drupal::themeHandler() is created. + * @see https://drupal.org/node/2029819 + */ +function theme_invoke($hook, $args = array()) { + // Allow the active theme to invoke hooks after the theme system has been + // initialized. + global $theme, $base_theme_info; + if (isset($theme)) { + $theme_keys = array(); + foreach ($base_theme_info as $base) { + $theme_keys[] = $base->name; + } + $theme_keys[] = $theme; + foreach ($theme_keys as $theme_key) { + $function = $theme_key . '_' . $hook; + if (function_exists($function)) { + return call_user_func_array($function, $args); + } + } + } +} + +/** * @addtogroup themeable * @{ */ diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php index 96b332f..92cf2a4 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -273,31 +273,6 @@ public function invoke($module, $hook, $args = array()) { } /** - * Rudimentary and temporary method for invoking theme hooks. - * - * @todo Remove once a proper Drupal::themeHandler() is created. - * @see https://drupal.org/node/2029819 - */ - public function themeInvoke($hook, $args = array()) { - // Allow the active theme to invoke hooks after the theme system has been - // initialized. - global $theme, $base_theme_info; - if (isset($theme)) { - $theme_keys = array(); - foreach ($base_theme_info as $base) { - $theme_keys[] = $base->name; - } - $theme_keys[] = $theme; - foreach ($theme_keys as $theme_key) { - $function = $theme_key . '_' . $hook; - if (function_exists($function)) { - return call_user_func_array($function, $args); - } - } - } - } - - /** * Implements \Drupal\Core\Extension\ModuleHandlerInterface::invokeAll(). */ public function invokeAll($hook, $args = array()) { diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php index 29ae59d..b8e24fe 100644 --- a/core/modules/system/theme.api.php +++ b/core/modules/system/theme.api.php @@ -109,7 +109,7 @@ function hook_form_system_theme_settings_alter(&$form, &$form_state) { * @see hook_theme_prepare() */ function hook_preprocess(&$variables, $hook) { - // This hook has been deprecated, do not use it. Please use instead: + // This hook has been deprecated, do not use it. Use the following instead: // hook_theme_prepare(). static $hooks; @@ -158,11 +158,11 @@ function hook_preprocess(&$variables, $hook) { * The variables array (modify in place). * * @deprecated - * @see hook_theme_prepare_SUGGESTION() + * @see hook_theme_prepare_THEME_HOOK() */ function hook_preprocess_HOOK(&$variables) { - // This hook has been deprecated, do not use it. Please use instead: - // hook_theme_prepare_SUGGESTION(). + // This hook has been deprecated, do not use it. Use the following instead: + // hook_theme_prepare_THEME_HOOK(). // This example is from rdf_preprocess_image(). It adds an RDF attribute // to the image hook's variables. @@ -170,22 +170,25 @@ function hook_preprocess_HOOK(&$variables) { } /** - * Prepares theme variables for templates. + * Prepares variables for theme functions and templates. * - * This hook allows modules to prepare theme variables for theme templates. - * It is called for all theme hooks implemented as templates, but not for theme - * hooks implemented as functions. hook_preprocess_HOOK() can be used to - * preprocess variables for a specific theme hook, whether implemented as a - * template or function. + * This hook allows any module or theme to prepare variables for any theme hook. + * hook_theme_prepare_THEME_HOOK() can be used to prepare variables for a + * specific theme hook. * * For more detailed information, see theme(). * - * @param array $context - * The immutable context array. + * @param array $variables + * The associative array of variables, passed by reference (modify in place). + * @param string $hook + * The name of the theme hook called. + * + * @see hook_theme_prepare_alter() + * @see hook_theme_prepare_THEME_HOOK() + * @see hook_theme_prepare_THEME_HOOK_alter() */ -function hook_theme_prepare($context) { +function hook_theme_prepare(&$variables, $hook) { static $hooks; - $variables = array(); // Add contextual links to the variables, if the user has permission. if (!user_access('access contextual links')) { @@ -196,9 +199,6 @@ function hook_theme_prepare($context) { $hooks = theme_get_registry(); } - // Retrieve the original theme hook from context. - $hook = $context['original_theme_hook']; - // Determine the primary theme function argument. if (isset($hooks[$hook]['variables'])) { $keys = array_keys($hooks[$hook]['variables']); @@ -218,59 +218,67 @@ function hook_theme_prepare($context) { $variables['attributes']['class'][] = 'contextual-links-region'; } } - - return $variables; } /** - * Alters the prepared theme variables used in templates. + * Alters the prepared variables used in theme functions and templates. * - * This hook allows any module or theme to add new variables or reorder/remove - * existing variables provided by earlier invocations of hook_theme_prepare() or - * hook_theme_prepare_THEME_HOOK(). + * This hook allows any module or theme to alter existing variables provided by + * earlier invocations of hook_theme_prepare() or + * hook_theme_prepare_THEME_HOOK(). This hook should only be used when it is + * needed to override or add to the $variables array for a theme hook it did not + * define. * * For more detailed information, see theme(). * * @param array $variables - * The variables array (modify in place). - * @param array $context - * The immutable context array. + * The associative array of variables, passed by reference (modify in place). + * @param string $hook + * The name of the theme hook called. + * + * @see hook_theme_prepare() + * @see hook_theme_prepare_THEME_HOOK() + * @see hook_theme_prepare_THEME_HOOK_alter() */ -function hook_theme_prepare_alter(&$variables, $context) { - // Replace the name of the user whom authored the node. - if ($context['theme_hook'] === 'node') { +function hook_theme_prepare_alter(&$variables, $hook) { + // Replace the name of the user whom authored article nodes. + if ($hook === 'node__article') { $variables['name'] = t('Anonymous Unicorn'); } } /** - * Prepares variables used in templates for a specific theme suggestion. + * Prepares variables for a specific theme hook or theme hook suggestion. * - * This hook allows modules to prepare theme variables for a specific theme - * suggestion. It should only be used when it is needed to override or add to - * theme preparation for a theme hook it did not define. + * This hook allow any module or theme to prepare theme variables for a specific + * theme hook or theme hook suggestion. * * THEME_HOOK can be either the base theme hook or a more specific suggestion * using the double-underscore ('__') notation. * * For more detailed information, see theme(). * - * @param array $context - * The immutable context array. + * @param array $variables + * The associative array of variables, passed by reference (modify in place). + * + * @see rdf_preprocess_image() + * @see hook_theme_prepare_THEME_HOOK_alter() + * @see hook_theme_prepare_alter() + * @see hook_theme_prepare() */ -function hook_theme_prepare_THEME_HOOK($context) { - // This example is from rdf_theme_prepare_image(). It adds an RDF attribute +function hook_theme_prepare_THEME_HOOK(&$variables) { + // This example is from rdf_preprocess_image(). It adds an RDF attribute // to the image hook's variables. $variables['attributes']['typeof'] = array('foaf:Image'); - return $variables; } /** - * Alters prepared variables used in templates for a specific theme suggestion. + * Alters prepared variables for a specific theme hook or theme hook suggestion. * - * This hook allows any module or theme to add new variables or reorder/remove - * existing variables provided by earlier invocations of hook_theme_prepare() or - * hook_theme_prepare_THEME_HOOK(). + * This hook allows any module or theme to alter existing variables provided by + * earlier invocations of hook_theme_prepare() or + * hook_theme_prepare_THEME_HOOK(). It should only be used when it is needed + * to override or add to the theme variable for a theme hook it did not define. * * THEME_HOOK can be either the base theme hook or a more specific suggestion * using the double-underscore ('__') notation. @@ -278,12 +286,16 @@ function hook_theme_prepare_THEME_HOOK($context) { * For more detailed information, see theme(). * * @param array $variables - * The variables array (modify in place). - * @param array $context - * The immutable context array. + * The associative array of variables, passed by reference (modify in place). + * + * @see hook_theme_prepare_THEME_HOOK() + * @see hook_theme_prepare_alter() + * @see hook_theme_prepare() */ -function hook_theme_prepare_THEME_HOOK_alter(&$variables, $context) { - // Replace the name of the user whom authored the node. +function hook_theme_prepare_THEME_HOOK_alter(&$variables) { + // Replace the name of the user whom authored article nodes; assuming + // THEME_HOOK was "node__article" and placed in node.module, the function name + // would read: node_theme_prepare_node__article_alter. $variables['name'] = t('Anonymous Unicorn'); }