Commit d3f105ed authored by alexpott's avatar alexpott

Issue #2226207 by lauriii, mgbellaire, Cottser, m1r1k, Mark Carver, LinL,...

Issue #2226207 by lauriii, mgbellaire, Cottser, m1r1k, Mark Carver, LinL, rachel_norfolk, rteijeiro, skwashd, davidhernandez, euphoric_mv: Make 'template' the default output option for hook_theme().
parent 12561915
......@@ -2295,6 +2295,7 @@ function drupal_common_theme() {
),
'indentation' => array(
'variables' => array('size' => 1),
'function' => 'theme_indentation',
),
// From theme.maintenance.inc.
'maintenance_page' => array(
......@@ -2311,9 +2312,15 @@ function drupal_common_theme() {
),
'authorize_message' => array(
'variables' => array('message' => NULL, 'success' => TRUE),
'function' => 'theme_authorize_message',
'path' => 'core/includes',
'file' => 'theme.maintenance.inc',
),
'authorize_report' => array(
'variables' => array('messages' => array()),
'function' => 'theme_authorize_report',
'path' => 'core/includes',
'file' => 'theme.maintenance.inc',
),
// From pager.inc.
'pager' => array(
......
......@@ -401,6 +401,9 @@ protected function build() {
* @see _theme()
* @see hook_theme()
* @see list_themes()
* @see twig_render_template()
*
* @throws \BadFunctionCallException
*/
protected function processExtension(&$cache, $name, $type, $theme, $path) {
$result = array();
......@@ -430,12 +433,6 @@ protected function processExtension(&$cache, $name, $type, $theme, $path) {
$result[$hook]['type'] = $type;
$result[$hook]['theme path'] = $path;
// If function and file are omitted, default to standard naming
// conventions.
if (!isset($info['template']) && !isset($info['function'])) {
$result[$hook]['function'] = ($type == 'module' ? 'theme_' : $name . '_') . $hook;
}
if (isset($cache[$hook]['includes'])) {
$result[$hook]['includes'] = $cache[$hook]['includes'];
}
......@@ -451,20 +448,37 @@ protected function processExtension(&$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']) && !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'])) {
$info['template'] = strtr($hook, '_', '-');
$result[$hook]['template'] = $info['template'];
}
// Prepend the current theming path when none is set. This is required
// for the default theme engine to know where the template lives.
if (isset($result[$hook]['template']) && !isset($info['path'])) {
$result[$hook]['path'] = $path . '/templates';
}
// If the default keys are not set, use the default values registered
// by the module.
if (isset($cache[$hook])) {
$result[$hook] += array_intersect_key($cache[$hook], $hook_defaults);
}
// The following apply only to theming hooks implemented as templates.
if (isset($info['template'])) {
// Prepend the current theming path when none is set.
if (!isset($info['path'])) {
$result[$hook]['template'] = $path . '/templates/' . $info['template'];
}
}
// Preprocess variables for all theming hooks, whether the hook is
// implemented as a template or as a function. Ensure they are arrays.
if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
......
......@@ -63,6 +63,7 @@ function book_theme() {
),
'book_link' => array(
'render element' => 'element',
'function' => 'theme_book_link',
),
'book_export_html' => array(
'variables' => array('title' => NULL, 'contents' => NULL, 'depth' => NULL),
......@@ -71,6 +72,7 @@ function book_theme() {
'book_admin_table' => array(
'render element' => 'form',
'file' => 'book.admin.inc',
'function' => 'theme_book_admin_table',
),
'book_all_books_block' => array(
'render element' => 'book_menus',
......
......@@ -66,6 +66,7 @@ function field_ui_theme() {
return array(
'field_ui_table' => array(
'render element' => 'elements',
'function' => 'theme_field_ui_table',
),
);
}
......
......@@ -100,10 +100,12 @@ function language_theme() {
'language_negotiation_configure_browser_form_table' => array(
'render element' => 'form',
'file' => 'language.admin.inc',
'function' => 'theme_language_negotiation_configure_browser_form_table',
),
'language_content_settings_table' => array(
'render element' => 'element',
'file' => 'language.admin.inc',
'function' => 'theme_language_content_settings_table',
),
);
}
......
......@@ -182,6 +182,7 @@ function locale_theme() {
'locale_translate_edit_form_strings' => array(
'render element' => 'form',
'file' => 'locale.pages.inc',
'function' => 'theme_locale_translate_edit_form_strings',
),
'locale_translation_last_check' => array(
'variables' => array('last' => NULL),
......
......@@ -78,6 +78,7 @@ function menu_ui_theme() {
'menu_overview_form' => array(
'file' => 'menu_ui.admin.inc',
'render element' => 'form',
'function' => 'theme_menu_overview_form',
),
);
}
......
......@@ -141,6 +141,7 @@ function node_theme() {
),
'node_search_admin' => array(
'render element' => 'form',
'function' => 'theme_node_search_admin',
),
'node_add_list' => array(
'variables' => array('content' => NULL),
......
......@@ -80,6 +80,7 @@ function responsive_image_theme() {
'attributes' => array(),
'mapping_id' => array(),
),
'function' => 'theme_responsive_image',
),
'responsive_image_formatter' => array(
'variables' => array(
......@@ -88,6 +89,7 @@ function responsive_image_theme() {
'image_style' => NULL,
'mapping_id' => array(),
),
'function' => 'theme_responsive_image_formatter',
),
'responsive_image_source' => array(
'variables' => array(
......@@ -96,6 +98,7 @@ function responsive_image_theme() {
'dimensions' => NULL,
'media' => NULL,
),
'function' => 'theme_responsive_image_source',
),
);
}
......
......@@ -981,17 +981,17 @@ function hook_help($route_name, \Drupal\Core\Routing\RouteMatchInterface $route_
* 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, this theme implementation is a template, and
* this is the template file without an extension. Do not put .html.twig on
* this file; that extension will be added automatically by the default
* rendering engine (which is Twig). If 'path' above is specified, the
* template should also be in this path.
* - 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: If specified, this will be the function name to invoke for
* this implementation. If neither 'template' nor 'function' is specified,
* a default function name will be assumed. For example, if a module
* registers the 'node' theme hook, 'theme_node' will be assigned to its
* function. If the chameleon theme registers the node hook, it will be
* assigned 'chameleon_node' as its function.
* this implementation. If neither 'template' nor 'function' are specified,
* a default template name will be assumed. See above for more details.
* - 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.
......
......@@ -187,10 +187,12 @@ function system_theme() {
'system_modules_details' => array(
'render element' => 'form',
'file' => 'system.admin.inc',
'function' => 'theme_system_modules_details',
),
'system_modules_uninstall' => array(
'render element' => 'form',
'file' => 'system.admin.inc',
'function' => 'theme_system_modules_uninstall',
),
'status_report' => array(
'variables' => array('requirements' => NULL),
......@@ -219,6 +221,7 @@ function system_theme() {
),
'system_compact_link' => array(
'variables' => array(),
'function' => 'theme_system_compact_link',
),
));
}
......
......@@ -123,6 +123,7 @@ function common_test_theme() {
),
'common_test_empty' => array(
'variables' => array('foo' => 'foo'),
'function' => 'theme_common_test_empty',
),
);
}
......
......@@ -12,6 +12,7 @@ function theme_suggestions_test_theme() {
$items['theme_suggestions_test_include'] = array(
'file' => 'theme_suggestions_test.inc',
'variables' => array(),
'function' => 'theme_theme_suggestions_test_include',
);
return $items;
}
......
......@@ -9,6 +9,7 @@ function theme_test_theme($existing, $type, $theme, $path) {
$items['theme_test'] = array(
'file' => 'theme_test.inc',
'variables' => array('foo' => ''),
'function' => 'theme_theme_test',
);
$items['theme_test_template_test'] = array(
'template' => 'theme_test.template_test',
......@@ -34,12 +35,15 @@ function theme_test_theme($existing, $type, $theme, $path) {
);
$items['theme_test_function_suggestions'] = array(
'variables' => array(),
'function' => 'theme_theme_test_function_suggestions',
);
$items['theme_test_suggestions_include'] = array(
'variables' => array(),
'function' => 'theme_theme_test_suggestions_include',
);
$items['theme_test_foo'] = array(
'variables' => array('foo' => NULL),
'function' => 'theme_theme_test_foo',
);
$items['theme_test_render_element'] = array(
'render element' => 'elements',
......@@ -47,9 +51,11 @@ function theme_test_theme($existing, $type, $theme, $path) {
);
$items['theme_test_render_element_children'] = array(
'render element' => 'element',
'function' => 'theme_theme_test_render_element_children',
);
$items['theme_test_function_template_override'] = array(
'variables' => array(),
'function' => 'theme_theme_test_function_template_override',
);
$info['test_theme_not_existing_function'] = array(
'function' => 'test_theme_not_existing_function',
......
......@@ -42,9 +42,6 @@ function toolbar_theme($existing, $type, $theme, $path) {
'render element' => 'element',
'template' => 'toolbar',
);
$items['toolbar_item'] = array(
'render element' => 'element',
);
return $items;
}
......
......@@ -205,11 +205,11 @@ function update_theme() {
'file' => 'update.report.inc',
'template' => 'update-project-status',
),
// We are using template instead of '#type' => 'table' here to keep markup
// out of preprocess and allow for easier changes to markup.
'update_version' => array(
'variables' => array('version' => NULL, 'title' => NULL, 'attributes' => array()),
'file' => 'update.report.inc',
// We are using template instead of '#type' => 'table' here to keep markup
// out of preprocess and allow for easier changes to markup.
'template' => 'update-version',
),
);
......
......@@ -129,6 +129,7 @@ function views_theme($existing, $type, $theme, $path) {
// Default view themes
$hooks['views_view_field'] = $base + array(
'variables' => array('view' => NULL, 'field' => NULL, 'row' => NULL),
'function' => 'theme_views_view_field',
);
$hooks['views_view_grouping'] = $base + array(
'variables' => array('view' => NULL, 'grouping' => NULL, 'grouping_level' => NULL, 'rows' => NULL, 'title' => NULL),
......@@ -149,9 +150,9 @@ function views_theme($existing, $type, $theme, $path) {
if (!isset($def['theme']) || empty($def['register_theme'])) {
continue;
}
// For each theme registration we a base directory to look for the
// templates folder. This will be in any case the root of the given module
// so we always need a module definition.
// For each theme registration, we have a base directory to check for the
// templates folder. This will be relative to the root of the given module
// folder, so we always need a module definition.
// @todo: watchdog or exception?
if (!isset($def['provider']) || !$module_handler->moduleExists($def['provider'])) {
continue;
......@@ -161,35 +162,44 @@ function views_theme($existing, $type, $theme, $path) {
'variables' => $variables[$type],
);
// For the views module we ensure views.theme.inc is included.
if ($def['provider'] == 'views') {
$def['theme_file'] = 'views.theme.inc';
}
// We always use the module directory as base dir.
$module_dir = drupal_get_path('module', $def['provider']);
$hooks[$def['theme']]['path'] = $module_dir;
// For the views module we ensure views.theme.inc is included.
if ($def['provider'] == 'views') {
if (!isset($hooks[$def['theme']]['includes'])) {
$hooks[$def['theme']]['includes'] = array();
}
if (!in_array('views.theme.inc', $hooks[$def['theme']]['includes'])) {
$hooks[$def['theme']]['includes'][] = $module_dir . '/views.theme.inc';
}
}
// The theme_file definition is always relative to the modules directory.
if (isset($def['theme_file'])) {
$hooks[$def['theme']]['path'] = $module_dir;
elseif (!empty($def['theme_file'])) {
$hooks[$def['theme']]['file'] = $def['theme_file'];
}
// Whenever we got a theme file, we include it directly so we can
// Whenever we have a theme file, we include it directly so we can
// auto-detect the theme function.
if (isset($def['theme_file'])) {
$include = DRUPAL_ROOT . '/' . $module_dir. '/' . $def['theme_file'];
$include = DRUPAL_ROOT . '/' . $module_dir . '/' . $def['theme_file'];
if (is_file($include)) {
require_once $include;
}
}
// If there is no theme function for the given theme definition, we assume
// a template file shall be used. By default this file is located in the
// /templates directory of the module's folder.
// If a module wants to define its own location it has to set
// register_theme of the plugin to FALSE and implement hook_theme() by
// itself.
// If there is no theme function for the given theme definition, it must
// be a template file. By default this file is located in the /templates
// directory of the module's folder. If a module wants to define its own
// location it has to set register_theme of the plugin to FALSE and
// implement hook_theme() by itself.
if (!function_exists('theme_' . $def['theme'])) {
$hooks[$def['theme']]['path'] = $module_dir;
$hooks[$def['theme']]['template'] = 'templates/' . drupal_clean_css_identifier($def['theme']);
$hooks[$def['theme']]['path'] .= '/templates';
$hooks[$def['theme']]['template'] = drupal_clean_css_identifier($def['theme']);
}
else {
$hooks[$def['theme']]['function'] = 'theme_' . $def['theme'];
}
}
}
......
......@@ -100,6 +100,7 @@ function views_ui_theme() {
'views_ui_build_group_filter_form' => array(
'render element' => 'form',
'file' => 'views_ui.theme.inc',
'function' => 'theme_views_ui_build_group_filter_form',
),
// On behalf of a plugin
......
......@@ -51,12 +51,17 @@ function twig_init(Extension $theme) {
function twig_render_template($template_file, $variables) {
/** @var \Twig_Environment $twig_service */
$twig_service = \Drupal::service('twig');
$output = array(
'debug_prefix' => '',
'debug_info' => '',
'rendered_markup' => $twig_service->loadTemplate($template_file)->render($variables),
'debug_suffix' => '',
);
try {
$output = array(
'debug_prefix' => '',
'debug_info' => '',
'rendered_markup' => $twig_service->loadTemplate($template_file)->render($variables),
'debug_suffix' => '',
);
}
catch (\Twig_Error_Loader $e) {
drupal_set_message($e->getMessage(), 'error');
}
if ($twig_service->isDebug()) {
$output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
$output['debug_prefix'] .= "\n<!-- THEME HOOK: '{$variables['theme_hook_original']}' -->";
......
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