You are here

public function FilterResponsiveImageStyle::process in Inline responsive images 8.2

Performs the filter processing.

Parameters

string $text: The text string to be filtered.

string $langcode: The language code of the text to be filtered.

Return value

\Drupal\filter\FilterProcessResult The filtered text, wrapped in a FilterProcessResult object, and possibly with associated assets, cacheability metadata and placeholders.

Overrides FilterInterface::process

See also

\Drupal\filter\FilterProcessResult

File

src/Plugin/Filter/FilterResponsiveImageStyle.php, line 50
Contains \Drupal\inline_responsive_images\Plugin\Filter\FilterResponsiveImageStyle.

Class

FilterResponsiveImageStyle
Provides a filter to render inline images as responsive images.

Namespace

Drupal\inline_responsive_images\Plugin\Filter

Code

public function process($text, $langcode) {
  if (stristr($text, 'data-responsive-image-style') !== FALSE && stristr($text, 'data-image-style') == FALSE) {
    $image_styles = \Drupal::entityTypeManager()
      ->getStorage('responsive_image_style')
      ->loadMultiple();
    $dom = Html::load($text);
    $xpath = new \DOMXPath($dom);
    foreach ($xpath
      ->query('//*[@data-entity-type="file" and @data-entity-uuid and @data-responsive-image-style]') as $node) {
      $file_uuid = $node
        ->getAttribute('data-entity-uuid');
      $image_style_id = $node
        ->getAttribute('data-responsive-image-style');

      // If the image style is not a valid one, then don't transform the HTML.
      if (empty($file_uuid) || !isset($image_styles[$image_style_id])) {
        continue;
      }

      // Retrieved matching file in array for the specified uuid.
      $matching_files = \Drupal::entityTypeManager()
        ->getStorage('file')
        ->loadByProperties([
        'uuid' => $file_uuid,
      ]);
      $file = reset($matching_files);

      // Stop further element processing, if it's not a valid file.
      if (!$file) {
        continue;
      }
      $image = \Drupal::service('image.factory')
        ->get($file
        ->getFileUri());

      // Stop further element processing, if it's not a valid image.
      if (!$image
        ->isValid()) {
        continue;
      }
      $width = $image
        ->getWidth();
      $height = $image
        ->getHeight();
      $node
        ->removeAttribute('width');
      $node
        ->removeAttribute('height');
      $node
        ->removeAttribute('src');

      // Make sure all non-regenerated attributes are retained.
      $attributes = [];
      for ($i = 0; $i < $node->attributes->length; $i++) {
        $attr = $node->attributes
          ->item($i);
        $attribute_name = $attr->name;
        if ($attribute_name === 'class') {
          $attributes[$attribute_name][] = $attr->value;
        }
        else {
          $attributes[$attribute_name] = $attr->value;
        }
      }

      // Create $attributes['class'] if it doesn't exist.
      // Append responsive_image_style_id to classes attribute.
      $image_style_id_class = Html::cleanCssIdentifier($image_style_id);
      $attributes['class'][] = $image_style_id_class;
      $attributes['class'][] = 'image-style-' . $image_style_id_class;

      // Set up image render array.
      $image = [
        '#theme' => 'responsive_image',
        '#uri' => $file
          ->getFileUri(),
        '#width' => $width,
        '#height' => $height,
        '#attributes' => $attributes,
        '#responsive_image_style_id' => $image_style_id,
      ];
      $altered_html = \Drupal::service('renderer')
        ->render($image);

      // Load the altered HTML into a new DOMDocument and retrieve the elements.
      $alt_nodes = Html::load(trim($altered_html))
        ->getElementsByTagName('body')
        ->item(0)->childNodes;
      foreach ($alt_nodes as $alt_node) {

        // Import the updated node from the new DOMDocument into the original
        // one, importing also the child nodes of the updated node.
        $new_node = $dom
          ->importNode($alt_node, TRUE);

        // Add the image node(s)!
        // The order of the children is reversed later on, so insert them in reversed order now.
        $node->parentNode
          ->insertBefore($new_node, $node);
      }

      // Finally, remove the original image node.
      $node->parentNode
        ->removeChild($node);
    }
    return new FilterProcessResult(Html::serialize($dom));
  }
  return new FilterProcessResult($text);
}