Completed
Push — master ( 0788a2...f57697 )
by Josh
12:54
created

Helper   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 86.36%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 0
dl 0
loc 169
ccs 38
cts 44
cp 0.8636
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A isCensored() 0 4 2
A censorText() 0 11 1
A isAllowed() 0 4 2
A __construct() 0 7 2
B censorHtml() 0 27 2
A buildTag() 0 11 2
A getReplacement() 0 17 4
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 21
	public function __construct(array $config)
53
	{
54 21
		foreach ($config as $k => $v)
55
		{
56 21
			$this->$k = $v;
57
		}
58 21
	}
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 15
	public function censorHtml($html, $censorAttributes = false)
70
	{
71 15
		$attributesExpr = '';
72 15
		if ($censorAttributes)
73
		{
74 2
			$attributesExpr = '|[^<">]*+(?=<|$|"(?> [-\\w]+="[^"]*+")*+\\/?>)';
75
		}
76
77
		// Modify the original regexp so that it only matches text nodes and optionally attribute
78
		// values
79 15
		$delim  = $this->regexpHtml[0];
80 15
		$pos    = strrpos($this->regexpHtml, $delim);
81
		$regexp = $delim
82 15
		        . '(?<!&#)(?<!&)'
83 15
		        . substr($this->regexpHtml, 1, $pos - 1)
84 15
		        . '(?=[^<>]*+(?=<|$)' . $attributesExpr . ')'
85 15
		        . substr($this->regexpHtml, $pos);
86
87 15
		return preg_replace_callback(
88 15
			$regexp,
89 15
			function ($m)
90
			{
91 14
				return htmlspecialchars($this->getReplacement(html_entity_decode($m[0], ENT_QUOTES, 'UTF-8')), ENT_QUOTES);
92 15
			},
93 15
			$html
94
		);
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 3
			$text
112
		);
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 17
	protected function getReplacement($word)
151
	{
152 17
		if ($this->isAllowed($word))
153
		{
154 2
			return $word;
155
		}
156
157 17
		foreach ($this->replacements as list($regexp, $replacement))
158
		{
159 6
			if (preg_match($regexp, $word))
160
			{
161 6
				return $replacement;
162
			}
163
		}
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 19
	protected function isAllowed($word)
175
	{
176 19
		return (isset($this->allowed) && preg_match($this->allowed, $word));
177
	}
178
}