<?php
/* * Copyright (c) 2009 Nguyen Duc Thuan <me@ndthuan.com> * All rights reserved. */
/** * Text highlighter without affecting HTML tags. This class supports highlighting * string in the double quotes of keyword for compatibility with some search methods such as * MySQL Full-text search, Google, Yahoo... * * Sample usage: * - Method 1: * $highlightedString = Fete_Util_Text_Highlighter::createInstance('<b>', '</b>')->highlight('PHP rules', 'rules'); * - Method 2: * $highlighter = new Fete_Util_Text_Highlighter(); * $highlightedString = $highlighter->setBeforeMatch('<b>') * ->setAfterMatch('</b>') * ->highlight('PHP rules the world', '"PHP rules"'); * * @author Nguyen Duc Thuan <me@ndthuan.com> */ class Fete_Util_Text_Highlighter { /** * @var string */ protected $_beforeMatch = '<span style="background-color:yellow">';
/** * @var string */ protected $_afterMatch = '</span>';
/** * * @param string $beforeMatch * @param string $afterMatch */ public function __construct($beforeMatch = null, $afterMatch = null) { if (null !== $beforeMatch) { $this->_beforeMatch = $beforeMatch; }
if (null !== $afterMatch) { $this->_afterMatch = $afterMatch; } }
/** * * @param string $beforeMatch * @param string $afterMatch * @return Fete_Util_Text_Highlighter */ static public function createInstance($beforeMatch = null, $afterMatch = null) { return new self($beforeMatch, $afterMatch); }
/** * * @param string $beforeMatch * @return Fete_Util_Text_Highlighter */ public function &setBeforeMatch($beforeMatch) { $this->_beforeMatch = $beforeMatch; return $this; }
/** * * @param string $afterMatch * @return Fete_Util_Text_Highlighter */ public function &setAfterMatch($afterMatch) { $this->_afterMatch = $afterMatch; return $this; }
/** * * @param string $text * @param string $keyword * @return string highlighted string */ public function highlight($text, $keyword) { $output = '';
$words = array();
preg_match_all('#(?:"([^"]+)"|(?:[^\s\+\-"\(\)><~\*\'\|\\`\!@\#\$%^&_=\[\]\{\}:;,\./\?]+))#si', $keyword, $matches, PREG_SET_ORDER);
foreach ($matches as $match) { if (2 === count($match)) { $words[] = $match[1]; } else { $words[] = $match[0]; } }
$words = implode('|', $words);
$textParts = preg_split('#(<script[^>]*>.*?</script>|<style[^>]*>.*?</style>|<.+?>)#si', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($textParts as $byHtmlPart) { if (!empty($byHtmlPart) && $byHtmlPart{0} != '<') { $byHtmlPart = preg_replace('#(' . $words . ')#si', $this->_beforeMatch . '\1' . $this->_afterMatch, $byHtmlPart); }
$output .= $byHtmlPart; }
return $output; } }
|