2012-11-03 17:36:10 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* Handles integration of Twig templates with the Drupal theme system.
|
|
|
|
*/
|
|
|
|
|
2014-03-11 17:19:24 +00:00
|
|
|
use Drupal\Core\Extension\Extension;
|
2014-03-24 08:51:28 +00:00
|
|
|
use Drupal\Component\Utility\Settings;
|
2014-03-11 17:19:24 +00:00
|
|
|
|
2012-11-03 17:36:10 +00:00
|
|
|
/**
|
|
|
|
* Implements hook_theme().
|
|
|
|
*/
|
|
|
|
function twig_theme($existing, $type, $theme, $path) {
|
2013-05-29 07:41:16 +00:00
|
|
|
$templates = drupal_find_theme_functions($existing, array($theme));
|
|
|
|
$templates += drupal_find_theme_templates($existing, '.html.twig', $path);
|
|
|
|
return $templates;
|
2012-11-03 17:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements hook_extension().
|
|
|
|
*/
|
|
|
|
function twig_extension() {
|
2013-01-30 03:11:25 +00:00
|
|
|
return '.html.twig';
|
2012-11-03 17:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements hook_init().
|
|
|
|
*/
|
2014-03-11 17:19:24 +00:00
|
|
|
function twig_init(Extension $theme) {
|
Issue #340723 by ParisLiakos, sun, Berdir, glennpratt, Cottser, swentel, alexpott, tstoeckler, Xano, tim.plunkett, BassistJimmyJam | beejeebus: Make modules and installation profiles only require .info.yml files.
2014-03-17 14:43:29 +00:00
|
|
|
$theme->load();
|
2012-11-03 17:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-02-19 08:59:05 +00:00
|
|
|
* Renders a Twig template.
|
2012-11-03 17:36:10 +00:00
|
|
|
*
|
2014-02-18 10:54:10 +00:00
|
|
|
* If the Twig debug setting is enabled, HTML comments including _theme() call
|
2013-02-19 08:59:05 +00:00
|
|
|
* and template file name suggestions will surround the template markup.
|
2012-11-03 17:36:10 +00:00
|
|
|
*
|
|
|
|
* @param $template_file
|
2013-02-19 08:59:05 +00:00
|
|
|
* The file name of the template to render.
|
2012-11-03 17:36:10 +00:00
|
|
|
* @param $variables
|
|
|
|
* A keyed array of variables that will appear in the output.
|
|
|
|
*
|
|
|
|
* @return
|
2013-02-19 08:59:05 +00:00
|
|
|
* The output generated by the template, plus any debug information.
|
2012-11-03 17:36:10 +00:00
|
|
|
*/
|
|
|
|
function twig_render_template($template_file, $variables) {
|
2013-02-19 08:59:05 +00:00
|
|
|
$output = array(
|
|
|
|
'debug_prefix' => '',
|
|
|
|
'debug_info' => '',
|
2013-12-22 21:03:21 +00:00
|
|
|
'rendered_markup' => \Drupal::service('twig')->loadTemplate($template_file)->render($variables),
|
2013-02-19 08:59:05 +00:00
|
|
|
'debug_suffix' => '',
|
|
|
|
);
|
2014-03-24 08:51:28 +00:00
|
|
|
if (Settings::get('twig_debug', FALSE)) {
|
2013-02-19 08:59:05 +00:00
|
|
|
$output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
|
2014-02-18 10:54:10 +00:00
|
|
|
$output['debug_prefix'] .= "\n<!-- CALL: _theme('{$variables['theme_hook_original']}') -->";
|
2014-03-04 21:04:23 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2013-02-19 08:59:05 +00:00
|
|
|
if (!empty($variables['theme_hook_suggestions'])) {
|
|
|
|
$extension = twig_extension();
|
|
|
|
$current_template = basename($template_file);
|
|
|
|
$suggestions = $variables['theme_hook_suggestions'];
|
2014-03-04 21:04:23 +00:00
|
|
|
// 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'];
|
|
|
|
}
|
2013-08-13 21:20:54 +00:00
|
|
|
foreach ($suggestions as &$suggestion) {
|
2013-02-19 08:59:05 +00:00
|
|
|
$template = strtr($suggestion, '_', '-') . $extension;
|
|
|
|
$prefix = ($template == $current_template) ? 'x' : '*';
|
|
|
|
$suggestion = $prefix . ' ' . $template;
|
|
|
|
}
|
|
|
|
$output['debug_info'] .= "\n<!-- FILE NAME SUGGESTIONS:\n " . implode("\n ", $suggestions) . "\n-->";
|
|
|
|
}
|
|
|
|
$output['debug_info'] .= "\n<!-- BEGIN OUTPUT from '{$template_file}' -->\n";
|
|
|
|
$output['debug_suffix'] .= "\n<!-- END OUTPUT from '{$template_file}' -->\n\n";
|
|
|
|
}
|
|
|
|
return implode('', $output);
|
2012-11-03 17:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper around render() for twig printed output.
|
|
|
|
*
|
|
|
|
* If an object is passed that has no __toString method an exception is thrown;
|
|
|
|
* other objects are casted to string. However in the case that the object is an
|
|
|
|
* instance of a Twig_Markup object it is returned directly to support auto
|
|
|
|
* escaping.
|
|
|
|
*
|
|
|
|
* If an array is passed it is rendered via render() and scalar values are
|
|
|
|
* returned directly.
|
|
|
|
*
|
|
|
|
* @param mixed $arg
|
|
|
|
* String, Object or Render Array
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* The rendered output or an Twig_Markup object.
|
|
|
|
*
|
|
|
|
* @see render
|
|
|
|
* @see TwigNodeVisitor
|
|
|
|
*/
|
2012-12-29 08:54:13 +00:00
|
|
|
function twig_render_var($arg) {
|
2013-04-29 11:24:59 +00:00
|
|
|
// Check for numeric zero.
|
|
|
|
if ($arg === 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-24 14:59:38 +00:00
|
|
|
// Return early for NULL and also true for empty arrays.
|
2012-11-03 17:36:10 +00:00
|
|
|
if ($arg == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-03-24 14:59:38 +00:00
|
|
|
// Keep Twig_Markup objects intact to prepare for later autoescaping support.
|
2012-11-03 17:36:10 +00:00
|
|
|
if ($arg instanceOf Twig_Markup) {
|
|
|
|
return $arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_scalar($arg)) {
|
|
|
|
return $arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_object($arg)) {
|
|
|
|
if (method_exists($arg, '__toString')) {
|
|
|
|
return (string) $arg;
|
|
|
|
}
|
|
|
|
throw new Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg))));
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a normal render array.
|
|
|
|
return render($arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-03-07 18:29:14 +00:00
|
|
|
* Removes child elements from a copy of the original array.
|
2012-11-03 17:36:10 +00:00
|
|
|
*
|
2014-03-07 18:29:14 +00:00
|
|
|
* Creates a copy of the renderable array and removes child elements by key
|
|
|
|
* specified throught 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.
|
2012-11-03 17:36:10 +00:00
|
|
|
*
|
2014-03-07 18:29:14 +00:00
|
|
|
* @param array $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.
|
2012-11-03 17:36:10 +00:00
|
|
|
*/
|
2014-03-07 18:29:14 +00:00
|
|
|
function twig_without($element) {
|
|
|
|
$filtered_element = $element;
|
|
|
|
$args = func_get_args();
|
|
|
|
unset($args[0]);
|
|
|
|
foreach ($args as $arg) {
|
|
|
|
if (isset($filtered_element[$arg])) {
|
|
|
|
unset($filtered_element[$arg]);
|
|
|
|
}
|
2012-11-03 17:36:10 +00:00
|
|
|
}
|
2014-03-07 18:29:14 +00:00
|
|
|
return $filtered_element;
|
2012-11-03 17:36:10 +00:00
|
|
|
}
|