You are here

function word_link_replace_text in Word Link 7

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

Find and convert defined word to link.

Parameters

array $words: Array with words.

string $subject: String in which need convert words to links.

Return value

string String with converted words.

2 calls to word_link_replace_text()
word_link_comment_view in ./word_link.module
Implements hook_comment_view().
word_link_process_node_fields in ./word_link.module
Find node fields content and pass it for processing.

File

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

Code

function word_link_replace_text($words, $subject) {

  // 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);

  // Implode all disallowed tags to string.
  $not = '';
  if (!empty($disallowed_tags)) {
    $not = array();
    foreach ($disallowed_tags as $ancestor) {
      $not[] = 'and not(ancestor::' . $ancestor . ')';
    }
    $not = implode(' ', $not);
  }

  // Get word link limit.
  $limit = variable_get('word_link_limit', 0);
  $preg_limit = $limit == 0 ? -1 : $limit;

  // Get current path.
  $path = drupal_strtolower(drupal_get_path_alias());
  $current_path = current_path();

  // Get highlight status.
  $highlight = variable_get('word_link_highlight', 0);

  // Create array of links and replace patterns for each word.
  foreach ($words as $word) {
    $url = drupal_get_path_alias($word->url);
    $match = FALSE;

    // Check if current path matches word except path.
    if (!empty($word->except)) {
      $match = drupal_match_path($path, $word->except);
      if ($path != $current_path) {
        $match = $match || drupal_match_path($current_path, $word->except);
      }
    }

    // Get visibility status and check if need to convert word on this page.
    $visibility = empty($word->except) || !isset($word->visibility) ? FALSE : $word->visibility;
    if ($url != $path && !$match && !$visibility || $url != $path && $visibility && $match) {

      // Pattern which will be used to replace words.
      $pattern = '$0';

      // If highlight is off build links.
      if (!$highlight) {

        // Build external link.
        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,
              ),
              'rel' => $word->rel,
              'title' => $word->url_title,
              'target' => '_blank',
            )),
            'external' => TRUE,
          ));
        }
        else {
          $replace[] = l($pattern, $word->url, array(
            'attributes' => array_filter(array(
              'class' => array(
                $word->class,
              ),
              'rel' => $word->rel,
              'title' => $word->url_title,
            )),
          ));
        }
      }
      else {
        $replace[] = '<span title="' . $word->url_title . '" class="' . $word->class . '">' . $pattern . '</span>';
      }

      // Build a patterns array.
      $pattern = '/((\\b)|(?<=))(' . preg_quote($word->text, '/') . ')(?!(".*>)|[\'"&’^])\\b/u';
      if ($word->case_sensitive) {
        $search[] = $pattern;
      }
      else {
        $search[] = $pattern . 'i';
      }
    }
  }

  // Find and convert words if $searh and $replace arrays are not empty.
  if (isset($search) && isset($replace)) {

    // Replace '&' to '&amp;';
    $subject = preg_replace('/&(?![a-z])/u', '&amp;', $subject);

    // Replace '&amp;' to '&#38;#38;';
    $subject = str_replace('&amp;', '&#38;#38;', $subject);

    // Turn off errors.
    libxml_use_internal_errors(TRUE);

    // Load string to DOMDocument.
    $dom = filter_dom_load($subject);
    $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);
      }
    }

    // Convert a DOM object back to an HTML snippet.
    $subject = filter_dom_serialize($dom);
  }

  // Remove '#38;' entity.
  $subject = str_replace('#38;', '', $subject);
  return $subject;
}