Search code examples
phpsymfonytwigtimber

Highlight search terms in search results in Twig/Timber


I'm working with the answer to this question Twig highlight word (Timber plugin) to update the function to work under the newer Timber/Twig 2 filter structure.

But I'm getting the error that "Argument 2 passed to {closure}() must be of the type array, null given".

So I know that I need to pass the search term(s) to the function. How do I do that?

Do I get search term(s) from {{ search_query }} on the search-results.twig template?

Or are the search term(s) in a global I can get from search.php and the "context" call in that file, i.e. $context['search_query'] = get_search_query();?

I need to use the filter in the standard way in search-results.twig, like this {{ content|highlight }} as I have separate fields for the search results title and content and want to highlight the terms in each.

This function in functions.php currently throws the error noted above:

add_filter('timber/twig', function($twig) {
   $twig->addExtension(new Twig_Extension_StringLoader());

   $twig->addFilter(
     new Twig_SimpleFilter(
       'highlight', 

function($text, array $terms) {

    $highlight = array();
    foreach($terms as $term) {
       $highlight[]= '<span class="highlight">'.$term.'</span>';
    }

    return str_ireplace($terms, $highlight, $text);
}

 )
   );

   return $twig;
});

Update: this works

functions.php:

add_filter('timber/twig', function($twig) {
   $twig->addExtension(new Twig_Extension_StringLoader());

   $twig->addFilter(
     new Twig_SimpleFilter(
       'highlight', 

function($text, array $terms) {

    $highlight = array();
    foreach($terms as $term) {
       $highlight[]= '<span class="highlight">'.$term.'</span>';
    }

    return str_ireplace($terms, $highlight, $text);
}

 )
   );

   return $twig;
});

and in search-results.twig:

{% set searches = [ search_query ] %}

and

{{ content|highlight(search_query|split(' ')) }}

and in search.php

$search_results = Timber::get_posts();
$context['search_query'] = get_search_query();

Solution

  • Pass the terms u want to highlight like this

    {{ content | highlight(['foo', 'bar',]) }}
    

    If you only have one term defined, u could do it like this

    {% set search = 'foo' %}
    {{ content | highlight([ search, ]) }}
    

    If I were you i'd change the function to this

    function($text, $terms) {
        if (!is_array($terms)) $terms = [ $terms, ];
        $highlight = array();
        foreach($terms as $term) {
           $highlight[]= '<span class="highlight">'.$term.'</span>';
        }
    
        return str_ireplace($terms, $highlight, $text);
    }
    

    Then u can pass a single term or multiple

    {% set search = 'foo' %}
    {{ content | highlight(search) }}
    
    {% set searches = [ 'foo', 'bar', ] %}
    {{ content | highlight(searches) }}