16
16
*/
17
17
class HtmlFilter implements Filter
18
18
{
19
+ /**
20
+ * Attribute name context.
21
+ */
22
+ const CTX_ATTR_NAME = 'attr_name ' ;
23
+
24
+ /**
25
+ * Attribute value context.
26
+ */
27
+ const CTX_ATTR_VALUE = 'attr_value ' ;
28
+
29
+ /**
30
+ * Tag attributes context.
31
+ */
32
+ const CTX_TAG_ATTRS = 'tag_attrs ' ;
33
+
34
+ /**
35
+ * Tag content context.
36
+ */
37
+ const CTX_TAG_CONTENT = 'tag_content ' ;
38
+
39
+ /**
40
+ * Tag name context.
41
+ */
42
+ const CTX_TAG_NAME = 'tag_name ' ;
43
+
19
44
/**
20
45
* Ignore content of these tags.
21
46
*
@@ -60,24 +85,32 @@ public function filter($string)
60
85
// Current/last attribute name
61
86
$ attrName = null ;
62
87
// Current context
63
- $ context = null ;
88
+ $ context = self :: CTX_TAG_CONTENT ;
64
89
// Expected context
65
90
$ expecting = null ;
66
91
92
+ // By default tag content treated as text.
93
+ $ ignoreTagContent = false ;
94
+ // By default attribute values NOT treated as text.
95
+ $ ignoreAttrValue = true ;
96
+
67
97
$ length = mb_strlen ($ string );
68
98
for ($ i = 0 ; $ i < $ length ; $ i ++) {
69
99
$ char = mb_substr ($ string , $ i , 1 );
70
100
switch (true ) {
71
101
case '< ' === $ char :
72
- $ context = ' tag_name ' ;
102
+ $ context = self :: CTX_TAG_NAME ;
73
103
$ tagName = null ;
74
104
$ char = ' ' ;
75
105
break ;
76
106
77
107
case '> ' === $ char :
78
- $ context = 'tag_name ' === $ context && $ this ->isIgnoredTag ($ tagName )
79
- ? 'ignored_tag_content '
80
- : null ;
108
+ if ($ this ->isIgnoredTag ($ tagName )) {
109
+ $ ignoreTagContent = true ;
110
+ } elseif ('/ ' === $ tagName [0 ]) {
111
+ $ ignoreTagContent = false ; // Restore to default state.
112
+ }
113
+ $ context = self ::CTX_TAG_CONTENT ;
81
114
$ expecting = null ;
82
115
$ char = ' ' ;
83
116
break ;
@@ -86,64 +119,67 @@ public function filter($string)
86
119
case "\n" === $ char :
87
120
case "\t" === $ char :
88
121
switch ($ context ) {
89
- case ' tag_name ' :
90
- $ context = ' tag_attrs ' ;
122
+ case self :: CTX_TAG_NAME :
123
+ $ context = self :: CTX_TAG_ATTRS ;
91
124
break ;
92
125
93
- case ' attr_name ' :
94
- $ context = ' tag_attrs ' ;
126
+ case self :: CTX_ATTR_NAME :
127
+ $ context = self :: CTX_TAG_ATTRS ;
95
128
break ;
96
129
}
97
130
break ;
98
131
99
- case '= ' === $ char && ('attr_name ' === $ context || 'tag_attrs ' === $ context ):
100
- $ expecting = 'attr_value ' ;
132
+ case '= ' === $ char
133
+ && (self ::CTX_ATTR_NAME === $ context || self ::CTX_TAG_ATTRS === $ context ):
134
+ $ expecting = self ::CTX_ATTR_VALUE ;
101
135
$ char = ' ' ;
102
136
break ;
103
137
104
138
case '" ' === $ char :
105
139
case "' " === $ char :
106
140
switch (true ) {
107
- case 'attr_value ' === $ expecting :
108
- $ context = 'attr_value ' ;
109
- if (in_array (strtolower ($ attrName ), self ::$ textAttrs , true )) {
110
- $ context = 'attr_text ' ;
111
- }
141
+ case self ::CTX_ATTR_VALUE === $ expecting :
142
+ $ context = self ::CTX_ATTR_VALUE ;
143
+ $ ignoreAttrValue
144
+ = !in_array (strtolower ($ attrName ), self ::$ textAttrs , true );
112
145
$ expecting = null ;
113
146
$ char = ' ' ;
114
147
break ;
115
148
116
- case 'attr_value ' === $ context :
117
- case 'attr_text ' === $ context :
118
- $ context = 'tag_attrs ' ;
149
+ case self ::CTX_ATTR_VALUE === $ context :
150
+ $ context = self ::CTX_TAG_ATTRS ;
119
151
$ char = ' ' ;
120
152
break ;
121
153
}
122
154
break ;
123
155
124
156
default :
125
157
switch ($ context ) {
126
- case ' tag_name ' :
158
+ case self :: CTX_TAG_NAME :
127
159
$ tagName .= $ char ;
128
160
$ char = ' ' ;
129
161
break ;
130
162
131
163
/** @noinspection PhpMissingBreakStatementInspection */
132
- case ' tag_attrs ' :
133
- $ context = ' attr_name ' ;
164
+ case self :: CTX_TAG_ATTRS :
165
+ $ context = self :: CTX_ATTR_NAME ;
134
166
$ attrName = null ;
135
167
// no break needed
136
- case ' attr_name ' :
168
+ case self :: CTX_ATTR_NAME :
137
169
$ attrName .= $ char ;
138
170
$ char = ' ' ;
139
171
break ;
140
172
141
- case 'attr_value ' :
142
- $ char = ' ' ;
173
+ case self ::CTX_ATTR_VALUE :
174
+ if ($ ignoreAttrValue ) {
175
+ $ char = ' ' ;
176
+ }
143
177
break ;
144
178
145
- case 'ignored_tag_content ' :
146
- $ char = ' ' ;
179
+ case self ::CTX_TAG_CONTENT :
180
+ if ($ ignoreTagContent ) {
181
+ $ char = ' ' ;
182
+ }
147
183
break ;
148
184
}
149
185
}
0 commit comments