diff --git a/core/modules/image/src/Plugin/Filter/FilterImageStyle.php b/core/modules/image/src/Plugin/Filter/FilterImageStyle.php
index 1c03de5..dffc408 100644
--- a/core/modules/image/src/Plugin/Filter/FilterImageStyle.php
+++ b/core/modules/image/src/Plugin/Filter/FilterImageStyle.php
@@ -6,15 +6,15 @@
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\file\FileInterface;
use Drupal\Core\Image\ImageFactory;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\file\FileInterface;
use Drupal\filter\Annotation\Filter;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Drupal\image\ImageStyleInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\Core\Render\RendererInterface;
/**
* Provides a filter to render inline images as image styles.
@@ -67,6 +67,7 @@ class FilterImageStyle extends FilterBase implements ContainerFactoryPluginInter
* @param \Drupal\Core\Image\ImageFactory $image_factory
* The image factory.
* @param \Drupal\Core\Render\RendererInterface $renderer
+ * The renderer.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository, ImageFactory $image_factory, RendererInterface $renderer) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
@@ -97,7 +98,8 @@ public function process($text, $langcode) {
$dom = HTML::load($text);
$xpath = new \DOMXPath($dom);
- // Process each img element DOM element found with the necessary attributes.
+ // Process each img element DOM element found with the necessary
+ // attributes.
/** @var \DOMElement $dom_element */
foreach ($xpath->query('//*[@data-entity-type="file" and @data-entity-uuid and @data-image-style]') as $dom_element) {
// Get the UUID and image style for the file.
@@ -154,12 +156,12 @@ protected function loadImageStyles() {
*/
protected function getImageInfo($file_uuid) {
/**
- * @var \Drupal\file\FileInterface;
+ * @var \Drupal\file\FileInterface $file;
*/
$file = $this->entityRepository->loadEntityByUuid('file', $file_uuid);
- // Determine width/height of the source image.
- $image_width = $image_height = NULL;
+ // Determine uri, width and height of the source image.
+ $image_uri = $image_width = $image_height = NULL;
$image = $this->imageFactory->get($file->getFileUri());
if ($image->isValid()) {
$image_uri = $file->getFileUri();
@@ -185,11 +187,13 @@ protected function getImageInfo($file_uuid) {
*/
protected function prepareImageAttributes(\DOMElement $dom_element) {
// Make sure all non-regenerated attributes are retained.
+ $dom_element->removeAttribute('data-entity-type-file');
$dom_element->removeAttribute('data-entity-uuid');
$dom_element->removeAttribute('data-image-style');
$dom_element->removeAttribute('width');
$dom_element->removeAttribute('height');
$dom_element->removeAttribute('src');
+
$attributes = array();
for ($i = 0; $i < $dom_element->attributes->length; $i++) {
$attr = $dom_element->attributes->item($i);
diff --git a/core/modules/responsive_image/src/Plugin/Filter/FilterResponsiveImageStyle.php b/core/modules/responsive_image/src/Plugin/Filter/FilterResponsiveImageStyle.php
index 3e7341f..fd47974 100644
--- a/core/modules/responsive_image/src/Plugin/Filter/FilterResponsiveImageStyle.php
+++ b/core/modules/responsive_image/src/Plugin/Filter/FilterResponsiveImageStyle.php
@@ -8,9 +8,18 @@
namespace Drupal\responsive_image\Plugin\Filter;
use Drupal\Component\Utility\Html;
+use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\EntityRepositoryInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Image\ImageFactory;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\file\FileInterface;
use Drupal\filter\Annotation\Filter;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
+use Drupal\responsive_image\ResponsiveImageStyleInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a filter to render inline images as responsive images.
@@ -23,72 +32,95 @@
* type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE
* )
*/
-class FilterResponsiveImageStyle extends FilterBase {
+class FilterResponsiveImageStyle extends FilterBase implements ContainerFactoryPluginInterface {
+
+ /**
+ * The entity type manager.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+ */
+ protected $entityTypeManager;
+
+ /**
+ * @var \Drupal\Core\Entity\EntityRepositoryInterface
+ */
+ protected $entityRepository;
+
+ /**
+ * @var \Drupal\Core\Image\ImageFactory
+ */
+ protected $imageFactory;
+
+ /**
+ * @var \Drupal\Core\Render\RendererInterface
+ */
+ protected $renderer;
+
+ /**
+ * Constructs a Drupal\Component\Plugin\PluginBase object.
+ *
+ * @param array $configuration
+ * A configuration array containing information about the plugin instance.
+ * @param string $plugin_id
+ * The plugin_id for the plugin instance.
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+ * The entity type manager.
+ * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
+ * The entity repository.
+ * @param \Drupal\Core\Image\ImageFactory $image_factory
+ * The image factory.
+ * @param \Drupal\Core\Render\RendererInterface $renderer
+ * The renderer.
+ */
+ public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository, ImageFactory $image_factory, RendererInterface $renderer) {
+ parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+ $this->entityTypeManager = $entity_type_manager;
+ $this->entityRepository = $entity_repository;
+ $this->imageFactory = $image_factory;
+ $this->renderer = $renderer;
+ }
/**
* {@inheritdoc}
*/
- public function process($text, $langcode) {
- $search = array();
- $replace = array();
+ 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('entity.repository'), $container->get('image.factory'), $container->get('renderer'));
+ }
+ /**
+ * {@inheritdoc}
+ */
+ public function process($text, $langcode) {
if (stristr($text, 'data-responsive-image-style') !== FALSE) {
- $responsive_image_styes = entity_load_multiple('responsive_image_style');
+ // Load all the responsive image styles so each img found in the text can
+ // be checked to ensure it has a valid responsive image style.
+ $responsive_image_styles = $this->loadResponsiveImageStyles();
+ // Load the text that is being processed into XML to find images.
$dom = Html::load($text);
$xpath = new \DOMXPath($dom);
- foreach ($xpath->query('//*[@data-entity-uuid and @data-responsive-image-style]') as $node) {
- $file_uuid = $node->getAttribute('data-entity-uuid');
- $node->removeAttribute('data-entity-uuid');
- $responsive_image_style_id = $node->getAttribute('data-responsive-image-style');
- $node->removeAttribute('data-responsive-image-style');
+
+ // Process each img element DOM element found with the necessary
+ // attributes.
+ /** @var \DOMElement $dom_element */
+ foreach ($xpath->query('//*[@data-entity-type="file" and @data-entity-uuid and @data-responsive-image-style]') as $dom_element) {
+ // Get the UUID and responsive image style for the file.
+ $file_uuid = $dom_element->getAttribute('data-entity-uuid');
+ $responsive_image_style_id = $dom_element->getAttribute('data-responsive-image-style');
// If the responsive image style is not a valid one, then don't
// transform the HTML.
- if (empty($file_uuid) || !in_array($responsive_image_style_id, array_keys($responsive_image_styes))) {
+ if (empty($file_uuid) || !in_array($responsive_image_style_id, array_keys($responsive_image_styles))) {
continue;
}
- $file = \Drupal::entityManager()->loadEntityByUuid('file', $file_uuid);
-
- // Determine width/height of images that don't have such attributes set.
- $width = $node->getAttribute('width');
- $height = $node->getAttribute('height');
- if (empty($width) || empty($height)) {
- $image = \Drupal::service('image.factory')->get($file->getFileUri());
- if ($image->isValid()) {
- if (empty($width)) {
- $width = $image->getWidth();
- }
- if (empty($height)) {
- $height = $image->getHeight();
- }
- }
- }
-
- // Make sure all non-regenerated attributes are retained.
- $node->removeAttribute('width');
- $node->removeAttribute('height');
- $node->removeAttribute('src');
- $attributes = array();
- for ($i = 0; $i < $node->attributes->length; $i++) {
- $attr = $node->attributes->item($i);
- $attributes[$attr->name] = $attr->value;
- }
-
- // Re-render as a responsive image.
- $responsive_image = array(
- '#theme' => 'responsive_image',
- '#uri' => $file->getFileUri(),
- '#width' => $width,
- '#height' => $height,
- '#attributes' => $attributes,
- '#responsive_image_style_id' => $responsive_image_style_id,
- );
- $altered_html = drupal_render($responsive_image);
+ // Transform the HTML for the img element by applying a responsive image
+ // style.
+ $altered_img = $this->getResponsiveImageStyleHtml($file_uuid, $responsive_image_style_id, $dom_element);
// Load the altered HTML into a new DOMDocument and retrieve the element.
- $updated_node = Html::load(trim($altered_html))->getElementsByTagName('body')
+ $updated_node = Html::load(trim($altered_img))->getElementsByTagName('body')
->item(0)
->childNodes
->item(0);
@@ -96,22 +128,132 @@ public function process($text, $langcode) {
// Import the updated node from the new DOMDocument into the original
// one, importing also the child nodes of the updated node.
$updated_node = $dom->importNode($updated_node, TRUE);
- // Finally, replace the original image node with the new image node!
- $node->parentNode->replaceChild($updated_node, $node);
+
+ // Finally, replace the original image node with the new image node.
+ $dom_element->parentNode->replaceChild($updated_node, $dom_element);
}
+ // Process the filter with the newly updated DOM.
return new FilterProcessResult(Html::serialize($dom));
}
+ // Process the filter if no image style img elements are found.
return new FilterProcessResult($text);
}
/**
+ * Loads the responsive image styles.
+ *
+ * @return string[]
+ */
+ protected function loadResponsiveImageStyles() {
+ return array_keys($this->entityTypeManager->getStorage('responsive_image_style')->loadMultiple());
+ }
+
+ /**
+ * Get the the width and height of an image based on the file UUID.
+ *
+ * @param string $file_uuid
+ * The UUID for the file.
+ *
+ * @return array
+ * The image information.
+ */
+ protected function getImageInfo($file_uuid) {
+ /**
+ * @var \Drupal\file\FileInterface $file;
+ */
+ $file = $this->entityRepository->loadEntityByUuid('file', $file_uuid);
+
+ // Determine uri, width and height of the source image.
+ $image_uri = $image_width = $image_height = NULL;
+ $image = $this->imageFactory->get($file->getFileUri());
+ if ($image->isValid()) {
+ $image_uri = $file->getFileUri();
+ $image_width = $image->getWidth();
+ $image_height = $image->getHeight();
+ }
+
+ return [
+ 'uri' => $image_uri,
+ 'width' => $image_width,
+ 'height' => $image_height
+ ];
+ }
+
+ /**
+ * Removes attributes that will be generated from image style theme function.
+ *
+ * @param \DOMElement $dom_element
+ * The DOM element for the img element.
+ *
+ * @return array
+ * The attributes array.
+ */
+ protected function prepareResponsiveImageAttributes(\DOMElement $dom_element) {
+ // Make sure all non-regenerated attributes are retained.
+ $dom_element->removeAttribute('data-entity-type-file');
+ $dom_element->removeAttribute('data-entity-uuid');
+ $dom_element->removeAttribute('data-responsive-image-style');
+ $dom_element->removeAttribute('width');
+ $dom_element->removeAttribute('height');
+ $dom_element->removeAttribute('src');
+
+ // Responsive image styles should override image styles.
+ if ($dom_element->hasAttribute('data-image-style')) {
+ $dom_element->removeAttribute('data-image-style');
+ }
+
+ $attributes = array();
+ for ($i = 0; $i < $dom_element->attributes->length; $i++) {
+ $attr = $dom_element->attributes->item($i);
+ $attributes[$attr->name] = $attr->value;
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Get the HTML for the img element after image style is applied.
+ *
+ * @param string $file_uuid
+ * The UUID for the file.
+ * @param string $responsive_image_style_id
+ * The ID for the responsive image style.
+ * @param \DOMElement $dom_element
+ * The DOM element for the image element.
+ *
+ * @return string
+ * The img element with the image style applied.
+ */
+ protected function getResponsiveImageStyleHtml($file_uuid, $responsive_image_style_id, \DOMElement $dom_element) {
+ $image_info = $this->getImageInfo($file_uuid);
+ $image_uri = $image_info['uri'];
+ $image_width = $image_info['width'];
+ $image_height = $image_info['height'];
+
+ // Remove attributes that will be generated by the image style.
+ $attributes = $this->prepareResponsiveImageAttributes($dom_element);
+
+ // Re-render as a responsive image.
+ $responsive_image = array(
+ '#theme' => 'responsive_image',
+ '#responsive_image_style_id' => $responsive_image_style_id,
+ '#uri' => $image_uri,
+ '#width' => $image_width,
+ '#height' => $image_height,
+ '#attributes' => $attributes,
+ );
+
+ return $this->renderer->render($responsive_image);
+ }
+
+ /**
* {@inheritdoc}
*/
public function tips($long = FALSE) {
if ($long) {
- $responsive_image_styles = entity_load_multiple('responsive_image_style');
+ $responsive_image_styles = $this->loadResponsiveImageStyles();
$list = '' . implode('
, ', array_keys($responsive_image_styles)) . '
';
return t('
You can make images responsive by adding a data-responsive-image-style
attribute, whose values is one of the responsive image style machine names: !responsive-image-style-machine-name-list.