View source
<?php
namespace Drupal\views_entity_embed\Plugin\Filter;
use Drupal\Component\Utility\Html;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\entity_embed\Exception\EntityNotFoundException;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\embed\DomHelperTrait;
use Drupal\views\Views;
use Drupal\Component\Serialization\Json;
class ViewsEmbedFilter extends FilterBase implements ContainerFactoryPluginInterface {
use DomHelperTrait;
protected $renderer;
public function __construct(array $configuration, $plugin_id, $plugin_definition, RendererInterface $renderer) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->renderer = $renderer;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('renderer'));
}
public function process($text, $langcode) {
$result = new FilterProcessResult($text);
if (strpos($text, 'data-view-name') !== FALSE && strpos($text, 'data-view-display') !== FALSE) {
$dom = Html::load($text);
$xpath = new \DOMXPath($dom);
foreach ($xpath
->query('//drupal-views[@data-view-name and @data-view-display]') as $node) {
$render_view = '';
try {
$build = $this
->buildViewsEmbed($node);
$render_view = $this->renderer
->executeInRenderContext(new RenderContext(), function () use (&$build) {
return $this->renderer
->render($build);
});
$result = $result
->merge(BubbleableMetadata::createFromRenderArray($build));
} catch (\Exception $e) {
throw new EntityNotFoundException(sprintf('Unable to load embedded %s view with %s display.', $view_name, $view_display));
}
$this
->replaceNodeContent($node, $render_view);
}
$result
->setProcessedText(Html::serialize($dom));
}
return $result;
}
public function tips($long = FALSE) {
if ($long) {
return $this
->t('
<p>You can embed Views. Additional properties can be added to the embed tag like data-caption and data-align if supported. Example:</p>
<code><drupal-views data-view-display="default" data-view-name="content"></drupal-views></code>');
}
else {
return $this
->t('You can embed Views entities.');
}
}
protected function buildViewsEmbed($node) {
$view_name = $node
->getAttribute('data-view-name');
$view_display = $node
->getAttribute('data-view-display');
$view_attr = Json::decode($node
->getAttribute('data-view-arguments'));
$view = Views::getView($view_name);
$view
->setDisplay($view_display);
if ($view_attr['override_title']) {
$view
->setTitle($view_attr['title']);
}
if (!empty($view_attr['filters'])) {
$view_filters = array_filter($view_attr['filters'], function ($k) use ($view_attr) {
return $view_attr['filters'][$k];
}, ARRAY_FILTER_USE_KEY);
$view
->setArguments($view_filters);
}
$view
->preExecute();
$view
->execute();
$build = [
'#theme_wrappers' => [
'views_entity_embed_container',
],
'#attributes' => [
'class' => [
'views-entity-embed',
],
],
'#view' => $view,
'#context' => [
'data-view-name' => $view_name,
'data-view-display' => $view_display,
'data-override-title' => $view_attr['override_title'],
'data-title' => $view_attr['title'],
],
];
return $build;
}
}