entityTypeManager = $entity_type_manager; $this->renderer = $renderer; $this->builder = $builder; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('entity_type.manager'), $container->get('renderer'), $container->get('entity_embed.builder') ); } /** * {@inheritdoc} */ public function process($text, $langcode) { $result = new FilterProcessResult($text); if (strpos($text, 'data-entity-type') !== FALSE && (strpos($text, 'data-entity-embed-display') !== FALSE || strpos($text, 'data-view-mode') !== FALSE)) { $dom = Html::load($text); $xpath = new \DOMXPath($dom); foreach ($xpath->query('//drupal-entity[@data-entity-type and (@data-entity-uuid or @data-entity-id) and (@data-entity-embed-display or @data-view-mode)]') as $node) { /** @var \DOMElement $node */ $entity_type = $node->getAttribute('data-entity-type'); $entity = NULL; $entity_output = ''; // data-entity-embed-settings is deprecated, make sure we convert it to // data-entity-embed-display-settings. if (($settings = $node->getAttribute('data-entity-embed-settings')) && !$node->hasAttribute('data-entity-embed-display-settings')) { $node->setAttribute('data-entity-embed-display-settings', $settings); $node->removeAttribute('data-entity-embed-settings'); } try { // Load the entity either by UUID (preferred) or ID. $id = NULL; $entity = NULL; if ($id = $node->getAttribute('data-entity-uuid')) { $entity = $this->entityTypeManager->getStorage($entity_type) ->loadByProperties(['uuid' => $id]); $entity = current($entity); } else { $id = $node->getAttribute('data-entity-id'); $entity = $this->entityTypeManager->getStorage($entity_type)->load($id); } if ($entity) { // Protect ourselves from recursive rendering. static $depth = 0; $depth++; if ($depth > 20) { throw new RecursiveRenderingException(sprintf('Recursive rendering detected when rendering embedded %s entity %s.', $entity_type, $entity->id())); } // If a UUID was not used, but is available, add it to the HTML. if (!$node->getAttribute('data-entity-uuid') && $uuid = $entity->uuid()) { $node->setAttribute('data-entity-uuid', $uuid); } $context = $this->getNodeAttributesAsArray($node); $context += array('data-langcode' => $langcode); $build = $this->builder->buildEntityEmbed($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--; } else { throw new EntityNotFoundException(sprintf('Unable to load embedded %s entity %s.', $entity_type, $id)); } } catch (\Exception $e) { watchdog_exception('entity_embed', $e); } $this->replaceNodeContent($node, $entity_output); } $result->setProcessedText(Html::serialize($dom)); } return $result; } /** * {@inheritdoc} */ public function tips($long = FALSE) { if ($long) { return $this->t('

You can embed entities. Additional properties can be added to the embed tag like data-caption and data-align if supported. Example:

<drupal-entity data-entity-type="node" data-entity-uuid="07bf3a2e-1941-4a44-9b02-2d1d7a41ec0e" data-view-mode="teaser" />'); } else { return $this->t('You can embed entities.'); } } }