annotate core/themes/engines/twig/twig.engine @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents c75dbcec494b
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /**
Chris@0 4 * @file
Chris@0 5 * Handles integration of Twig templates with the Drupal theme system.
Chris@0 6 */
Chris@0 7
Chris@0 8 use Drupal\Component\Utility\Html;
Chris@0 9 use Drupal\Core\Render\Markup;
Chris@0 10 use Drupal\Core\Extension\Extension;
Chris@0 11
Chris@0 12 /**
Chris@0 13 * Implements hook_theme().
Chris@0 14 */
Chris@0 15 function twig_theme($existing, $type, $theme, $path) {
Chris@0 16 $templates = drupal_find_theme_functions($existing, [$theme]);
Chris@0 17 $templates += drupal_find_theme_templates($existing, '.html.twig', $path);
Chris@0 18 return $templates;
Chris@0 19 }
Chris@0 20
Chris@0 21 /**
Chris@0 22 * Implements hook_extension().
Chris@0 23 */
Chris@0 24 function twig_extension() {
Chris@0 25 return '.html.twig';
Chris@0 26 }
Chris@0 27
Chris@0 28 /**
Chris@0 29 * Includes .theme file from themes.
Chris@0 30 *
Chris@0 31 * @param \Drupal\Core\Extension\Extension $theme
Chris@0 32 * The theme extension object.
Chris@0 33 */
Chris@0 34 function twig_init(Extension $theme) {
Chris@0 35 $theme->load();
Chris@0 36 }
Chris@0 37
Chris@0 38 /**
Chris@0 39 * Implements hook_render_template().
Chris@0 40 *
Chris@0 41 * Renders a Twig template.
Chris@0 42 *
Chris@0 43 * If the Twig debug setting is enabled, HTML comments including the theme hook
Chris@0 44 * and template file name suggestions will surround the template markup.
Chris@0 45 *
Chris@0 46 * @param string $template_file
Chris@0 47 * The file name of the template to render.
Chris@0 48 * @param array $variables
Chris@0 49 * A keyed array of variables that will appear in the output.
Chris@0 50 *
Chris@0 51 * @return string|\Drupal\Component\Render\MarkupInterface
Chris@0 52 * The output generated by the template, plus any debug information.
Chris@0 53 */
Chris@0 54 function twig_render_template($template_file, array $variables) {
Chris@0 55 /** @var \Twig_Environment $twig_service */
Chris@0 56 $twig_service = \Drupal::service('twig');
Chris@0 57 $output = [
Chris@0 58 'debug_prefix' => '',
Chris@0 59 'debug_info' => '',
Chris@0 60 'rendered_markup' => '',
Chris@0 61 'debug_suffix' => '',
Chris@0 62 ];
Chris@0 63 try {
Chris@0 64 $output['rendered_markup'] = $twig_service->loadTemplate($template_file)->render($variables);
Chris@0 65 }
Chris@0 66 catch (\Twig_Error_Runtime $e) {
Chris@0 67 // In case there is a previous exception, re-throw the previous exception,
Chris@0 68 // so that the original exception is shown, rather than
Chris@0 69 // \Twig_Template::displayWithErrorHandling()'s exception.
Chris@0 70 $previous_exception = $e->getPrevious();
Chris@0 71 if ($previous_exception) {
Chris@0 72 throw $previous_exception;
Chris@0 73 }
Chris@0 74 throw $e;
Chris@0 75 }
Chris@0 76 if ($twig_service->isDebug()) {
Chris@0 77 $output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
Chris@0 78 $output['debug_prefix'] .= "\n<!-- THEME HOOK: '" . Html::escape($variables['theme_hook_original']) . "' -->";
Chris@0 79 // If there are theme suggestions, reverse the array so more specific
Chris@0 80 // suggestions are shown first.
Chris@0 81 if (!empty($variables['theme_hook_suggestions'])) {
Chris@0 82 $variables['theme_hook_suggestions'] = array_reverse($variables['theme_hook_suggestions']);
Chris@0 83 }
Chris@0 84 // Add debug output for directly called suggestions like
Chris@0 85 // '#theme' => 'comment__node__article'.
Chris@0 86 if (strpos($variables['theme_hook_original'], '__') !== FALSE) {
Chris@0 87 $derived_suggestions[] = $hook = $variables['theme_hook_original'];
Chris@0 88 while ($pos = strrpos($hook, '__')) {
Chris@0 89 $hook = substr($hook, 0, $pos);
Chris@0 90 $derived_suggestions[] = $hook;
Chris@0 91 }
Chris@0 92 // Get the value of the base hook (last derived suggestion) and append it
Chris@0 93 // to the end of all theme suggestions.
Chris@0 94 $base_hook = array_pop($derived_suggestions);
Chris@0 95 $variables['theme_hook_suggestions'] = array_merge($derived_suggestions, $variables['theme_hook_suggestions']);
Chris@0 96 $variables['theme_hook_suggestions'][] = $base_hook;
Chris@0 97 }
Chris@0 98 if (!empty($variables['theme_hook_suggestions'])) {
Chris@0 99 $extension = twig_extension();
Chris@0 100 $current_template = basename($template_file);
Chris@0 101 $suggestions = $variables['theme_hook_suggestions'];
Chris@0 102 // Only add the original theme hook if it wasn't a directly called
Chris@0 103 // suggestion.
Chris@0 104 if (strpos($variables['theme_hook_original'], '__') === FALSE) {
Chris@0 105 $suggestions[] = $variables['theme_hook_original'];
Chris@0 106 }
Chris@0 107 foreach ($suggestions as &$suggestion) {
Chris@0 108 $template = strtr($suggestion, '_', '-') . $extension;
Chris@0 109 $prefix = ($template == $current_template) ? 'x' : '*';
Chris@0 110 $suggestion = $prefix . ' ' . $template;
Chris@0 111 }
Chris@0 112 $output['debug_info'] .= "\n<!-- FILE NAME SUGGESTIONS:\n " . Html::escape(implode("\n ", $suggestions)) . "\n-->";
Chris@0 113 }
Chris@0 114 $output['debug_info'] .= "\n<!-- BEGIN OUTPUT from '" . Html::escape($template_file) . "' -->\n";
Chris@0 115 $output['debug_suffix'] .= "\n<!-- END OUTPUT from '" . Html::escape($template_file) . "' -->\n\n";
Chris@0 116 }
Chris@0 117 // This output has already been rendered and is therefore considered safe.
Chris@0 118 return Markup::create(implode('', $output));
Chris@0 119 }
Chris@0 120
Chris@0 121 /**
Chris@0 122 * Removes child elements from a copy of the original array.
Chris@0 123 *
Chris@0 124 * Creates a copy of the renderable array and removes child elements by key
Chris@0 125 * specified through filter's arguments. The copy can be printed without these
Chris@0 126 * elements. The original renderable array is still available and can be used
Chris@0 127 * to print child elements in their entirety in the twig template.
Chris@0 128 *
Chris@0 129 * @param array|object $element
Chris@0 130 * The parent renderable array to exclude the child items.
Chris@0 131 * @param string[] ...
Chris@0 132 * The string keys of $element to prevent printing.
Chris@0 133 *
Chris@0 134 * @return array
Chris@0 135 * The filtered renderable array.
Chris@5 136 *
Chris@5 137 * @deprecated in Drupal 8.7.x and will be removed before 9.0.0. Use
Chris@5 138 * \Drupal\Core\Template\TwigExtension::withoutFilter() instead.
Chris@0 139 */
Chris@0 140 function twig_without($element) {
Chris@5 141 @trigger_error('twig_without() is deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Template\TwigExtension::withoutFilter(). See https://www.drupal.org/node/3011154.', E_USER_DEPRECATED);
Chris@5 142 /** @var \Drupal\Core\Template\TwigExtension $extension */
Chris@5 143 $extension = \Drupal::service('twig.extension');
Chris@5 144
Chris@5 145 return call_user_func_array([$extension, 'withoutFilter'], func_get_args());
Chris@0 146 }