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