Completed
Push — master ( 51fce5...f0a1b6 )
by Josh
29:12 queued 02:58
created

Helper::isAllowed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2017 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Plugins\Censor;
9
10
class Helper
11
{
12
	/**
13
	* @var string Regexp matching whitelisted words
14
	*/
15
	public $allowed;
16
17
	/**
18
	* @var string Name of attribute used for the replacement
19
	*/
20
	public $attrName = 'with';
21
22
	/**
23
	* @var string Default string used to replace censored words
24
	*/
25
	public $defaultReplacement = '****';
26
27
	/**
28
	* @var string Regexp matching blacklisted words in plain text
29
	*/
30
	public $regexp = '/(?!)/';
31
32
	/**
33
	* @var string Regexp matching blacklisted words in HTML
34
	*/
35
	public $regexpHtml = '/(?!)/';
36
37
	/**
38
	* @var array Array of [regexp => replacement]
39
	*/
40
	public $replacements = [];
41
42
	/**
43
	* @var string Name of the tag used to mark censored words
44
	*/
45
	public $tagName = 'CENSOR';
46
47
	/**
48
	* Constructor
49
	*
50
	* @param  array $config Helper's config
51
	*/
52 20
	public function __construct(array $config)
53
	{
54 20
		foreach ($config as $k => $v)
55
		{
56 20
			$this->$k = $v;
57 20
		}
58 20
	}
59
60
	/**
61
	* Censor text nodes inside of HTML code
62
	*
63
	* NOTE: will only recognize attributes that are enclosed in double quotes
64
	*
65
	* @param  string $html             Original HTML
66
	* @param  bool   $censorAttributes Whether to censor the content of attributes
67
	* @return string                   Censored HTML
68
	*/
69 14
	public function censorHtml($html, $censorAttributes = false)
70
	{
71 14
		$attributesExpr = '';
72
		if ($censorAttributes)
73 14
		{
74 2
			$attributesExpr = '|[^<">]*+(?=<|$|"(?> [-\\w]+="[^"]*+")*+\\/?>)';
75 2
		}
76
77
		// Modify the original regexp so that it only matches text nodes and optionally attribute
78
		// values
79 14
		$delim  = $this->regexpHtml[0];
80 14
		$pos    = strrpos($this->regexpHtml, $delim);
81
		$regexp = $delim
82
		        . '(?<!&#)(?<!&)'
83 14
		        . substr($this->regexpHtml, 1, $pos - 1)
84 14
		        . '(?=[^<>]*+(?=<|$)' . $attributesExpr . ')'
85 14
		        . substr($this->regexpHtml, $pos);
86
87 14
		return preg_replace_callback(
88 14
			$regexp,
89
			function ($m)
90
			{
91 13
				return htmlspecialchars($this->getReplacement($m[0]), ENT_QUOTES);
92 14
			},
93
			$html
94 14
		);
95
	}
96
97
	/**
98
	* Censor given plain text
99
	*
100
	* @param  string $text Original text
101
	* @return string       Censored text
102
	*/
103 3
	public function censorText($text)
104
	{
105 3
		return preg_replace_callback(
106 3
			$this->regexp,
107 3
			function ($m)
108
			{
109 3
				return $this->getReplacement($m[0]);
110 3
			},
111
			$text
112 3
		);
113
	}
114
115
	/**
116
	* Test whether given word is censored
117
	*
118
	* @param  string $word
119
	* @return bool
120
	*/
121 3
	public function isCensored($word)
122
	{
123 3
		return (preg_match($this->regexp, $word) && !$this->isAllowed($word));
124
	}
125
126
	/**
127
	* Build and return the censor tag that matches given word
128
	*
129
	* @param  string $word Word to censor
130
	* @return string       Censor tag, complete with its replacement attribute
131
	*/
132
	protected function buildTag($word)
133
	{
134
		$startTag = '<' . $this->tagName;
135
		$replacement = $this->getReplacement($word);
136
		if ($replacement !== $this->defaultReplacement)
137
		{
138
			$startTag .= ' ' . $this->attrName . '="' . htmlspecialchars($replacement, ENT_COMPAT) . '"';
139
		}
140
141
		return $startTag . '>' . $word . '</' . $this->tagName . '>';
142
	}
143
144
	/**
145
	* Get the replacement for given word
146
	*
147
	* @param  string $word Original word
148
	* @return string       Replacement if the word is censored, or the original word otherwise
149
	*/
150 16
	protected function getReplacement($word)
151
	{
152 16
		if ($this->isAllowed($word))
153 16
		{
154 2
			return $word;
155
		}
156
157 16
		foreach ($this->replacements as list($regexp, $replacement))
158
		{
159 5
			if (preg_match($regexp, $word))
160 5
			{
161 5
				return $replacement;
162
			}
163 11
		}
164
165 11
		return $this->defaultReplacement;
166
	}
167
168
	/**
169
	* Test whether given word is allowed (whitelisted)
170
	*
171
	* @param  string $word
172
	* @return bool
173
	*/
174 18
	protected function isAllowed($word)
175
	{
176 18
		return (isset($this->allowed) && preg_match($this->allowed, $word));
177
	}
178
}