1

I found this function on the net. I have placed this in my custom functions file separate from functions.php.

function highlight_search_term($text){
    if(is_search()){
        $keys = implode('|', explode(' ', get_search_query()));
        $text = preg_replace('/(' . $keys .')/iu', '<span class="search-term">\1</span>', $text);
    }
    return $text;
}
add_filter('the_excerpt', 'highlight_search_term');
add_filter('the_title', 'highlight_search_term');

It works fine except it alters the read more link. Hovering over this link shows:

http://www.mysite.com/%3span%20classs=

When it is removed the link is unaffected. What is wrong with it? I have used the following CSS with it:

.search-term {
    background: yellow;
}

1 Answer 1

3

You can try running the function early so that it runs before the more link is created.

add_filter('the_excerpt', 'highlight_search_term',1);
add_filter('the_title', 'highlight_search_term');

But I don't think that solves the deeper problem, even if it were to work. That function is pretty crude and it will replace inside URLs and inside tag attributes, which it should not ever be doing as it would result, almost certainly, in broken links and broken markup.

Here is a more complicated, minimally tested version:

function highlight_search_term_placeholders() {
  static $iter = 0;
  $ret = "|##{$iter}##|";
  $iter++;
  return $ret;
}
function highlight_search_term_cb() {
  static $iter = 0;
  $ret = "##{$iter}##";
  $iter++;
  return $ret;
}
function highlight_search_term($text){
  if(is_search() && !is_admin()){
    $keys = implode('|', explode(' ', get_search_query()));
    $pattern = '/<[^>].*?>/i';
    preg_match_all($pattern,$text,$matches);
    $placeholders = array();
    foreach ($matches[0] as $v) {
      $placeholders[] = highlight_search_term_placeholders();
    }
    $text = preg_replace_callback($pattern,'highlight_search_term_cb',$text);
    $pattern2 = '/(' . $keys .')/iu';
    $text = preg_replace($pattern2, ' <span class="search-term">\1</span> ', $text);
    $text = preg_replace($placeholders,$matches[0],$text);
  }
  return $text;
}
add_filter('the_excerpt', 'highlight_search_term');
add_filter('the_content', 'highlight_search_term');
add_filter('the_title', 'highlight_search_term');

I built this to operate piecemeal, so that it (hopefully) will not replace anything at all inside of < and > tag opening and closing markers. It moves the markup out of the way, replaces everything else, and then puts the markup back. I am sure it could be cleaned up but that is a start.

5
  • Beat me to it! Great answer, with a regex to boot. May 1, 2013 at 15:00
  • Thanks for your reply. See below. It is still affecting the read more link with the same problem.
    – user32271
    May 1, 2013 at 16:54
  • Great answer? Off hand I noticed two problems when tested it. (1) the search term is preceded and followed by # signs and a number. For example, if I search for say "test", the highlighted search term is followed by shows ##52# test #53## (2) If the word is "testing", and I search for "test", the search highlights the part "test" and removes "i" from the remaining word!
    – Tara
    May 2, 2013 at 15:12
  • @t-p : It is much better than the previous version. Good point though. It is a minor issue with $pattern2, not with the string you mentioned. Try again, if you don't mind.
    – s_ha_dum
    May 2, 2013 at 15:34
  • @s_ha_dum : It works just perfect, NO issue with the more link or or any others. No doubt this is much better than the previous version!
    – Tara
    May 2, 2013 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.