', '<', '(', ')', '~', '*', '"'); protected static $_highlightTemplate = '$1'; /** * @param string $body Text with NOT converted HTML special characters * @param string $searchText Text with NOT converted HTML special characters * @return string */ public static function markSearchWords($body, $searchText) { if ('' == $searchText) { return $body; } $body = preg_replace('/\s+/', ' ', $body); $body = htmlspecialchars($body, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); $wordList = static::getWordList($searchText); foreach ($wordList as $word) { $block = static::getMarkedBlock($body, $word); if ($block !== false){ break; } } if (empty($block)){ $block = substr($body, 0, static::$_charactersBefore + static::$_charactersAfter); if (strlen($block) < strlen($body)) { $block .= '...'; } } $block = static::markSearchWord($block, $wordList); return $block; } /** * @param string $searchText Text with NOT converted HTML special characters * @return array */ public static function getWordList($searchText) { $words = explode(' ', trim(str_replace(static::$_wordSplitters, ' ', $searchText))); $words = array_unique($words); $words = array_filter($words, function ($var) { return ('' != $var); }); $compareFunction = function ($a, $b) { $aLength = strlen($a); $bLength = strlen($b); if ($aLength == $bLength) { return 0; } return ($aLength > $bLength) ? -1 : 1; }; usort($words, $compareFunction); return $words; } /** * @param string $body Text with converted HTML special characters * @param string $searchText Text with NOT converted HTML special characters * @return bool|string */ public static function getMarkedBlock($body, $searchText) { if (!empty(static::$_charactersBefore) && !empty(static::$_charactersAfter)) { $bodyLowercase = strtolower($body); $searchTextLowercase = strtolower($searchText); $searchTextStart = strpos($bodyLowercase, $searchTextLowercase); if ($searchTextStart !== false){ $blockStart = max($searchTextStart - static::$_charactersBefore, 0); if ($blockStart > 0 && false !== ($nextSpacePos = strpos($body, ' ', $blockStart))) { $blockStart = $nextSpacePos + 1; } $blockLength = $searchTextStart - $blockStart + strlen($searchText) + static::$_charactersAfter; if (strlen($body) > $blockStart + $blockLength && false !== ($nextSpacePos = strpos($body, ' ', $blockStart + $blockLength)) ) { $blockLength = $nextSpacePos - $blockStart; } $block = ($blockStart > 0 ? '...' : '') . substr($body, $blockStart, $blockLength) . ($blockLength + $blockStart < strlen($body) ? '...' : ''); } else { $block = false; } } else { $block = $body; } return $block; } /** * @param string $body Text with converted HTML special characters * @param array $words Array with words with NOT converted HTML special characters * @return mixed */ public static function markSearchWord($body, $words) { if (!is_array($words)) { $words = array($words); } $words = array_filter($words, function ($var) { return ('' != $var); }); foreach ($words as &$word) { $word = htmlspecialchars($word); $word = preg_quote($word, '/'); } $result = preg_replace( array('/\s/', '/(' . implode('|', $words) . ')/i'), array(' ', static::$_highlightTemplate), $body ); return $result; } /** * @param int $charactersBefore * @return bool */ public static function setCharactersBefore($charactersBefore) { static::$_charactersBefore = $charactersBefore; return true; } /** * @param int $charactersAfter * @return bool */ public static function setCharactersAfter($charactersAfter) { static::$_charactersAfter = $charactersAfter; return true; } /** * @param array $wordSplitters * @return bool */ public static function setWordSplitters(array $wordSplitters) { static::$_wordSplitters = $wordSplitters; return true; } /** * @param string $splitter * @return bool */ public static function addSplitter($splitter) { if (!in_array(static::$_wordSplitters, $splitter)) { static::$_wordSplitters[] = $splitter; } return true; } /** * @param string $splitter * @return bool */ public static function removeSplitter($splitter) { if (in_array(static::$_wordSplitters, $splitter)) { unset(static::$_wordSplitters[array_search($splitter, static::$_wordSplitters)]); } return true; } /** * @param string $highlightTemplate * @return bool */ public static function setHighlightTemplate($highlightTemplate) { static::$_highlightTemplate = $highlightTemplate; return true; } /** * @param array $data * @param string|array $fields * @param bool $stripTags * @return string */ public static function prepareSearchText(array $data, $fields, $stripTags = true) { $text = array(); if (!is_array($fields)) { $fields = array($fields); } foreach ($fields as $key => $field) { if (is_scalar($field)) { if (array_key_exists($field, $data)) { $value = $data[$field]; if ($stripTags) { $value = strip_tags($value); } $search = array(' ', ''', ''', '"', '»', '«', '›', '‹', '”', '“', '’', '‘'); $replace = array(' ', '\'', '\'', '"', '»', '«', '›', '‹', '”', '“', '’', '‘'); $value = str_replace($search, $replace, htmlspecialchars_decode($value, ENT_NOQUOTES)); $value = preg_replace('/[\n\r\t]+/', ' ', $value); $value = trim($value); $text[] = $value; } } else if (array_key_exists($key, $data) && is_array($data[$key])) { $text = array_merge($text, (array) static::prepareSearchText($data[$key], $field)); } } return implode(' ', $text); } }