diff --git a/core/core.services.yml b/core/core.services.yml index 9ec818a..2bfd898 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1,5 +1,6 @@ parameters: twig.config: {} + renderer.config: {} factory.keyvalue: default: keyvalue.database factory.keyvalue.expirable: @@ -1102,4 +1103,4 @@ services: - { name: mime_type_guesser } renderer: class: Drupal\Core\Render\Renderer - arguments: ['@controller_resolver', '@theme.manager', '@plugin.manager.element_info', '@request_stack'] + arguments: ['@controller_resolver', '@theme.manager', '@plugin.manager.element_info', '@request_stack', '%renderer.config%'] diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index db1a85c..bd34fda 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -55,6 +55,13 @@ class Renderer implements RendererInterface { protected static $stack; /** + * The renderer configuration array. + * + * @var array + */ + protected $rendererConfig; + + /** * Constructs a new Renderer. * * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver @@ -65,12 +72,15 @@ class Renderer implements RendererInterface { * The element info. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack * The request stack. + * @param array $renderer_config + * The renderer configuration array. */ - public function __construct(ControllerResolverInterface $controller_resolver, ThemeManagerInterface $theme, ElementInfoManagerInterface $element_info, RequestStack $request_stack) { + public function __construct(ControllerResolverInterface $controller_resolver, ThemeManagerInterface $theme, ElementInfoManagerInterface $element_info, RequestStack $request_stack, $renderer_config) { $this->controllerResolver = $controller_resolver; $this->theme = $theme; $this->elementInfo = $element_info; $this->requestStack = $request_stack; + $this->rendererConfig = $renderer_config; } /** @@ -154,6 +164,10 @@ protected function doRender(&$elements, $is_root_call = FALSE) { $this->processPostRenderCache($elements); } $elements['#markup'] = SafeMarkup::set($elements['#markup']); + // Add debug output to the renderable array on cache hit. + if ($this->rendererConfig['debug'] === TRUE) { + $elements = $this->addDebugOutput($elements, TRUE); + } // The render cache item contains all the bubbleable rendering metadata // for the subtree. $this->updateStack($elements); @@ -512,6 +526,10 @@ protected function cacheSet(&$markup, array $elements) { $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'render'; $expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : Cache::PERMANENT; \Drupal::cache($bin)->set($cid, $data, $expire, $data['#cache']['tags']); + // Add debug output to the renderable array on cache miss. + if ($this->rendererConfig['debug'] === TRUE) { + $this->addDebugOutput($elements, FALSE); + } } /** @@ -528,4 +546,40 @@ public function getCacheableRenderArray(&$markup, $elements) { ]; } + /** + * @param $elements + * The renderable array that must be wrapped with the cache debug output. + * @param $is_cache_hit + * A flag indicating that the cache is hit or miss. + * @return array + * The renderable array. + */ + protected function addDebugOutput($elements, $is_cache_hit) { + $prefix = "\n"; + + $suffix = ""; + + if (!empty($elements['#markup'])) { + $elements['#markup'] = "\n$prefix\n" . $elements['#markup'] . "\n$suffix\n"; + } + return $elements; + } + } diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml index a5307ec..a95c8cd 100644 --- a/sites/default/default.services.yml +++ b/sites/default/default.services.yml @@ -39,6 +39,18 @@ parameters: # Not recommended in production environments # @default true cache: true + renderer.config: + # Renderer debugging: + # + # When debugging is enabled, debug output is shown for the rendered array: + # - Cache hit or miss. + # - Contents of the #pre_render key is printed in HTML comments. + # + # For more information, see https://www.drupal.org/node/2381797 + # + # Not recommended in production environments + # @default false + debug: false factory.keyvalue: {} # Default key/value storage service to use.