Commit 6ad38cd2 authored by catch's avatar catch
Browse files

Issue #3097889 by longwave, paulocs, anushrikumari, SenthilMohith, andypost,...

Issue #3097889 by longwave, paulocs, anushrikumari, SenthilMohith, andypost, Gábor Hojtsy, catch, lauriii, Wim Leers: Remove deprecated theme functions
parent e9b366c9
Loading
Loading
Loading
Loading
+0 −59
Original line number Diff line number Diff line
@@ -123,65 +123,6 @@ function drupal_theme_rebuild() {
  \Drupal::service('theme.registry')->reset();
}

/**
 * Allows themes and/or theme engines to discover overridden theme functions.
 *
 * @param array $cache
 *   The existing cache of theme hooks to test against.
 * @param array $prefixes
 *   An array of prefixes to test, in reverse order of importance.
 *
 * @return array
 *   The functions found, suitable for returning from hook_theme;
 */
function drupal_find_theme_functions($cache, $prefixes) {
  $implementations = [];
  $grouped_functions = \Drupal::service('theme.registry')->getPrefixGroupedUserFunctions($prefixes);

  foreach ($cache as $hook => $info) {
    foreach ($prefixes as $prefix) {
      // Find theme functions that implement possible "suggestion" variants of
      // registered theme hooks and add those as new registered theme hooks.
      // The 'pattern' key defines a common prefix that all suggestions must
      // start with. The default is the name of the hook followed by '__'. A
      // 'base hook' key is added to each entry made for a found suggestion,
      // so that common functionality can be implemented for all suggestions of
      // the same base hook. To keep things simple, deep hierarchy of
      // suggestions is not supported: each suggestion's 'base hook' key
      // refers to a base hook, not to another suggestion, and all suggestions
      // are found using the base hook's pattern, not a pattern from an
      // intermediary suggestion.
      $pattern = $info['pattern'] ?? ($hook . '__');
      // Grep only the functions which are within the prefix group.
      [$first_prefix] = explode('_', $prefix, 2);
      if (!isset($info['base hook']) && !empty($pattern) && isset($grouped_functions[$first_prefix])) {
        $matches = preg_grep('/^' . $prefix . '_' . $pattern . '/', $grouped_functions[$first_prefix]);
        if ($matches) {
          foreach ($matches as $match) {
            $new_hook = substr($match, strlen($prefix) + 1);
            $arg_name = isset($info['variables']) ? 'variables' : 'render element';
            $implementations[$new_hook] = [
              'function' => $match,
              $arg_name => $info[$arg_name],
              'base hook' => $hook,
            ];
          }
        }
      }
      // Find theme functions that implement registered theme hooks and include
      // that in what is returned so that the registry knows that the theme has
      // this implementation.
      if (function_exists($prefix . '_' . $hook)) {
        $implementations[$hook] = [
          'function' => $prefix . '_' . $hook,
        ];
      }
    }
  }

  return $implementations;
}

/**
 * Allows themes and/or theme engines to easily discover overridden templates.
 *
+35 −77
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@
 * implementing hook_theme(), which specifies the name of the hook, the input
 * "variables" used to provide data and options, and other information. Modules
 * implementing hook_theme() also need to provide a default implementation for
 * each of their theme hooks, normally in a Twig file, and they may also provide
 * each of their theme hooks in a Twig file, and they may also provide
 * preprocessing functions. For example, the core Search module defines a theme
 * hook for a search result item in search_theme():
 * @code
@@ -68,14 +68,6 @@
 * rendered by the Twig template; the processed variables that the Twig template
 * receives are documented in the header of the default Twig template file.
 *
 * hook_theme() implementations can also specify that a theme hook
 * implementation is a theme function, but that is uncommon and not recommended.
 * Note that while Twig templates will auto-escape variables, theme functions
 * must explicitly escape any variables by using theme_render_and_autoescape().
 * Failure to do so is likely to result in security vulnerabilities. Theme
 * functions are deprecated in Drupal 8.0.x and will be removed before
 * Drupal 9.0.x. Use Twig templates instead.
 *
 * @section sec_overriding_theme_hooks Overriding Theme Hooks
 * Themes may register new theme hooks within a hook_theme() implementation, but
 * it is more common for themes to override default implementations provided by
@@ -86,33 +78,16 @@
 * templates directory. A good starting point for doing this is normally to
 * copy the default implementation template, and then modifying it as desired.
 *
 * In the uncommon case that a theme hook uses a theme function instead of a
 * template file, a module would provide a default implementation function
 * called theme_HOOK, where HOOK is the name of the theme hook (for example,
 * theme_search_result() would be the name of the function for search result
 * theming). In this case, a theme can override the default implementation by
 * defining a function called THEME_HOOK() in its THEME.theme file, where THEME
 * is the machine name of the theme (for example, 'bartik' is the machine name
 * of the core Bartik theme, and it would define a function called
 * bartik_search_result() in the bartik.theme file, if the search_result hook
 * implementation was a function instead of a template). Normally, copying the
 * default function is again a good starting point for overriding its behavior.
 * Again, note that theme functions (unlike templates) must explicitly escape
 * variables using theme_render_and_autoescape() or risk security
 * vulnerabilities. Theme functions are deprecated in Drupal 8.0.x and will be
 * removed before Drupal 9.0.x. Use Twig templates instead.
 *
 * @section sec_preprocess_templates Preprocessing for Template Files
 * If the theme implementation is a template file, several functions are called
 * before the template file is invoked to modify the variables that are passed
 * to the template. These make up the "preprocessing" phase, and are executed
 * (if they exist), in the following order (note that in the following list,
 * HOOK indicates the hook being called or a less specific hook. For example, if
 * '#theme' => 'node__article' is called, hook is node__article and node. MODULE
 * indicates a module name, THEME indicates a theme name, and ENGINE indicates a
 * theme engine name). Modules, themes, and theme engines can provide these
 * functions to modify how the data is preprocessed, before it is passed to the
 * theme template:
 * Several functions are called before the template file is invoked to modify
 * the variables that are passed to the template. These make up the
 * "preprocessing" phase, and are executed (if they exist), in the following
 * order (note that in the following list, HOOK indicates the hook being called
 * or a less specific hook. For example, if '#theme' => 'node__article' is
 * called, hook is node__article and node. MODULE indicates a module name,
 * THEME indicates a theme name, and ENGINE indicates a theme engine name).
 * Modules, themes, and theme engines can provide these functions to modify how
 * the data is preprocessed, before it is passed to the theme template:
 * - template_preprocess(&$variables, $hook): Creates a default set of variables
 *   for all theme hooks with template implementations. Provided by Drupal Core.
 * - template_preprocess_HOOK(&$variables): Should be implemented by the module
@@ -131,13 +106,6 @@
 * - THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary
 *   variables specific to the particular theme hook.
 *
 * @section sec_preprocess_functions Preprocessing for Theme Functions
 * If the theming implementation is a function, only the theme-hook-specific
 * preprocess functions (the ones ending in _HOOK) are called from the list
 * above. This is because theme hooks with function implementations need to be
 * fast, and calling the non-theme-hook-specific preprocess functions for them
 * would incur a noticeable performance penalty.
 *
 * @section sec_suggestions Theme hook suggestions
 * In some cases, instead of calling the base theme hook implementation (either
 * the default provided by the module that defined the hook, or the override
@@ -551,10 +519,8 @@ function hook_form_system_theme_settings_alter(&$form, \Drupal\Core\Form\FormSta
 * Preprocess theme variables for templates.
 *
 * This hook allows modules to preprocess 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.
 * hook_preprocess_HOOK() can be used to preprocess variables for a specific
 * theme hook.
 *
 * For more detailed information, see the
 * @link themeable Theme system overview topic @endlink.
@@ -620,8 +586,8 @@ function hook_preprocess_HOOK(&$variables) {
/**
 * Provides alternate named suggestions for a specific theme hook.
 *
 * This hook allows modules to provide alternative theme function or template
 * name suggestions.
 * This hook allows modules to provide alternative theme template name
 * suggestions.
 *
 * HOOK is the least-specific version of the hook being called. For example, if
 * '#theme' => 'node__article' is called, then hook_theme_suggestions_node()
@@ -680,8 +646,7 @@ function hook_theme_suggestions_HOOK(array $variables) {
 * @endcode
 *
 * @param array $suggestions
 *   An array of alternate, more specific names for template files or theme
 *   functions.
 *   An array of alternate, more specific names for template files.
 * @param array $variables
 *   An array of variables passed to the theme hook. Note that this hook is
 *   invoked before any variable preprocessing.
@@ -704,8 +669,8 @@ function hook_theme_suggestions_alter(array &$suggestions, array $variables, $ho
/**
 * Alters named suggestions for a specific theme hook.
 *
 * This hook allows any module or theme to provide alternative theme function or
 * template name suggestions and reorder or remove suggestions provided by
 * This hook allows any module or theme to provide alternative template name
 * suggestions and reorder or remove suggestions provided by
 * hook_theme_suggestions_HOOK() or by earlier invocations of this hook.
 *
 * HOOK is the least-specific version of the hook being called. For example, if
@@ -1152,33 +1117,26 @@ function hook_page_bottom(array &$page_bottom) {
 *     where the array keys are the names of the variables, and the array
 *     values are the default values if they are not given in the render array.
 *     Template implementations receive each array key as a variable in the
 *     template file (so they must be legal PHP/Twig variable names). Function
 *     implementations are passed the variables in a single $variables function
 *     argument. If you are using these variables in a render array, prefix the
 *     variable names defined here with a #.
 *     template file (so they must be legal PHP/Twig variable names). If you
 *     are using these variables in a render array, prefix the variable names
 *     defined here with a #.
 *   - render element: Used for render element items only: the name of the
 *     renderable element or element tree to pass to the theme function. This
 *     name is used as the name of the variable that holds the renderable
 *     element or tree in preprocess and process functions.
 *   - file: The file the implementation resides in. This file will be included
 *     prior to the theme being rendered, to make sure that the function or
 *     preprocess function (as needed) is actually loaded.
 *     renderable element or element tree to pass to the template. This name is
 *     used as the name of the variable that holds the renderable element or
 *     tree in preprocess and process functions.
 *   - file: The file that any preprocess implementations reside in. This file
 *     will be included prior to the template being rendered, to make sure that
 *     the preprocess function (as needed) is actually loaded.
 *   - path: Override the path of the file to be used. Ordinarily the module or
 *     theme path will be used, but if the file will not be in the default
 *     path, include it here. This path should be relative to the Drupal root
 *     directory.
 *   - template: If specified, the theme implementation is a template file, and
 *     this is the template name. Do not add 'html.twig' on the end of the
 *     template name. The extension will be added automatically by the default
 *     rendering engine (which is Twig.) If 'path' is specified, 'template'
 *     should also be specified. If neither 'template' nor 'function' are
 *     specified, a default template name will be assumed. For example, if a
 *     module registers the 'search_result' theme hook, 'search-result' will be
 *     assigned as its template name.
 *   - function: (deprecated in Drupal 8.0.x, will be removed in Drupal 9.0.x)
 *     If specified, this will be the function name to invoke for this
 *     implementation. If neither 'template' nor 'function' are specified, a
 *     default template name will be assumed. See above for more details.
 *   - template: The template name, without 'html.twig' on the end. The
 *     extension will be added automatically by the default rendering engine
 *     (which is Twig.) If 'path' is specified, 'template' should also be
 *     specified. If not specified, a default template name will be assumed.
 *     For example, if a module registers the 'search_result' theme hook,
 *     'search-result' will be assigned as its template name.
 *   - base hook: Used for theme suggestions only: the base theme hook name.
 *     Instead of this suggestion's implementation being used directly, the base
 *     hook will be invoked with this implementation as its first suggestion.
@@ -1188,8 +1146,8 @@ function hook_page_bottom(array &$page_bottom) {
 *     HOOK is the base hook) changes the suggestion order, a different
 *     suggestion may be used in place of this suggestion. If after
 *     hook_theme_suggestions_HOOK() this suggestion remains the first
 *     suggestion, then this suggestion's function or template will be used to
 *     generate the rendered output.
 *     suggestion, then this suggestion's template will be used to generate the
 *     rendered output.
 *   - pattern: A regular expression pattern to be used to allow this theme
 *     implementation to have a dynamic name. The convention is to use __ to
 *     differentiate the dynamic portion of the theme. For example, to allow
@@ -1244,7 +1202,7 @@ function hook_theme($existing, $type, $theme, $path) {
 * Alter the theme registry information returned from hook_theme().
 *
 * The theme registry stores information about all available theme hooks,
 * including which callback functions those hooks will call when triggered,
 * including which preprocess functions those hooks will call when triggered,
 * what template files are exposed by these hooks, and so on.
 *
 * Note that this hook is only executed as the theme cache is re-built.
+5 −36
Original line number Diff line number Diff line
@@ -53,9 +53,7 @@ class Registry implements DestructableInterface {
   *     from; e.g., 'node' for theme hook 'node' of Node module.
   *   - theme path: The effective \Drupal\Core\Theme\ActiveTheme::getPath()
   *      during \Drupal\Core\Theme\ThemeManagerInterface::render(), available
   *      as 'directory' variable in templates. For functions, it should point
   *      to the respective theme. For templates, it should point to the
   *      directory that contains the template.
   *      as 'directory' variable in templates.
   *   - includes: (optional) An array of include files to load when the theme
   *     hook is executed by \Drupal\Core\Theme\ThemeManagerInterface::render().
   *   - file: (optional) A filename to add to 'includes', either prefixed with
@@ -76,13 +74,11 @@ class Registry implements DestructableInterface {
   *   - template_file: A full path and file name to a template file to use.
   *     Allows any extension to override the effective template file.
   *   - engine: The theme engine to use for the template file.
   *   In case of a theme function:
   *   - function: The function name to call to generate the output.
   *   For any registered theme hook, including theme hook suggestions:
   *   - preprocess: An array of theme variable preprocess callbacks to invoke
   *     before invoking final theme variable processors.
   *   - process: An array of theme variable process callbacks to invoke
   *     before invoking the actual theme function or template.
   *     before invoking the actual template.
   */
  protected $registry = [];

@@ -299,7 +295,7 @@ public function getBaseHook($hook) {
    // Iteratively strip everything after the last '__' delimiter, until a
    // base hook definition is found. Recursive base hooks of base hooks are
    // not supported, so the base hook must be an original implementation that
    // points to a theme function or template.
    // points to a template.
    while ($pos = strrpos($base_hook, '__')) {
      $base_hook = substr($base_hook, 0, $pos);
      if (isset($this->registry[$base_hook]['exists'])) {
@@ -409,12 +405,6 @@ protected function build() {
   *   describing the hook:
   *   - 'type': The passed-in $type.
   *   - 'theme path': The passed-in $path.
   *   - 'function': The name of the function generating output for this theme
   *     hook. Either defined explicitly in hook_theme() or, if neither
   *     'function' nor 'template' is defined, then the default theme function
   *     name is used. The default theme function name is the theme hook
   *     prefixed by either 'theme_' for modules or '$name_' for everything
   *     else. If 'function' is defined, 'template' is not used.
   *   - 'template': The filename of the template generating output for this
   *     theme hook. The template is in the directory defined by the 'path' key
   *     of hook_theme() or defaults to "$path/templates".
@@ -506,24 +496,11 @@ protected function processExtension(array &$cache, $name, $type, $theme, $path)
          $result[$hook]['includes'][] = $include_file;
        }

        // A template file is the default implementation for a theme hook, but
        // if the theme hook specifies a function callback instead, check to
        // ensure the function actually exists.
        if (isset($info['function'])) {
          trigger_error(sprintf('Theme functions are deprecated in drupal:8.0.0 and are removed from drupal:10.0.0. Use Twig templates instead of %s(). See https://www.drupal.org/node/1831138', $info['function']), E_USER_DEPRECATED);
          if (!function_exists($info['function'])) {
            throw new \BadFunctionCallException(sprintf(
              'Theme hook "%s" refers to a theme function callback that does not exist: "%s"',
              $hook,
              $info['function']
            ));
          }
        }
        // Provide a default naming convention for 'template' based on the
        // hook used. If the template does not exist, the theme engine used
        // should throw an exception at runtime when attempting to include
        // the template file.
        elseif (!isset($info['template'])) {
        if (!isset($info['template'])) {
          $info['template'] = strtr($hook, '_', '-');
          $result[$hook]['template'] = $info['template'];
        }
@@ -540,8 +517,7 @@ protected function processExtension(array &$cache, $name, $type, $theme, $path)
          $result[$hook] += array_intersect_key($cache[$hook], $hook_defaults);
        }

        // Preprocess variables for all theming hooks, whether the hook is
        // implemented as a template or as a function. Ensure they are arrays.
        // Preprocess variables for all theming hooks. Ensure they are arrays.
        if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
          $info['preprocess functions'] = [];
          $prefixes = [];
@@ -590,13 +566,6 @@ protected function processExtension(array &$cache, $name, $type, $theme, $path)
        }
        $result[$hook]['preprocess functions'] = $info['preprocess functions'];

        // If a theme implementation definition provides both 'template' and
        // 'function', the 'function' will be used. In this case, if the new
        // result provides a 'template' value, any existing 'function' value
        // must be removed for the override to be called.
        if (isset($result[$hook]['template'])) {
          unset($cache[$hook]['function']);
        }
      }

      // Merge the newly created theme hooks into the existing cache.
+59 −73
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
namespace Drupal\Core\Theme;

use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\StackedRouteMatchInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -256,8 +255,7 @@ public function render($hook, array $variables) {
      }
    }

    // Include a file if the theme function or variable preprocessor is held
    // elsewhere.
    // Include a file if the variable preprocessor is held elsewhere.
    if (!empty($info['includes'])) {
      foreach ($info['includes'] as $include_file) {
        include_once $this->root . '/' . $include_file;
@@ -307,17 +305,7 @@ public function render($hook, array $variables) {
      }
    }

    // Generate the output using either a function or a template.
    $output = '';
    if (isset($info['function'])) {
      if (function_exists($info['function'])) {
        // Theme functions do not render via the theme engine, so the output is
        // not autoescaped. However, we can only presume that the theme function
        // has been written correctly and that the markup is safe.
        $output = Markup::create($info['function']($variables));
      }
    }
    else {
    // Generate the output using a template.
    $render_function = 'twig_render_template';
    $extension = '.html.twig';

@@ -382,8 +370,6 @@ public function render($hook, array $variables) {
      $variables['theme_hook_suggestion'] = $theme_hook_suggestion;
    }
    $output = $render_function($template_file, $variables);
    }

    return ($output instanceof MarkupInterface) ? $output : (string) $output;
  }

+0 −13
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Include file for testing theme suggestion hooks for legacy theme functions.
 */

/**
 * Returns HTML for a theme function include test.
 */
function theme_theme_suggestions_test_include($variables) {
  return 'Function suggested via suggestion alter hook found in include file.';
}
Loading