/**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $this->currentFilterProcessResult = new FilterProcessResult($text);
     $this->currentFilterProcessResult->setProcessedText(preg_replace_callback('/\\[currency-localize:([a-z]{3}):(.+?)\\]/i', [$this, 'processCallback'], $text));
     $result = $this->currentFilterProcessResult;
     unset($this->currentFilterProcessResult);
     return $result;
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     // Track if widget has been found so that we can attached the
     // jquery_ui_filter library and settings.
     $has_widget = FALSE;
     foreach (self::$widgets as $name => $widget) {
         if (strpos($text, '[' . $name) === FALSE) {
             continue;
         }
         $has_widget = TRUE;
         // Remove block tags around tokens.
         $text = preg_replace('#<(p|div)[^>]*>\\s*(\\[/?' . $name . '[^]]*\\])\\s*</\\1>#', '\\2', $text);
         // Convert opening [token] to opening <div data-ui-*> tag.
         $text = preg_replace_callback('#\\[' . $name . '([^]]*)?\\]#is', function ($match) use($name) {
             // Set data-ui-* attributes from role and options.
             $attributes = new Attribute(['data-ui-role' => $name]);
             $options = $this->parseOptions($match[1]);
             foreach ($options as $name => $value) {
                 $attributes->setAttribute('data-ui-' . $name, $value);
             }
             return "<div{$attributes}>";
         }, $text);
         // Convert closing [/token] to closing </div> tag.
         $text = str_replace('[/' . $name . ']', '</div>', $text);
     }
     if ($has_widget) {
         $result->setAttachments(['library' => ['jquery_ui_filter/jquery_ui_filter'], 'drupalSettings' => ['jquery_ui_filter' => \Drupal::config('jquery_ui_filter.settings')->get()]]);
     }
     return $result->setProcessedText($text);
 }
예제 #3
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     $placeholder = $result->createPlaceholder('\\Drupal\\filter_test\\Plugin\\Filter\\FilterTestPlaceholders::renderDynamicThing', ['llama']);
     $result->setProcessedText($text . '<p>' . $placeholder . '</p>');
     return $result;
 }
예제 #4
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $response = new FilterProcessResult($text);
     // Use a look ahead to match the capture groups in any order.
     if (preg_match_all('/<p>(?<json>{(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})<\\/p>/', $text, $matches)) {
         foreach ($matches['json'] as $delta => $match) {
             // Ensure the JSON string is valid.
             $embed_data = json_decode($match, TRUE);
             if (!is_array($embed_data)) {
                 continue;
             }
             // If the URL can't matched to a provider or the settings are invalid,
             // ignore it.
             $provider = $this->providerManager->loadProviderFromInput($embed_data['video_url']);
             if (!$provider || !$this->validSettings($embed_data['settings'])) {
                 continue;
             }
             $embed_code = $provider->renderEmbedCode($embed_data['settings']['width'], $embed_data['settings']['height'], $embed_data['settings']['autoplay']);
             // Add the container to make the video responsive if it's been
             //configured as such. This usually is attached to field output in the
             // case of a formatter, but a custom container must be used where one is
             // not present.
             if ($embed_data['settings']['responsive']) {
                 $embed_code = ['#type' => 'container', '#attributes' => ['class' => ['video-embed-field-responsive-video']], 'children' => $embed_code];
             }
             // Replace the JSON settings with a video.
             $text = str_replace($matches[0][$delta], $this->renderer->renderRoot($embed_code), $text);
         }
     }
     // Add the required responsive video library and update the response text.
     $response->setProcessedText($text);
     $response->addAttachments(['library' => ['video_embed_field/responsive-video']]);
     return $response;
 }
예제 #5
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     if (stristr($text, 'data-entity-type="file"') !== FALSE) {
         $dom = Html::load($text);
         $xpath = new \DOMXPath($dom);
         $processed_uuids = array();
         foreach ($xpath->query('//*[@data-entity-type="file" and @data-entity-uuid]') as $node) {
             $uuid = $node->getAttribute('data-entity-uuid');
             // If there is a 'src' attribute, set it to the file entity's current
             // URL. This ensures the URL works even after the file location changes.
             if ($node->hasAttribute('src')) {
                 $file = $this->entityManager->loadEntityByUuid('file', $uuid);
                 if ($file) {
                     $node->setAttribute('src', file_url_transform_relative(file_create_url($file->getFileUri())));
                 }
             }
             // Only process the first occurrence of each file UUID.
             if (!isset($processed_uuids[$uuid])) {
                 $processed_uuids[$uuid] = TRUE;
                 $file = $this->entityManager->loadEntityByUuid('file', $uuid);
                 if ($file) {
                     $result->addCacheTags($file->getCacheTags());
                 }
             }
         }
         $result->setProcessedText(Html::serialize($dom));
     }
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     if (strpos($text, '<oembed') !== FALSE) {
         $result->setProcessedText($this->ckeditor_media_embed->processEmbeds($text));
     }
     return $result;
 }
예제 #7
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     // Replace node macros with entity content.
     $pattern = '/\\[mailchimp_campaign\\|entity_type=(\\w+)\\|entity_id=(\\d+)\\|view_mode=(\\w+)\\]/s';
     $text = preg_replace_callback($pattern, array($this, 'mailchimp_campaign_process_callback'), $text);
     // Convert URL to absolute.
     $text = $this->convertUrl($text);
     $result->setProcessedText($text);
     return $result;
 }
예제 #8
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $new_text = $text;
     $filter_result = new FilterProcessResult($text);
     if (preg_match('/\\[survey\\:.+\\]/', $text, $result)) {
         $token = $result[0];
         $start = strpos($token, ':') + 1;
         $length = strpos($token, ']') - $start;
         $id = substr($token, $start, $length);
         $block = Block::load($id);
         if ($block) {
             $replace = $block->get('settings')['html'];
             $new_text = str_replace($token, $replace, $text);
             $filter_result->setProcessedText($new_text);
             $filter_result->setCacheTags($block->getCacheTags());
         }
     }
     return $filter_result;
 }
예제 #9
0
 /**
  * {@inheritdoc}
  */
 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', '#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_nodes = Html::load($altered_html)->getElementsByTagName('body')->item(0)->childNodes;
             foreach ($updated_nodes as $updated_node) {
                 // 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);
                 $node->parentNode->insertBefore($updated_node, $node);
             }
             // Finally, remove the original data-caption node.
             $node->parentNode->removeChild($node);
         }
         $result->setProcessedText(Html::serialize($dom))->addAttachments(array('library' => array('filter/caption')));
     }
     return $result;
 }
예제 #10
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     if (stristr($text, 'data-align') !== FALSE) {
         $dom = Html::load($text);
         $xpath = new \DOMXPath($dom);
         foreach ($xpath->query('//*[@data-align]') as $node) {
             // Read the data-align attribute's value, then delete it.
             $align = $node->getAttribute('data-align');
             $node->removeAttribute('data-align');
             // If one of the allowed alignments, add the corresponding class.
             if (in_array($align, array('left', 'center', 'right'))) {
                 $classes = $node->getAttribute('class');
                 $classes = strlen($classes) > 0 ? explode(' ', $classes) : array();
                 $classes[] = 'align-' . $align;
                 $node->setAttribute('class', implode(' ', $classes));
             }
         }
         $result->setProcessedText(Html::serialize($dom));
     }
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     if (stristr($text, '<img ') !== FALSE) {
         $dom = Html::load($text);
         $images = $dom->getElementsByTagName('img');
         foreach ($images as $image) {
             $src = $image->getAttribute("src");
             // The src must be non-empty.
             if (Unicode::strlen($src) === 0) {
                 continue;
             }
             // The src must not already be an external URL
             if (stristr($src, 'http://') !== FALSE || stristr($src, 'https://') !== FALSE) {
                 continue;
             }
             $url = Url::fromUri('internal:' . $src, array('absolute' => TRUE));
             $url_string = $url->toString();
             $image->setAttribute('src', $url_string);
         }
         $result->setProcessedText(Html::serialize($dom));
     }
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     $dom = Html::load($text);
     $xpath = new \DOMXPath($dom);
     /** @var \DOMNode $node */
     foreach ($xpath->query('//img') as $node) {
         // Read the data-align attribute's value, then delete it.
         $width = $node->getAttribute('width');
         $height = $node->getAttribute('height');
         $src = $node->getAttribute('src');
         if (!UrlHelper::isExternal($src)) {
             if ($width || $height) {
                 /** @var \DOMNode $element */
                 $element = $dom->createElement('a');
                 $element->setAttribute('href', $src);
                 $node->parentNode->replaceChild($element, $node);
                 $element->appendChild($node);
             }
         }
     }
     $result->setProcessedText(Html::serialize($dom));
     return $result;
 }
예제 #13
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     if (stristr($text, 'data-caption') !== FALSE || stristr($text, 'data-align') !== FALSE) {
         $caption_found = FALSE;
         $dom = Html::load($text);
         $xpath = new \DOMXPath($dom);
         foreach ($xpath->query('//*[@data-caption or @data-align]') as $node) {
             $caption = NULL;
             $align = NULL;
             // Retrieve, then remove the data-caption and data-align attributes.
             if ($node->hasAttribute('data-caption')) {
                 $caption = String::checkPlain($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 = String::decodeEntities($caption);
                 $caption = Xss::filter($caption, array('a', 'em', 'strong', 'cite', 'code', 'br'));
                 // The caption must be non-empty.
                 if (Unicode::strlen($caption) === 0) {
                     $caption = NULL;
                 }
             }
             if ($node->hasAttribute('data-align')) {
                 $align = $node->getAttribute('data-align');
                 $node->removeAttribute('data-align');
                 // Only allow 3 values: 'left', 'center' and 'right'.
                 if (!in_array($align, array('left', 'center', 'right'))) {
                     $align = NULL;
                 }
             }
             // Don't transform the HTML if there isn't a caption after validation.
             if ($caption === NULL) {
                 // If there is a valid alignment, then transform the data-align
                 // attribute to a corresponding alignment class.
                 if ($align !== NULL) {
                     $classes = $node->getAttribute('class');
                     $classes = strlen($classes) > 0 ? explode(' ', $classes) : array();
                     $classes[] = 'align-' . $align;
                     $node->setAttribute('class', implode(' ', $classes));
                 }
                 continue;
             } else {
                 $caption_found = TRUE;
             }
             // Given the updated node, caption and alignment: re-render it with a
             // caption.
             $filter_caption = array('#theme' => 'filter_caption', '#node' => SafeMarkup::set($node->C14N()), '#tag' => $node->tagName, '#caption' => $caption, '#align' => $align);
             $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 image node with the new image node!
             $node->parentNode->replaceChild($updated_node, $node);
         }
         $result->setProcessedText(Html::serialize($dom));
         if ($caption_found) {
             $result->addAssets(array('library' => array('filter/caption')));
         }
     }
     return $result;
 }