You are here

public function FilterCaption::process in Zircon Profile 8.0

Same name and namespace in other branches
  1. 8 core/modules/filter/src/Plugin/Filter/FilterCaption.php \Drupal\filter\Plugin\Filter\FilterCaption::process()

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

core/modules/filter/src/Plugin/Filter/FilterCaption.php, line 34
Contains \Drupal\filter\Plugin\Filter\FilterCaption.

Class

FilterCaption
Provides a filter to caption elements.

Namespace

Drupal\filter\Plugin\Filter

Code

public function process($text, $langcode) {
  $result = new FilterProcessResult($text);
  if (stristr($text, 'data-caption') !== FALSE) {
    $dom = Html::load($text);
    $xpath = new \DOMXPath($dom);
    foreach ($xpath
      ->query('//*[@data-caption]') as $node) {

      // Read the data-caption attribute's value, then delete it.
      $caption = Html::escape($node
        ->getAttribute('data-caption'));
      $node
        ->removeAttribute('data-caption');

      // Sanitize caption: decode HTML encoding, limit allowed HTML tags; only
      // allow inline tags that are allowed by default, plus <br>.
      $caption = Html::decodeEntities($caption);
      $caption = FilteredMarkup::create(Xss::filter($caption, array(
        'a',
        'em',
        'strong',
        'cite',
        'code',
        'br',
      )));

      // The caption must be non-empty.
      if (Unicode::strlen($caption) === 0) {
        continue;
      }

      // Given the updated node and caption: re-render it with a caption, but
      // bubble up the value of the class attribute of the captioned element,
      // this allows it to collaborate with e.g. the filter_align filter.
      $tag = $node->tagName;
      $classes = $node
        ->getAttribute('class');
      $node
        ->removeAttribute('class');
      $node = $node->parentNode->tagName === 'a' ? $node->parentNode : $node;
      $filter_caption = array(
        '#theme' => 'filter_caption',
        // We pass the unsanitized string because this is a text format
        // filter, and after filtering, we always assume the output is safe.
        // @see \Drupal\filter\Element\ProcessedText::preRenderText()
        '#node' => FilteredMarkup::create($node
          ->C14N()),
        '#tag' => $tag,
        '#caption' => $caption,
        '#classes' => $classes,
      );
      $altered_html = drupal_render($filter_caption);

      // Load the altered HTML into a new DOMDocument and retrieve the element.
      $updated_node = Html::load($altered_html)
        ->getElementsByTagName('body')
        ->item(0)->childNodes
        ->item(0);

      // 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 node with the new node.
      $node->parentNode
        ->replaceChild($updated_node, $node);
    }
    $result
      ->setProcessedText(Html::serialize($dom))
      ->addAttachments(array(
      'library' => array(
        'filter/caption',
      ),
    ));
  }
  return $result;
}