This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
drupalcampbristol/core/themes/engines/twig/twig.engine

177 lines
5.8 KiB
Plaintext

<?php
/**
* @file
* Handles integration of Twig templates with the Drupal theme system.
*/
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Extension\Extension;
/**
* Implements hook_theme().
*/
function twig_theme($existing, $type, $theme, $path) {
$templates = drupal_find_theme_functions($existing, array($theme));
$templates += drupal_find_theme_templates($existing, '.html.twig', $path);
return $templates;
}
/**
* Implements hook_extension().
*/
function twig_extension() {
return '.html.twig';
}
/**
* Implements hook_init().
*/
function twig_init(Extension $theme) {
$theme->load();
}
/**
* Implements hook_render_template().
*
* Renders a Twig template.
*
* If the Twig debug setting is enabled, HTML comments including _theme() call
* and template file name suggestions will surround the template markup.
*
* @param string $template_file
* The file name of the template to render.
* @param array $variables
* A keyed array of variables that will appear in the output.
*
* @return string
* The output generated by the template, plus any debug information.
*/
function twig_render_template($template_file, array $variables) {
/** @var \Twig_Environment $twig_service */
$twig_service = \Drupal::service('twig');
$output = [
'debug_prefix' => '',
'debug_info' => '',
'rendered_markup' => '',
'debug_suffix' => '',
];
try {
$output['rendered_markup'] = $twig_service->loadTemplate($template_file)->render($variables);
}
catch (\Twig_Error_Loader $e) {
drupal_set_message($e->getMessage(), 'error');
}
catch (\Twig_Error_Runtime $e) {
// In case there is a previous exception, re-throw the previous exception,
// so that the original exception is shown, rather than
// \Twig_Template::displayWithErrorHandling()'s exception.
$previous_exception = $e->getPrevious();
if ($previous_exception) {
throw $previous_exception;
}
throw $e;
}
if ($twig_service->isDebug()) {
$output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
$output['debug_prefix'] .= "\n<!-- THEME HOOK: '" . SafeMarkup::checkPlain($variables['theme_hook_original']) . "' -->";
// If there are theme suggestions, reverse the array so more specific
// suggestions are shown first.
if (!empty($variables['theme_hook_suggestions'])) {
$variables['theme_hook_suggestions'] = array_reverse($variables['theme_hook_suggestions']);
}
// Add debug output for directly called suggestions like
// '#theme' => 'comment__node__article'.
if (strpos($variables['theme_hook_original'], '__') !== FALSE) {
$derived_suggestions[] = $hook = $variables['theme_hook_original'];
while ($pos = strrpos($hook, '__')) {
$hook = substr($hook, 0, $pos);
$derived_suggestions[] = $hook;
}
// Get the value of the base hook (last derived suggestion) and append it
// to the end of all theme suggestions.
$base_hook = array_pop($derived_suggestions);
$variables['theme_hook_suggestions'] = array_merge($derived_suggestions, $variables['theme_hook_suggestions']);
$variables['theme_hook_suggestions'][] = $base_hook;
}
if (!empty($variables['theme_hook_suggestions'])) {
$extension = twig_extension();
$current_template = basename($template_file);
$suggestions = $variables['theme_hook_suggestions'];
// Only add the original theme hook if it wasn't a directly called
// suggestion.
if (strpos($variables['theme_hook_original'], '__') === FALSE) {
$suggestions[] = $variables['theme_hook_original'];
}
foreach ($suggestions as &$suggestion) {
$template = strtr($suggestion, '_', '-') . $extension;
$prefix = ($template == $current_template) ? 'x' : '*';
$suggestion = $prefix . ' ' . $template;
}
$output['debug_info'] .= "\n<!-- FILE NAME SUGGESTIONS:\n " . SafeMarkup::checkPlain(implode("\n ", $suggestions)) . "\n-->";
}
$output['debug_info'] .= "\n<!-- BEGIN OUTPUT from '" . SafeMarkup::checkPlain($template_file) . "' -->\n";
$output['debug_suffix'] .= "\n<!-- END OUTPUT from '" . SafeMarkup::checkPlain($template_file) . "' -->\n\n";
}
return SafeMarkup::set(implode('', $output));
}
/**
* Removes child elements from a copy of the original array.
*
* Creates a copy of the renderable array and removes child elements by key
* specified through filter's arguments. The copy can be printed without these
* elements. The original renderable array is still available and can be used
* to print child elements in their entirety in the twig template.
*
* @param array|object $element
* The parent renderable array to exclude the child items.
* @param string[] $args, ...
* The string keys of $element to prevent printing.
*
* @return array
* The filtered renderable array.
*/
function twig_without($element) {
if ($element instanceof ArrayAccess) {
$filtered_element = clone $element;
}
else {
$filtered_element = $element;
}
$args = func_get_args();
unset($args[0]);
foreach ($args as $arg) {
if (isset($filtered_element[$arg])) {
unset($filtered_element[$arg]);
}
}
return $filtered_element;
}
/**
* Overrides twig_join_filter().
*
* Safely joins several strings together.
*
* @param array|Traversable $value
* The pieces to join.
* @param string $glue
* The delimiter with which to join the string. Defaults to an empty string.
* This value is expected to be safe for output and user provided data should
* never be used as a glue.
*
* @return \Drupal\Component\Utility\SafeMarkup|string
* The imploded string, which is now also marked as safe.
*/
function twig_drupal_join_filter($value, $glue = '') {
$separator = '';
$output = '';
foreach ($value as $item) {
$output .= $separator . SafeMarkup::escape($item);
$separator = $glue;
}
return SafeMarkup::set($output);
}