From cc5cbf5999314e3dadebb8c4d02fd5bb3125cb48 Mon Sep 17 00:00:00 2001 From: Wim Leers Date: Thu, 15 Oct 2015 13:32:27 +0200 Subject: [PATCH] Improve/fix handling of bubbleable metadata in entity_embed. --- src/EntityHelperTrait.php | 12 +++++------- src/Plugin/Filter/EntityEmbedFilter.php | 21 +++++++++++++++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/EntityHelperTrait.php b/src/EntityHelperTrait.php index 13ac8802..c560411b 100644 --- a/src/EntityHelperTrait.php +++ b/src/EntityHelperTrait.php @@ -158,8 +158,8 @@ protected function renderEntity(EntityInterface $entity, $view_mode, $langcode = * (optional) Array of context values, corresponding to the attributes on * the embed HTML tag. * - * @return string - * The HTML of the entity rendered with the display plugin. + * @return array + * A render array from entity_view(). */ protected function renderEntityEmbed(EntityInterface $entity, array $context = array()) { // Support the deprecated view-mode data attribute. @@ -185,8 +185,8 @@ protected function renderEntityEmbed(EntityInterface $entity, array $context = a // Allow modules to alter the entity prior to embed rendering. $this->moduleHandler()->alter(array("{$context['data-entity-type']}_embed_context", 'entity_embed_context'), $context, $entity); - // Build and render the display plugin, allowing modules to alter the - // result before rendering. + // Build the display plugin, allowing modules to alter the result before + // rendering. $build = $this->renderEntityEmbedDisplayPlugin( $entity, $context['data-entity-embed-display'], @@ -195,9 +195,7 @@ protected function renderEntityEmbed(EntityInterface $entity, array $context = a ); // @todo Should this hook get invoked if $build is an empty array? $this->moduleHandler()->alter(array("{$context['data-entity-type']}_embed", 'entity_embed'), $build, $entity, $context); - $entity_output = $this->renderer()->render($build); - - return $entity_output; + return $build; } /** diff --git a/src/Plugin/Filter/EntityEmbedFilter.php b/src/Plugin/Filter/EntityEmbedFilter.php index 112614a7..9ea7cf42 100644 --- a/src/Plugin/Filter/EntityEmbedFilter.php +++ b/src/Plugin/Filter/EntityEmbedFilter.php @@ -12,6 +12,8 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Render\BubbleableMetadata; +use Drupal\Core\Render\RenderContext; use Drupal\entity_embed\EntityHelperTrait; use Drupal\entity_embed\Exception\EntityNotFoundException; use Drupal\entity_embed\Exception\RecursiveRenderingException; @@ -102,13 +104,24 @@ public function process($text, $langcode) { } $access = $entity->access('view', NULL, TRUE); - $access_metadata = CacheableMetadata::createFromObject($access); - $entity_metadata = CacheableMetadata::createFromObject($entity); - $result = $result->merge($entity_metadata)->merge($access_metadata); + $result->addCacheableDependency($access); $context = $this->getNodeAttributesAsArray($node); $context += array('data-langcode' => $langcode); - $entity_output = $this->renderEntityEmbed($entity, $context); + $build = $this->renderEntityEmbed($entity, $context); + // We need to render the embedded entity: + // - without replacing placeholders, so that the placeholders are + // only replaced at the last possible moment. Hence we cannot use + // either renderPlain() or renderRoot(), so we must use render(). + // - without bubbling beyond this filter, because filters must + // ensure that the bubbleable metadata for the changes they make + // when filtering text makes it onto the FilterProcessResult + // object that they return ($result). To prevent that bubbling, we + // must wrap the call to render() in a render context. + $entity_output = $this->renderer()->executeInRenderContext(new RenderContext(), function () use (&$build) { + return $this->renderer()->render($build); + }); + $result = $result->merge(BubbleableMetadata::createFromRenderArray($build)); $depth--; }