@@ -35,12 +35,28 @@ class ProperEscapingFunctionSniff extends Sniff {
35
35
'esc_html_e ' => 'html ' ,
36
36
];
37
37
38
+ /**
39
+ * List of tokens we can skip.
40
+ *
41
+ * @var array
42
+ */
43
+ private $ echo_or_concat_tokens =
44
+ [
45
+ T_ECHO => T_ECHO ,
46
+ T_OPEN_TAG => T_OPEN_TAG ,
47
+ T_OPEN_TAG_WITH_ECHO => T_OPEN_TAG_WITH_ECHO ,
48
+ T_STRING_CONCAT => T_STRING_CONCAT ,
49
+ T_COMMA => T_COMMA ,
50
+ ];
51
+
38
52
/**
39
53
* Returns an array of tokens this test wants to listen for.
40
54
*
41
55
* @return array
42
56
*/
43
57
public function register () {
58
+ $ this ->echo_or_concat_tokens += Tokens::$ emptyTokens ;
59
+
44
60
return [ T_STRING ];
45
61
}
46
62
@@ -59,36 +75,17 @@ public function process_token( $stackPtr ) {
59
75
60
76
$ function_name = $ this ->tokens [ $ stackPtr ]['content ' ];
61
77
62
- $ data = [ $ function_name ];
63
-
64
- $ echo_or_concat_or_html = $ this ->phpcsFile ->findPrevious ( Tokens::$ emptyTokens , $ stackPtr - 1 , null , true );
78
+ $ html = $ this ->phpcsFile ->findPrevious ( $ this ->echo_or_concat_tokens , $ stackPtr - 1 , null , true );
65
79
66
- if ( $ this ->tokens [ $ echo_or_concat_or_html ]['code ' ] === T_ECHO ) {
67
- // Very likely inline HTML with <?php tag.
68
- $ php_open = $ this ->phpcsFile ->findPrevious ( Tokens::$ emptyTokens , $ echo_or_concat_or_html - 1 , null , true );
69
-
70
- if ( $ this ->tokens [ $ php_open ]['code ' ] !== T_OPEN_TAG ) {
71
- return ;
72
- }
80
+ $ data = [ $ function_name ];
73
81
74
- $ html = $ this ->phpcsFile ->findPrevious ( Tokens::$ emptyTokens , $ php_open - 1 , null , true );
82
+ if ( isset ( Tokens::$ textStringTokens [ $ this ->tokens [ $ html ]['code ' ] ] ) === false ) { // Use $textStringTokens b/c heredoc and nowdoc tokens shouldn't be matched anyways.
83
+ return ;
84
+ }
75
85
76
- if ( $ this ->tokens [ $ html ]['code ' ] === T_INLINE_HTML && $ this ->is_outside_html_attr_context ( $ function_name , $ this ->tokens [ $ html ]['content ' ] ) ) {
77
- $ message = 'Wrong escaping function, please do not use `%s()` in a context outside of HTML attributes. ' ;
78
- $ this ->phpcsFile ->addError ( $ message , $ html , 'notAttrEscAttr ' , $ data );
79
- return ;
80
- }
81
- } elseif ( $ this ->tokens [ $ echo_or_concat_or_html ]['code ' ] === T_STRING_CONCAT || $ this ->tokens [ $ echo_or_concat_or_html ]['code ' ] === T_COMMA ) {
82
- // Very likely string concatenation mixing strings and functions/variables.
83
- $ html = $ this ->phpcsFile ->findPrevious ( Tokens::$ emptyTokens , $ echo_or_concat_or_html - 1 , null , true );
84
-
85
- if ( $ this ->tokens [ $ html ]['code ' ] === T_CONSTANT_ENCAPSED_STRING && $ this ->is_outside_html_attr_context ( $ function_name , trim ( $ this ->tokens [ $ html ]['content ' ], '" \'' ) ) ) {
86
- $ message = 'Wrong escaping function, please do not use `%s()` in a context outside of HTML attributes. ' ;
87
- $ this ->phpcsFile ->addError ( $ message , $ html , 'notAttrEscAttr ' , $ data );
88
- return ;
89
- }
90
- } else {
91
- // Neither - bailing.
86
+ if ( $ this ->is_outside_html_attr_context ( $ function_name , Sniff::strip_quotes ( $ this ->tokens [ $ html ]['content ' ] ) ) ) {
87
+ $ message = 'Wrong escaping function, please do not use `%s()` in a context outside of HTML attributes. ' ;
88
+ $ this ->phpcsFile ->addError ( $ message , $ html , 'notAttrEscAttr ' , $ data );
92
89
return ;
93
90
}
94
91
@@ -97,6 +94,7 @@ public function process_token( $stackPtr ) {
97
94
$ this ->phpcsFile ->addError ( $ message , $ stackPtr , 'hrefSrcEscUrl ' , $ data );
98
95
return ;
99
96
}
97
+
100
98
if ( $ function_name === 'esc_html ' && $ this ->is_html_attr ( $ this ->tokens [ $ html ]['content ' ] ) ) {
101
99
$ message = 'Wrong escaping function. HTML attributes should be escaped by `esc_attr()`, not by `%s()`. ' ;
102
100
$ this ->phpcsFile ->addError ( $ message , $ stackPtr , 'htmlAttrNotByEscHTML ' , $ data );
@@ -167,12 +165,12 @@ public function endswith( $haystack, $needle ) {
167
165
/**
168
166
* Tests whether provided string ends with closing HTML tag in an attribute context.
169
167
*
170
- * @param string $function_name Escaping attribute function name .
171
- * @param string $content Haystack in which we look for open HTML tag.
168
+ * @param string $function_name Name of function found .
169
+ * @param string $content Haystack in which we look for open HTML tag.
172
170
*
173
171
* @return bool True if string ends with open HTML tag.
174
172
*/
175
173
public function is_outside_html_attr_context ( $ function_name , $ content ) {
176
- return $ this ->escaping_functions [ $ function_name ] === 'attr ' && substr ( $ content , -1 ) === '> ' ;
174
+ return $ this ->escaping_functions [ $ function_name ] === 'attr ' && substr ( trim ( $ content ) , -1 ) === '> ' ;
177
175
}
178
176
}
0 commit comments