121 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @file
							 | 
						||
| 
								 | 
							
								 * Handles integration of Twig templates with the Drupal theme system.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use Drupal\Component\Render\MarkupInterface;
							 | 
						||
| 
								 | 
							
								use Drupal\Component\Utility\Html;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Render\Markup;
							 | 
						||
| 
								 | 
							
								use Twig\Error\RuntimeError;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Implements hook_theme().
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function twig_theme($existing, $type, $theme, $path): array {
							 | 
						||
| 
								 | 
							
								  return drupal_find_theme_templates($existing, '.html.twig', $path);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Implements hook_extension().
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function twig_extension(): string {
							 | 
						||
| 
								 | 
							
								  return '.html.twig';
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Implements hook_render_template().
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function twig_render_template($template_file, array $variables): string|MarkupInterface {
							 | 
						||
| 
								 | 
							
								  /** @var \Twig\Environment $twig_service */
							 | 
						||
| 
								 | 
							
								  $twig_service = \Drupal::service('twig');
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    $rendered_markup = $twig_service->load($template_file)->render($variables);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  catch (RuntimeError $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' => '',
							 | 
						||
| 
								 | 
							
								      'debug_info' => '',
							 | 
						||
| 
								 | 
							
								      'rendered_markup' => $rendered_markup,
							 | 
						||
| 
								 | 
							
								      'debug_suffix' => '',
							 | 
						||
| 
								 | 
							
								    ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
							 | 
						||
| 
								 | 
							
								    $output['debug_prefix'] .= "\n<!-- THEME HOOK: '" . Html::escape($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 (str_contains($variables['theme_hook_original'], '__')) {
							 | 
						||
| 
								 | 
							
								      $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 (!str_contains($variables['theme_hook_original'], '__')) {
							 | 
						||
| 
								 | 
							
								        $suggestions[] = $variables['theme_hook_original'];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      $invalid_suggestions = [];
							 | 
						||
| 
								 | 
							
								      $base_hook = $base_hook ?? $variables['theme_hook_original'];
							 | 
						||
| 
								 | 
							
								      foreach ($suggestions as $key => &$suggestion) {
							 | 
						||
| 
								 | 
							
								        // Valid suggestions are $base_hook, $base_hook__*, and contain no
							 | 
						||
| 
								 | 
							
								        // hyphens.
							 | 
						||
| 
								 | 
							
								        if (($suggestion !== $base_hook && !str_starts_with($suggestion, $base_hook . '__')) || str_contains($suggestion, '-')) {
							 | 
						||
| 
								 | 
							
								          $invalid_suggestions[] = $suggestion;
							 | 
						||
| 
								 | 
							
								          unset($suggestions[$key]);
							 | 
						||
| 
								 | 
							
								          continue;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $template = strtr($suggestion, '_', '-') . $extension;
							 | 
						||
| 
								 | 
							
								        $prefix = ($template == $current_template) ? '✅' : '▪️';
							 | 
						||
| 
								 | 
							
								        $suggestion = $prefix . ' ' . $template;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      $output['debug_info'] .= "\n<!-- FILE NAME SUGGESTIONS:\n   " . Html::escape(implode("\n   ", $suggestions)) . "\n-->";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!empty($invalid_suggestions)) {
							 | 
						||
| 
								 | 
							
								        $output['debug_info'] .= "\n<!-- INVALID FILE NAME SUGGESTIONS:";
							 | 
						||
| 
								 | 
							
								        $output['debug_info'] .= "\n   See https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook_theme_suggestions_alter";
							 | 
						||
| 
								 | 
							
								        $output['debug_info'] .= "\n   " . Html::escape(implode("\n   ", $invalid_suggestions));
							 | 
						||
| 
								 | 
							
								        $output['debug_info'] .= "\n-->";
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // Check if the template_file belongs to a custom theme
							 | 
						||
| 
								 | 
							
								    $template_override_status_output = "BEGIN OUTPUT";
							 | 
						||
| 
								 | 
							
								    $template_override_suffix_output = "END OUTPUT";
							 | 
						||
| 
								 | 
							
								    if (str_starts_with($template_file, $variables['directory'])) {
							 | 
						||
| 
								 | 
							
								      $template_override_status_output = "💡 BEGIN CUSTOM TEMPLATE OUTPUT";
							 | 
						||
| 
								 | 
							
								      $template_override_suffix_output = "END CUSTOM TEMPLATE OUTPUT";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    $output['debug_info']   .= "\n<!-- " . $template_override_status_output . " from '" . Html::escape($template_file) . "' -->\n";
							 | 
						||
| 
								 | 
							
								    $output['debug_suffix'] .= "\n<!-- " . $template_override_suffix_output . " from '" . Html::escape($template_file) . "' -->\n\n";
							 | 
						||
| 
								 | 
							
								    // This output has already been rendered and is therefore considered safe.
							 | 
						||
| 
								 | 
							
								    return Markup::create(implode('', $output));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return Markup::create($rendered_markup);
							 | 
						||
| 
								 | 
							
								}
							 |