Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Form Questions

Highlight search query in results page?


Reply

25 Posts   7405 Views

Avatar
Juanitou

24 August 2009 at 10:06pm Community Member, 323 Posts

Thank you very much! I've tested it and it seems to work perfectly. The no-clip feature is really nice.

Have you submitted it to Trac as an enhancement?

Best regards,
Juan

Avatar
Ultimate

27 August 2009 at 8:29am Community Member, 18 Posts

Hey Juanitou,
nice to hear from you.

I noticed, that I still had some improvements to do. The problem was to get well-formed XML out of this function, because it will only return plain text. Since some special charakters like the ampersand (&) are forbidden in XML, the xml rendering of the result page will fail, if one of those chracters is part of the returned MyContextSummary.
So I did another update, that handles this problem and converts all special characters to htmlentities at the end of the function.

// New Result-function with highlighted search-strings
   // refer to: http://www.silverstripe.org/form-questions/show/262339?start=0
   function MyContextSummary($characters = 500, $string = false, $striphtml = true, $highlight = true)
      {

   if(!$string) $string = $_REQUEST['Search']; // Use the default "Search" request variable (from SearchForm)

      /*** Prepare Content ***/

      // Replace <br /> in order to get separate words

      $content = str_replace('<br />', ' ', $this->Content);

      // Decoding entities prevents XML validation error

      $content = html_entity_decode($content, ENT_COMPAT , 'UTF-8');

      // Remove HTML tags so we don't have to deal with matching tags

      $text = strip_tags($content);

      // Remove BBCode

      $pattern = '|[[\/\!]*?[^\[\]]*?]|si';

      $replace = '';

      $text = preg_replace($pattern, $replace, $text);

      // Find the search string

      $position = (int) stripos($text, $string);

      // We want the search string to be in the middle of our block to give it some context

      $position = max(0, $position - ($characters / 2));

      // We don't want to start mid-word

      if($position > 0)
         {

      $position = max((int) strrpos(substr($text, 0, $position), ' '), (int) strrpos(substr($text, 0, $position), "\n"));

         }
         
      $summary = substr($text, $position, $characters);
      
      // We also don't want to end mid-word
      $offset = $characters+$position;
      if ($offset > strlen($text)-1) $offset = strlen($text)-1;
      $position = min((int) strpos($text, ' ', $offset), (int) strpos($text, "\n", $offset));
      if ($position) $summary = $summary.substr($text, $offset, $position-$offset);
          
   if($highlight)
      {
      // Setting the content that will be inserted before and after the highlighted words
      $before_content = "<span class=\"highlight\">";
      $after_content = "</span>";
      
         // We have to insert content without any html-entities in the first place
         // The following two lines should not be altered
      $before_placeholder = "%BEFORE_CONTENT%";
      $after_placeholder = "%AFTER_CONTENT%";
      
      // Save the different search values into an array
      $stringPieces = explode(' ', $string);
      
      foreach($stringPieces as $stringPiece)
         {
         //Setting the start from where $stringPiece will be searched
         $offset = 0;
         // Recursively add before_placeholder and after_placeholder around all found $stringPiece

            while($position = stripos($summary, $stringPiece, $offset))
               {
               $summary =
                  substr($summary, 0, $position)
                  .$before_placeholder
                  .substr($summary, $position, strlen($stringPiece))
                  .$after_placeholder
                  .substr($summary, $position + strlen($stringPiece), strlen($summary)-($position+1));
               
               $offset = $position + strlen($before_placeholder) + strlen($after_placeholder);
            }
         }
      
      
      }
      
      // Re-add all htmlentities in order to get well-formed XML
      $summary = htmlentities($summary, ENT_COMPAT , 'UTF-8');
      
      if ($highlight)
         {
         // Replacing the placeholders with the set content
         $summary = str_replace($before_placeholder , $before_content , $summary);
         $summary = str_replace($after_placeholder , $after_content , $summary);
         }
      
      return trim($summary);
      }

Avatar
Juanitou

27 August 2009 at 8:20pm Community Member, 323 Posts

Bravo! You should submit it to Trac. Thanks again.

Avatar
Stijn

12 October 2009 at 6:34am (Last edited: 12 October 2009 6:35am), Community Member, 46 Posts

hmm, did doesnt work for me :-(

When I use this:

      <% control Results %>
         <a class="searchResultHeader" href="$Link">
            <% if MenuTitle %>
               <h3>$MenuTitle</h3>
            <% else %>
               <h3>$Title</h3>
            <% end_if %>
         </a>
         <p><% if Content %> &hellip; $MyContextSummary(375); &hellip;<% end_if %></p>
         <a class="read-more" href="$Link" title="<% _t('Globals.READ_MORE_ON') %> &quot;{$Title}&quot;"><% _t('Globals.READ_MORE_ON') %> &quot;{$Title}&quot;</a>
         <% if last %><% else %><div class="seperator"></div><% end_if %>
      <% end_control %>

Avatar
Juanitou

13 October 2009 at 2:51am Community Member, 323 Posts

Hi! What do you mean? What’s the error? Did you put this code in Page_results.ss? Apart from a semi-colon after $MyContextSummary(375); that should not be there, I can’t see where the problem can be.

Avatar
Stijn

13 October 2009 at 3:10am Community Member, 46 Posts

Get no erros, but nothing is showing :(

I've added the function the my Page.php

And that code to my page_results.ss

Avatar
schellmax

22 October 2009 at 6:18am Community Member, 126 Posts

like this solution, works for me
@Stijn: you might have made the same mistake as me initially: don't add the MyContextSummary function to the controller (Page_Controller) class but to the model (Page) class.

Avatar
JuLo

29 November 2009 at 7:38pm Community Member, 37 Posts

That's a piece of art Ultimate!
Exactly what I was (poorly) trying to do.
Thanks.

But I still seem to have the problem you originally had where the case (uppercase or lowecase etc.) of the word found in the text is replaced by the case of the query word.

I think I understand that you extract the word directly from the text with "substr($summary, $position, strlen($stringPiece))" but mine is still replaced by the Search String.

Some more help please?
Or anyone else?

Thanks