Chris@0: load(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Implements hook_render_template(). Chris@0: * Chris@0: * Renders a Twig template. Chris@0: * Chris@0: * If the Twig debug setting is enabled, HTML comments including the theme hook Chris@0: * and template file name suggestions will surround the template markup. Chris@0: * Chris@0: * @param string $template_file Chris@0: * The file name of the template to render. Chris@0: * @param array $variables Chris@0: * A keyed array of variables that will appear in the output. Chris@0: * Chris@0: * @return string|\Drupal\Component\Render\MarkupInterface Chris@0: * The output generated by the template, plus any debug information. Chris@0: */ Chris@0: function twig_render_template($template_file, array $variables) { Chris@0: /** @var \Twig_Environment $twig_service */ Chris@0: $twig_service = \Drupal::service('twig'); Chris@0: $output = [ Chris@0: 'debug_prefix' => '', Chris@0: 'debug_info' => '', Chris@0: 'rendered_markup' => '', Chris@0: 'debug_suffix' => '', Chris@0: ]; Chris@0: try { Chris@0: $output['rendered_markup'] = $twig_service->loadTemplate($template_file)->render($variables); Chris@0: } Chris@0: catch (\Twig_Error_Runtime $e) { Chris@0: // In case there is a previous exception, re-throw the previous exception, Chris@0: // so that the original exception is shown, rather than Chris@0: // \Twig_Template::displayWithErrorHandling()'s exception. Chris@0: $previous_exception = $e->getPrevious(); Chris@0: if ($previous_exception) { Chris@0: throw $previous_exception; Chris@0: } Chris@0: throw $e; Chris@0: } Chris@0: if ($twig_service->isDebug()) { Chris@0: $output['debug_prefix'] .= "\n\n"; Chris@0: $output['debug_prefix'] .= "\n"; Chris@0: // If there are theme suggestions, reverse the array so more specific Chris@0: // suggestions are shown first. Chris@0: if (!empty($variables['theme_hook_suggestions'])) { Chris@0: $variables['theme_hook_suggestions'] = array_reverse($variables['theme_hook_suggestions']); Chris@0: } Chris@0: // Add debug output for directly called suggestions like Chris@0: // '#theme' => 'comment__node__article'. Chris@0: if (strpos($variables['theme_hook_original'], '__') !== FALSE) { Chris@0: $derived_suggestions[] = $hook = $variables['theme_hook_original']; Chris@0: while ($pos = strrpos($hook, '__')) { Chris@0: $hook = substr($hook, 0, $pos); Chris@0: $derived_suggestions[] = $hook; Chris@0: } Chris@0: // Get the value of the base hook (last derived suggestion) and append it Chris@0: // to the end of all theme suggestions. Chris@0: $base_hook = array_pop($derived_suggestions); Chris@0: $variables['theme_hook_suggestions'] = array_merge($derived_suggestions, $variables['theme_hook_suggestions']); Chris@0: $variables['theme_hook_suggestions'][] = $base_hook; Chris@0: } Chris@0: if (!empty($variables['theme_hook_suggestions'])) { Chris@0: $extension = twig_extension(); Chris@0: $current_template = basename($template_file); Chris@0: $suggestions = $variables['theme_hook_suggestions']; Chris@0: // Only add the original theme hook if it wasn't a directly called Chris@0: // suggestion. Chris@0: if (strpos($variables['theme_hook_original'], '__') === FALSE) { Chris@0: $suggestions[] = $variables['theme_hook_original']; Chris@0: } Chris@0: foreach ($suggestions as &$suggestion) { Chris@0: $template = strtr($suggestion, '_', '-') . $extension; Chris@0: $prefix = ($template == $current_template) ? 'x' : '*'; Chris@0: $suggestion = $prefix . ' ' . $template; Chris@0: } Chris@0: $output['debug_info'] .= "\n"; Chris@0: } Chris@0: $output['debug_info'] .= "\n\n"; Chris@0: $output['debug_suffix'] .= "\n\n\n"; Chris@0: } Chris@0: // This output has already been rendered and is therefore considered safe. Chris@0: return Markup::create(implode('', $output)); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Removes child elements from a copy of the original array. Chris@0: * Chris@0: * Creates a copy of the renderable array and removes child elements by key Chris@0: * specified through filter's arguments. The copy can be printed without these Chris@0: * elements. The original renderable array is still available and can be used Chris@0: * to print child elements in their entirety in the twig template. Chris@0: * Chris@0: * @param array|object $element Chris@0: * The parent renderable array to exclude the child items. Chris@0: * @param string[] ... Chris@0: * The string keys of $element to prevent printing. Chris@0: * Chris@0: * @return array Chris@0: * The filtered renderable array. Chris@0: */ Chris@0: function twig_without($element) { Chris@0: if ($element instanceof ArrayAccess) { Chris@0: $filtered_element = clone $element; Chris@0: } Chris@0: else { Chris@0: $filtered_element = $element; Chris@0: } Chris@0: $args = func_get_args(); Chris@0: unset($args[0]); Chris@0: foreach ($args as $arg) { Chris@0: if (isset($filtered_element[$arg])) { Chris@0: unset($filtered_element[$arg]); Chris@0: } Chris@0: } Chris@0: return $filtered_element; Chris@0: }