You are here

function word_link_replace_text in Word Link 8

Same name and namespace in other branches
  1. 7 word_link.module \word_link_replace_text()

Find and replace defined word to link.

2 calls to word_link_replace_text()
word_link_comment_view in ./word_link.module
Implements hook_comment_view().
word_link_node_view in ./word_link.module
Implements hook_node_view().

File

./word_link.module, line 187
This module allows users to replace previously defined words to the links.

Code

function word_link_replace_text($words, $subject, $langcode = NULL) {

  // Get disallowed html tags and explode it to array.
  $disallowed_tags = variable_get('word_link_tags_except', NULL);
  $disallowed_tags = preg_split('/\\s+|<|>/', $disallowed_tags, -1, PREG_SPLIT_NO_EMPTY);
  if (!empty($disallowed_tags)) {
    foreach ($disallowed_tags as $ancestor) {
      $not[] = 'and not(ancestor::' . $ancestor . ')';
    }
    $not = implode(' ', $not);
  }
  else {
    $not = '';
  }

  // Get word link limit.
  $limit = variable_get('word_link_limit', 0);
  $preg_limit = $limit == 0 ? -1 : $limit;
  $current_path = current_path();
  $path = drupal_strtolower(drupal_container()
    ->get('path.alias_manager')
    ->getPathAlias($current_path, $langcode));
  foreach ($words as $word) {
    $url = drupal_container()
      ->get('path.alias_manager')
      ->getPathAlias($word->url, $langcode);
    $match = FALSE;
    if (!empty($word->except)) {
      $match = drupal_match_path($path, $word->except);
      if ($path != $current_path) {
        $match = $match || drupal_match_path($current_path, $word->except);
      }
    }
    $visibility = empty($word->except) ? FALSE : $word->visibility;
    if ($url != $path && !$match && !$visibility || $url != $path && $visibility && $match) {

      // Build a link.
      $pattern = '$0';
      if (strpos($word->url, 'http://') === 0 || strpos($word->url, 'https://') === 0) {
        $replace[] = l($pattern, $word->url, array(
          'attributes' => array_filter(array(
            'class' => array(
              $word->class,
            ),
            'title' => $word->url_title,
            'target' => '_blank',
          )),
          'external' => TRUE,
        ));
      }
      else {
        $replace[] = l($pattern, $word->url, array(
          'attributes' => array_filter(array(
            'class' => array(
              $word->class,
            ),
            'title' => $word->url_title,
          )),
        ));
      }
      $pattern = '/((\\b)|(?<=\\W))(' . preg_quote($word->text, '/') . ')(?!(<\\/a>)|(".*>)|[\'"&’^])\\b/u';
      if ($word->case_sensitive) {
        $search[] = $pattern;
      }
      else {
        $search[] = $pattern . 'i';
      }
    }
  }
  if (isset($search) && isset($replace)) {
    $dom = new DOMDocument();
    $subject = str_replace('&amp;', '&#38;#38;', preg_replace('/&(?![a-z])/u', '&amp;', $subject));

    // Comment <iframe> tag because it can cause error.
    $subject = str_replace(array(
      '<iframe',
      '</iframe>',
    ), array(
      '<!--word_link<iframe',
      '</iframe>word_link-->',
    ), $subject);
    libxml_use_internal_errors(TRUE);
    $dom
      ->loadHTML(mb_convert_encoding(htmlspecialchars_decode($subject), 'HTML-ENTITIES', 'UTF-8'));
    $xpath = new DOMXPath($dom);
    if ($limit != 0) {
      $counts = array_fill(0, count($search), 0);
      foreach ($xpath
        ->query('//text()[not(ancestor::a) ' . $not . ']') as $node) {
        $replaced = $node->wholeText;
        $del = array_filter($counts);
        foreach ($del as $key => $val) {
          if ($val >= $limit) {
            unset($search[$key], $replace[$key]);
          }
        }
        foreach ($search as $id => $search_word) {
          $new_preg_limit = $preg_limit - $counts[$id];
          $replaced = preg_replace($search_word, $replace[$id], $replaced, $new_preg_limit, $count);
          $counts[$id] += $count;
        }
        $new_node = $dom
          ->createDocumentFragment();
        $new_node
          ->appendXML($replaced);
        $node->parentNode
          ->replaceChild($new_node, $node);
      }
    }
    else {
      foreach ($xpath
        ->query('//text()[not(ancestor::a) ' . $not . ']') as $node) {
        $replaced = preg_replace($search, $replace, $node->wholeText);
        $new_node = $dom
          ->createDocumentFragment();
        $new_node
          ->appendXML($replaced);
        $node->parentNode
          ->replaceChild($new_node, $node);
      }
    }

    // Get only the body tag with its contents, then trim the body tag
    // itself to get only the original content.
    $subject = drupal_substr($dom
      ->saveXML($xpath
      ->query('//body')
      ->item(0)), 6, -7);
  }
  return str_replace(array(
    '<!--word_link<iframe',
    '</iframe>word_link-->',
  ), array(
    '<iframe',
    '</iframe>',
  ), $subject);
}