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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Form Questions /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Highlight search query in results page?


Go to End


25 Posts   12939 Views

Avatar
Juanitou

Community Member, 323 Posts

24 August 2009 at 10:06pm

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

Community Member, 18 Posts

27 August 2009 at 8:29am

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

Community Member, 323 Posts

27 August 2009 at 8:20pm

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

Avatar
Stijn

Community Member, 46 Posts

12 October 2009 at 6:34am

Edited: 12/10/2009 6:35am

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

Community Member, 323 Posts

13 October 2009 at 2:51am

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

Community Member, 46 Posts

13 October 2009 at 3:10am

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

Community Member, 126 Posts

22 October 2009 at 6:18am

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

Community Member, 37 Posts

29 November 2009 at 7:38pm

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