/**
  * {@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);
     // The changes made by this filter are language-specific.
     $result->addCacheContexts(['languages:' . LanguageInterface::TYPE_CONTENT]);
     return $result;
 }
 /**
  * {@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);
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     $result->addCacheTags(array('foo:bar'));
     $result->addCacheTags(array('foo:baz'));
     return $result;
 }
 /**
  * {@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;
 }
 /**
  * {@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;
 }
 /**
  * {@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;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $callback = '\\Drupal\\filter_test\\Plugin\\Filter\\FilterTestPostRenderCache::renderDynamicThing';
     $context = array('thing' => 'llama');
     $placeholder = drupal_render_cache_generate_placeholder($callback, $context);
     $result = new FilterProcessResult($text . '<p>' . $placeholder . '</p>');
     $result->addPostRenderCacheCallback($callback, $context);
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $invitation = $this->settings['celebrate_invitation'] ? ' Come on!' : '';
     $replace = '<span class="celebrate-filter">' . $this->t('Good Times!' . $invitation) . '</span>';
     $new_text = str_replace('[celebrate]', $replace, $text);
     $result = new FilterProcessResult($new_text);
     $result->setAttachments(array('library' => array('custom_filters/celebrate-shake')));
     return $result;
 }
 /**
  * {@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;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     if (stristr($text, '<pre') !== FALSE) {
         $attach = FALSE;
         $nodes = Html::load($text)->getElementsByTagName('pre');
         foreach ($nodes as $node) {
             if (preg_match('/\\bbrush\\b:(.*?);/i', $node->getAttribute('class'))) {
                 $attach = TRUE;
                 break;
             }
         }
         if ($attach) {
             $result->addAttachments(['library' => ['syntax_highlighter/highlight']]);
         }
     }
     return $result;
 }
Exemple #12
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;
 }
Exemple #13
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;
 }
 /**
  * {@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');
             // 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());
                 }
             }
         }
     }
     return $result;
 }
Exemple #15
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);
     $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;
 }
 /**
  * {@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;
 }
 /**
  * Implements preg_replace_callback() callback.
  *
  * @see self::process()
  */
 function processCallback(array $matches)
 {
     $currency_code = $matches[1];
     $amount = $this->input->parseAmount($matches[2]);
     // The amount is invalid, so return the token.
     if (!$amount) {
         return $matches[0];
     }
     /** @var \Drupal\currency\Entity\CurrencyInterface $currency */
     $currency = $this->currencyStorage->load($currency_code);
     $this->currentFilterProcessResult->addCacheableDependency($currency);
     if ($currency) {
         return $currency->formatAmount($amount);
     }
     // The currency code is invalid, so return the token.
     return $matches[0];
 }
 /**
  * Implements preg_replace_callback() callback.
  *
  * @see self::process()
  */
 function processCallback(array $matches)
 {
     $currency_code_from = $matches[1];
     $currency_code_to = $matches[2];
     $amount = str_replace(':', '', $matches[3]);
     if (strlen($amount) !== 0) {
         $amount = $this->input->parseAmount($amount);
         // The amount is invalid, so return the token.
         if (!$amount) {
             return $matches[0];
         }
     } else {
         $amount = 1;
     }
     $exchange_rate = $this->exchangeRateProvider->load($currency_code_from, $currency_code_to);
     $this->currentFilterProcessResult->addCacheableDependency($exchange_rate);
     if ($exchange_rate) {
         return bcmul($amount, $exchange_rate->getRate(), 6);
     }
     // No exchange rate could be loaded, so return the token.
     return $matches[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;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     // Supporting both [fn] and <fn> now. Thanks to fletchgqc
     // http://drupal.org/node/268026.
     // Convert all square brackets to angle brackets. This way all further code
     // just manipulates angle brackets. (Angle brackets are preferred here for
     // the simple reason that square brackets are more tedious to use in
     // regexps).
     $text = preg_replace('|\\[fn([^\\]]*)\\]|', '<fn$1>', $text);
     $text = preg_replace('|\\[/fn\\]|', '</fn>', $text);
     $text = preg_replace('|\\[footnotes([^\\]]*)\\]|', '<footnotes$1>', $text);
     // Check that there are an even number of open and closing tags.
     // If there is one closing tag missing, append this to the end.
     // If there is more disparity, throw a warning and continue.
     // A closing tag may sometimes be missing when we are processing a teaser
     // and it has been cut in the middle of the footnote.
     // See http://drupal.org/node/253326
     $foo = array();
     $open_tags = preg_match_all("|<fn([^>]*)>|", $text, $foo);
     $close_tags = preg_match_all("|</fn>|", $text, $foo);
     if ($open_tags == $close_tags + 1) {
         $text = $text . '</fn>';
     } elseif ($open_tags > $close_tags + 1) {
         trigger_error(t("You have unclosed fn tags. This is invalid and will\n        produce unpredictable results."));
     }
     // Before doing the replacement, the callback function needs to know which
     // options to use.
     $this->replaceCallback($this->settings['footnotes_collapse'], 'prepare');
     $pattern = '|<fn([^>]*)>(.*?)</fn>|s';
     $text = preg_replace_callback($pattern, array($this, 'replaceCallback'), $text);
     // Replace tag <footnotes> with the list of footnotes.
     // If tag is not present, by default add the footnotes at the end.
     // Thanks to acp on drupal.org for this idea. see
     // http://drupal.org/node/87226.
     $footer = $this->replaceCallback(NULL, 'output footer');
     $pattern = '|(<footnotes([^\\]]*)>)|';
     if (preg_match($pattern, $text) > 0) {
         $text = preg_replace($pattern, $footer, $text, 1);
     } else {
         $text .= "\n\n" . $footer;
     }
     $result = new FilterProcessResult($text);
     $result->setAttachments(array('library' => array('footnotes/footnotes')));
     return $result;
 }
Exemple #22
0
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     $result->addAttachments(array('library' => array('filter/caption')));
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function process($text, $langcode)
 {
     $result = new FilterProcessResult($text);
     try {
         // Load GeSHi library (if not already).
         $geshi_library = libraries_load('geshi');
         if (!$geshi_library['loaded']) {
             throw new \Exception($geshi_library['error message']);
         }
         // Get the available tags.
         list($generic_code_tags, $language_tags, $tag_to_lang) = $this->getTags();
         if (in_array(GeshiFilter::BRACKETS_PHPBLOCK, array_filter($this->tagStyles()))) {
             $language_tags[] = 'questionmarkphp';
             $tag_to_lang['questionmarkphp'] = 'php';
         }
         $tags = array_merge($generic_code_tags, $language_tags);
         // Escape special (regular expression) characters in tags (for tags like
         // 'c++' and 'c#').
         $tags = preg_replace('#(\\+|\\#)#', '\\\\$1', $tags);
         $tags_string = implode('|', $tags);
         // Pattern for matching the prepared "<code>...</code>" stuff.
         $pattern = '#\\[geshifilter-(' . $tags_string . ')([^\\]]*)\\](.*?)(\\[/geshifilter-\\1\\])#s';
         $text = preg_replace_callback($pattern, array($this, 'replaceCallback'), $text);
         // Create the object with result.
         $result = new FilterProcessResult($text);
         // Add the css file when necessary.
         if ($this->config->get('css_mode') == GeshiFilter::CSS_CLASSES_AUTOMATIC) {
             $result->setAttachments(array('library' => array('geshifilter/geshifilter')));
         }
         // Add cache tags, so we can re-create the node when some geshifilter
         // settings change.
         $cache_tags = array('geshifilter');
         $result->addCacheTags($cache_tags);
     } catch (\Exception $e) {
         watchdog_exception('geshifilter', $e);
         drupal_set_message($geshi_library['error message'], 'error');
     }
     return $result;
 }