Completed
Pull Request — master (#628)
by Richard
19:02 queued 04:58
created

Highlighter   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Test Coverage

Coverage 78.13%

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 75
rs 10
c 0
b 0
f 0
ccs 25
cts 32
cp 0.7813
wmc 7

2 Methods

Rating   Name   Duplication   Size   Complexity  
A apply() 0 11 3
A splitOnTag() 0 32 4
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\Highlighter
18
 * @package   Xmf
19
 * @author    Richard Griffith <[email protected]>
20
 * @copyright 2011-2018 XOOPS Project (https://xoops.org)
21
 * @license   GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
22
 * @link      https://xoops.org
23
 */
24
class Highlighter
25
{
26
    /**
27
     * mbstring encoding
28
     */
29
    const ENCODING = 'UTF-8';
30
31
    /**
32
     * Apply highlight to words in body text
33
     *
34
     * Surround occurrences of words in body with pre in front and post
35
     * behind. Considers only occurrences of words outside of HTML tags.
36
     *
37
     * @param string|string[] $words words to highlight
38
     * @param string          $body  body of html text to highlight
39
     * @param string          $pre   string to begin a highlight
40
     * @param string          $post  string to end a highlight
41
     *
42
     * @return string highlighted body
43
     */
44 1
    public static function apply($words, $body, $pre = '<mark>', $post = '</mark>')
45
    {
46 1
        if (!is_array($words)) {
47 1
            $words = preg_replace('/[\s]+/', ' ', $words);
48 1
            $words = explode(' ', $words);
49
        }
50 1
        foreach ($words as $word) {
51 1
            $body = static::splitOnTag($word, $body, $pre, $post);
52
        }
53
54 1
        return $body;
55
    }
56
57
    /**
58
     * find needle in between html tags and add highlighting
59
     *
60
     * @param string $needle   string to find
61
     * @param string $haystack html text to find needle in
62
     * @param string $pre      insert before needle
63
     * @param string $post     insert after needle
64
     *
65
     * @return mixed return from preg_replace_callback()
66
     */
67 1
    protected static function splitOnTag($needle, $haystack, $pre, $post)
68
    {
69 1
        $encoding = static::ENCODING;
70 1
        return preg_replace_callback(
71 1
            '#((?:(?!<[/a-z]).)*)([^>]*>|$)#si',
72
            function ($capture) use ($needle, $pre, $post, $encoding) {
73 1
                $haystack = $capture[1];
74 1
                if (function_exists('mb_substr')) {
75 1
                    $p1 = mb_stripos($haystack, $needle, 0, $encoding);
76 1
                    $l1 = mb_strlen($needle, $encoding);
77 1
                    $ret = '';
78 1
                    while ($p1 !== false) {
79 1
                        $ret .= mb_substr($haystack, 0, $p1, $encoding) . $pre
80 1
                            . mb_substr($haystack, $p1, $l1, $encoding) . $post;
81 1
                        $haystack = mb_substr($haystack, $p1 + $l1, mb_strlen($haystack), $encoding);
82 1
                        $p1 = mb_stripos($haystack, $needle, 0, $encoding);
83
                    }
84
                } else {
85
                    $p1 = stripos($haystack, $needle);
86
                    $l1 = strlen($needle);
87
                    $ret = '';
88
                    while ($p1 !== false) {
89
                        $ret .= substr($haystack, 0, $p1) . $pre . substr($haystack, $p1, $l1) . $post;
90
                        $haystack = substr($haystack, $p1 + $l1);
91
                        $p1 = stripos($haystack, $needle);
92
                    }
93
                }
94 1
                $ret .= $haystack . $capture[2];
95
96 1
                return $ret;
97 1
            },
98 1
            $haystack
99
        );
100
    }
101
}
102