1: <?php
2: /*
3: You may not change or alter any portion of this comment or credits
4: of supporting developers from this source code or any supporting source code
5: which is considered copyrighted (c) material of the original comment or credit authors.
6:
7: This program is distributed in the hope that it will be useful,
8: but WITHOUT ANY WARRANTY; without even the implied warranty of
9: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10: */
11:
12: namespace Xmf;
13:
14: /**
15: * Highlighter
16: *
17: * @category Xmf\Module\Highlighter
18: * @package Xmf
19: * @author Richard Griffith <richard@geekwright.com>
20: * @copyright 2011-2013 XOOPS Project (http://xoops.org)
21: * @license GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
22: * @version Release: 1.0
23: * @link http://xoops.org
24: * @since 1.0
25: */
26: class Highlighter
27: {
28: /**
29: * Apply highlight to words in body text
30: *
31: * Surround occurances of words in body with pre in front and post
32: * behing. Considers only occurances of words outside of HTML tags.
33: *
34: * @param mixed $words words to highlight
35: * @param string $body body of html text to highlight
36: * @param string $pre string to begin a highlight
37: * @param string $post string to end a highlight
38: *
39: * @return string highlighted body
40: */
41: public static function apply($words, $body, $pre = '<strong>', $post = '</strong>')
42: {
43: if (!is_array($words)) {
44: $words=str_replace(' ', ' ', $words);
45: $words=explode(' ', $words);
46: }
47: foreach ($words as $word) {
48: $body=Highlighter::splitOnTag($word, $body, $pre, $post);
49: }
50:
51: return $body;
52: }
53:
54: /**
55: * find needle in between html tags and add highlighting
56: *
57: * @param string $needle string to find
58: * @param string $haystack html text to find needle in
59: * @param string $pre insert before needle
60: * @param string $post insert after needle
61: *
62: * @return string
63: */
64: private static function splitOnTag($needle, $haystack, $pre, $post)
65: {
66: return preg_replace_callback(
67: '#((?:(?!<[/a-z]).)*)([^>]*>|$)#si',
68: function ($capture) use ($needle, $pre, $post) {
69: $haystack=$capture[1];
70: $p1=mb_stripos($haystack, $needle);
71: $l1=mb_strlen($needle);
72: $ret='';
73: while ($p1!==false) {
74: $ret .= mb_substr($haystack, 0, $p1) . $pre
75: . mb_substr($haystack, $p1, $l1) . $post;
76: $haystack=mb_substr($haystack, $p1+$l1);
77: $p1=mb_stripos($haystack, $needle);
78: }
79: $ret.=$haystack.$capture[2];
80:
81: return $ret;
82:
83: },
84: $haystack
85: );
86: }
87: }
88: