Chris@0: array( Chris@0: * 'variables' => array( Chris@0: * 'result' => NULL, Chris@0: * 'plugin_id' => NULL, Chris@0: * ), Chris@0: * 'file' => 'search.pages.inc', Chris@0: * ), Chris@0: * ); Chris@0: * @endcode Chris@0: * Given this definition, the template file with the default implementation is Chris@0: * search-result.html.twig, which can be found in the Chris@0: * core/modules/search/templates directory, and the variables for rendering are Chris@0: * the search result and the plugin ID. In addition, there is a function Chris@0: * template_preprocess_search_result(), located in file search.pages.inc, which Chris@0: * preprocesses the information from the input variables so that it can be Chris@0: * rendered by the Twig template; the processed variables that the Twig template Chris@0: * receives are documented in the header of the default Twig template file. Chris@0: * Chris@0: * hook_theme() implementations can also specify that a theme hook Chris@0: * implementation is a theme function, but that is uncommon and not recommended. Chris@0: * Note that while Twig templates will auto-escape variables, theme functions Chris@0: * must explicitly escape any variables by using theme_render_and_autoescape(). Chris@0: * Failure to do so is likely to result in security vulnerabilities. Theme Chris@0: * functions are deprecated in Drupal 8.0.x and will be removed before Chris@0: * Drupal 9.0.x. Use Twig templates instead. Chris@0: * Chris@0: * @section sec_overriding_theme_hooks Overriding Theme Hooks Chris@0: * Themes may register new theme hooks within a hook_theme() implementation, but Chris@0: * it is more common for themes to override default implementations provided by Chris@0: * modules than to register entirely new theme hooks. Themes can override a Chris@0: * default implementation by creating a template file with the same name as the Chris@0: * default implementation; for example, to override the display of search Chris@0: * results, a theme would add a file called search-result.html.twig to its Chris@0: * templates directory. A good starting point for doing this is normally to Chris@0: * copy the default implementation template, and then modifying it as desired. Chris@0: * Chris@0: * In the uncommon case that a theme hook uses a theme function instead of a Chris@0: * template file, a module would provide a default implementation function Chris@0: * called theme_HOOK, where HOOK is the name of the theme hook (for example, Chris@0: * theme_search_result() would be the name of the function for search result Chris@0: * theming). In this case, a theme can override the default implementation by Chris@0: * defining a function called THEME_HOOK() in its THEME.theme file, where THEME Chris@0: * is the machine name of the theme (for example, 'bartik' is the machine name Chris@0: * of the core Bartik theme, and it would define a function called Chris@0: * bartik_search_result() in the bartik.theme file, if the search_result hook Chris@0: * implementation was a function instead of a template). Normally, copying the Chris@0: * default function is again a good starting point for overriding its behavior. Chris@0: * Again, note that theme functions (unlike templates) must explicitly escape Chris@0: * variables using theme_render_and_autoescape() or risk security Chris@0: * vulnerabilities. Theme functions are deprecated in Drupal 8.0.x and will be Chris@0: * removed before Drupal 9.0.x. Use Twig templates instead. Chris@0: * Chris@0: * @section sec_preprocess_templates Preprocessing for Template Files Chris@0: * If the theme implementation is a template file, several functions are called Chris@0: * before the template file is invoked to modify the variables that are passed Chris@0: * to the template. These make up the "preprocessing" phase, and are executed Chris@0: * (if they exist), in the following order (note that in the following list, Chris@0: * HOOK indicates the hook being called or a less specific hook. For example, if Chris@0: * '#theme' => 'node__article' is called, hook is node__article and node. MODULE Chris@0: * indicates a module name, THEME indicates a theme name, and ENGINE indicates a Chris@0: * theme engine name). Modules, themes, and theme engines can provide these Chris@0: * functions to modify how the data is preprocessed, before it is passed to the Chris@0: * theme template: Chris@0: * - template_preprocess(&$variables, $hook): Creates a default set of variables Chris@0: * for all theme hooks with template implementations. Provided by Drupal Core. Chris@0: * - template_preprocess_HOOK(&$variables): Should be implemented by the module Chris@0: * that registers the theme hook, to set up default variables. Chris@0: * - MODULE_preprocess(&$variables, $hook): hook_preprocess() is invoked on all Chris@0: * implementing modules. Chris@0: * - MODULE_preprocess_HOOK(&$variables): hook_preprocess_HOOK() is invoked on Chris@0: * all implementing modules, so that modules that didn't define the theme hook Chris@0: * can alter the variables. Chris@0: * - ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to Chris@0: * set necessary variables for all theme hooks with template implementations. Chris@0: * - ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set Chris@0: * necessary variables for the particular theme hook. Chris@0: * - THEME_preprocess(&$variables, $hook): Allows the theme to set necessary Chris@0: * variables for all theme hooks with template implementations. Chris@0: * - THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary Chris@0: * variables specific to the particular theme hook. Chris@0: * Chris@0: * @section sec_preprocess_functions Preprocessing for Theme Functions Chris@0: * If the theming implementation is a function, only the theme-hook-specific Chris@0: * preprocess functions (the ones ending in _HOOK) are called from the list Chris@0: * above. This is because theme hooks with function implementations need to be Chris@0: * fast, and calling the non-theme-hook-specific preprocess functions for them Chris@0: * would incur a noticeable performance penalty. Chris@0: * Chris@0: * @section sec_suggestions Theme hook suggestions Chris@0: * In some cases, instead of calling the base theme hook implementation (either Chris@0: * the default provided by the module that defined the hook, or the override Chris@0: * provided by the theme), the theme system will instead look for "suggestions" Chris@0: * of other hook names to look for. Suggestions can be specified in several Chris@0: * ways: Chris@0: * - In a render array, the '#theme' property (which gives the name of the hook Chris@0: * to use) can be an array of theme hook names instead of a single hook name. Chris@0: * In this case, the render system will look first for the highest-priority Chris@0: * hook name, and if no implementation is found, look for the second, and so Chris@0: * on. Note that the highest-priority suggestion is at the end of the array. Chris@0: * - In a render array, the '#theme' property can be set to the name of a hook Chris@0: * with a '__SUGGESTION' suffix. For example, in search results theming, the Chris@0: * hook 'item_list__search_results' is given. In this case, the render system Chris@0: * will look for theme templates called item-list--search-results.html.twig, Chris@0: * which would only be used for rendering item lists containing search Chris@0: * results, and if this template is not found, it will fall back to using the Chris@0: * base item-list.html.twig template. This type of suggestion can also be Chris@0: * combined with providing an array of theme hook names as described above. Chris@0: * - A module can implement hook_theme_suggestions_HOOK(). This allows the Chris@0: * module that defines the theme template to dynamically return an array Chris@0: * containing specific theme hook names (presumably with '__' suffixes as Chris@0: * defined above) to use as suggestions. For example, the Search module Chris@0: * does this in search_theme_suggestions_search_result() to suggest Chris@0: * search_result__PLUGIN as the theme hook for search result items, where Chris@0: * PLUGIN is the machine name of the particular search plugin type that was Chris@0: * used for the search (such as node_search or user_search). Chris@0: * Chris@0: * For further information on overriding theme hooks see Chris@0: * https://www.drupal.org/node/2186401 Chris@0: * Chris@0: * @section sec_alternate_suggestions Altering theme hook suggestions Chris@0: * Modules can also alter the theme suggestions provided using the mechanisms Chris@0: * of the previous section. There are two hooks for this: the Chris@0: * theme-hook-specific hook_theme_suggestions_HOOK_alter() and the generic Chris@0: * hook_theme_suggestions_alter(). These hooks get the current list of Chris@0: * suggestions as input, and can change this array (adding suggestions and Chris@0: * removing them). Chris@0: * Chris@0: * @section assets Assets Chris@0: * We can distinguish between three types of assets: Chris@0: * - Unconditional page-level assets (loaded on all pages where the theme is in Chris@0: * use): these are defined in the theme's *.info.yml file. Chris@0: * - Conditional page-level assets (loaded on all pages where the theme is in Chris@0: * use and a certain condition is met): these are attached in Chris@0: * hook_page_attachments_alter(), e.g.: Chris@0: * @code Chris@0: * function THEME_page_attachments_alter(array &$page) { Chris@0: * if ($some_condition) { Chris@0: * $page['#attached']['library'][] = 'mytheme/something'; Chris@0: * } Chris@0: * } Chris@0: * @endcode Chris@0: * - Template-specific assets (loaded on all pages where a specific template is Chris@0: * in use): these can be added by in preprocessing functions, using @code Chris@0: * $variables['#attached'] @endcode, e.g.: Chris@0: * @code Chris@0: * function THEME_preprocess_menu_local_action(array &$variables) { Chris@0: * // We require Modernizr's touch test for button styling. Chris@0: * $variables['#attached']['library'][] = 'core/modernizr'; Chris@0: * } Chris@0: * @endcode Chris@0: * Chris@0: * @see hooks Chris@0: * @see callbacks Chris@0: * @see theme_render Chris@0: * Chris@0: * @} Chris@0: */ Chris@0: Chris@0: /** Chris@0: * @defgroup theme_render Render API overview Chris@0: * @{ Chris@0: * Overview of the Theme system and Render API. Chris@0: * Chris@0: * The main purpose of Drupal's Theme system is to give themes complete control Chris@0: * over the appearance of the site, which includes the markup returned from HTTP Chris@0: * requests and the CSS files used to style that markup. In order to ensure that Chris@0: * a theme can completely customize the markup, module developers should avoid Chris@0: * directly writing HTML markup for pages, blocks, and other user-visible output Chris@0: * in their modules, and instead return structured "render arrays" (see Chris@0: * @ref arrays below). Doing this also increases usability, by ensuring that the Chris@0: * markup used for similar functionality on different areas of the site is the Chris@0: * same, which gives users fewer user interface patterns to learn. Chris@0: * Chris@0: * For further information on the Theme and Render APIs, see: Chris@0: * - https://www.drupal.org/docs/8/theming Chris@0: * - https://www.drupal.org/developing/api/8/render Chris@0: * - @link themeable Theme system overview @endlink. Chris@0: * Chris@0: * @section arrays Render arrays Chris@0: * The core structure of the Render API is the render array, which is a Chris@0: * hierarchical associative array containing data to be rendered and properties Chris@0: * describing how the data should be rendered. A render array that is returned Chris@0: * by a function to specify markup to be sent to the web browser or other Chris@0: * services will eventually be rendered by a call to drupal_render(), which will Chris@0: * recurse through the render array hierarchy if appropriate, making calls into Chris@0: * the theme system to do the actual rendering. If a function or method actually Chris@0: * needs to return rendered output rather than a render array, the best practice Chris@0: * would be to create a render array, render it by calling drupal_render(), and Chris@0: * return that result, rather than writing the markup directly. See the Chris@0: * documentation of drupal_render() for more details of the rendering process. Chris@0: * Chris@0: * Each level in the hierarchy of a render array (including the outermost array) Chris@0: * has one or more array elements. Array elements whose names start with '#' are Chris@0: * known as "properties", and the array elements with other names are "children" Chris@0: * (constituting the next level of the hierarchy); the names of children are Chris@0: * flexible, while property names are specific to the Render API and the Chris@0: * particular type of data being rendered. A special case of render arrays is a Chris@0: * form array, which specifies the form elements for an HTML form; see the Chris@0: * @link form_api Form generation topic @endlink for more information on forms. Chris@0: * Chris@0: * Render arrays (at any level of the hierarchy) will usually have one of the Chris@0: * following properties defined: Chris@0: * - #type: Specifies that the array contains data and options for a particular Chris@0: * type of "render element" (for example, 'form', for an HTML form; Chris@0: * 'textfield', 'submit', for HTML form element types; 'table', for a table Chris@0: * with rows, columns, and headers). See @ref elements below for more on Chris@0: * render element types. Chris@0: * - #theme: Specifies that the array contains data to be themed by a particular Chris@0: * theme hook. Modules define theme hooks by implementing hook_theme(), which Chris@0: * specifies the input "variables" used to provide data and options; if a Chris@0: * hook_theme() implementation specifies variable 'foo', then in a render Chris@0: * array, you would provide this data using property '#foo'. Modules Chris@0: * implementing hook_theme() also need to provide a default implementation for Chris@0: * each of their theme hooks, normally in a Twig file. For more information Chris@0: * and to discover available theme hooks, see the documentation of Chris@0: * hook_theme() and the Chris@0: * @link themeable Default theme implementations topic. @endlink Chris@0: * - #markup: Specifies that the array provides HTML markup directly. Unless Chris@0: * the markup is very simple, such as an explanation in a paragraph tag, it Chris@0: * is normally preferable to use #theme or #type instead, so that the theme Chris@0: * can customize the markup. Note that the value is passed through Chris@0: * \Drupal\Component\Utility\Xss::filterAdmin(), which strips known XSS Chris@0: * vectors while allowing a permissive list of HTML tags that are not XSS Chris@0: * vectors. (For example,