Skip to content

Commit c6e62ce

Browse files
committed
Sniff to detect script tags that should be either enqueued or generated by the new script templating functions: wp_get_script_tag() and wp_get_inline_script_tag().
1 parent 07abb48 commit c6e62ce

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

WordPress-Extra/ruleset.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
https://github.com/WordPress/WordPress-Coding-Standards/issues/35 -->
100100
<rule ref="WordPress.WP.EnqueuedResources"/>
101101

102+
<!-- Non enqueable inline scripts should be generated using wp_get_inline_script_tag().
103+
https://core.trac.wordpress.org/ticket/39941 -->
104+
<rule ref="WordPress.WP.TemplatedInlineScripts"/>
105+
102106
<!-- Warn against overriding WP global variables.
103107
https://github.com/WordPress/WordPress-Coding-Standards/issues/26 -->
104108
<rule ref="WordPress.WP.GlobalVariablesOverride"/>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/**
3+
* WordPress Coding Standard.
4+
*
5+
* @package WPCS\WordPressCodingStandards
6+
* @link https://github.com/WordPress/WordPress-Coding-Standards
7+
* @license https://opensource.org/licenses/MIT MIT
8+
*/
9+
10+
namespace WordPressCS\WordPress\Sniffs\WP;
11+
12+
use PHP_CodeSniffer\Exceptions\RuntimeException;
13+
use PHP_CodeSniffer\Util\Tokens;
14+
use PHPCSUtils\Tokens\Collections;
15+
use PHPCSUtils\Utils\TextStrings;
16+
use WordPressCS\WordPress\Sniff;
17+
18+
/**
19+
* Makes sure inline scripts and scripts are generated using either {@see wp_get_script_tag()} or {@see wp_get_inline_script_tag()}.
20+
*
21+
* @package WPCS\WordPressCodingStandards
22+
* @since 3.0.0
23+
*/
24+
class TemplatedInlineScriptsSniff extends Sniff {
25+
26+
/**
27+
* Returns an array of tokens this test wants to listen for.
28+
*
29+
* @return array
30+
*/
31+
public function register() {
32+
$targets = Collections::$textStingStartTokens;
33+
$targets[] = \T_INLINE_HTML;
34+
35+
return $targets;
36+
}
37+
38+
/**
39+
* Processes this test, when one of its tokens is encountered.
40+
*
41+
* @param int $stackPtr The position of the current token in the stack.
42+
*
43+
* @return void
44+
*/
45+
public function process_token( $stackPtr ) {
46+
47+
$content = $this->tokens[ $stackPtr ]['content'];
48+
if ( \T_INLINE_HTML !== $this->tokens[ $stackPtr ]['code'] ) {
49+
try {
50+
$content = TextStrings::getCompleteTextString( $this->phpcsFile, $stackPtr );
51+
} catch ( RuntimeException $e ) {
52+
// Not the first token in a multi-line text string. Any issues will already have been reported.
53+
return;
54+
}
55+
}
56+
57+
if ( preg_match_all( '#<script\b(?![^>]*\btext\/html\b)(?![^>]*\btext\/template\b)(?![^>]*\bapplication\/json\b)(?![^>]*\bsrc=\b)[^>]*>#', $content, $matches, PREG_OFFSET_CAPTURE ) > 0 ) {
58+
foreach ( $matches[0] as $match ) {
59+
$this->phpcsFile->addError(
60+
'If the current script is related to an enqued script, it should be added to the queue with wp_add_inline_script(), otherwise it should be generated by wp_get_inline_script().',
61+
$this->find_token_in_multiline_string( $stackPtr, $content, $match[1] ),
62+
'NonTemplatedInlineScript'
63+
);
64+
}
65+
}
66+
}
67+
68+
/**
69+
* Find the exact token on which the error should be reported for multi-line strings.
70+
*
71+
* @param int $stackPtr The position of the current token in the stack.
72+
* @param string $content The complete, potentially multi-line, text string.
73+
* @param int $match_offset The offset within the content at which the match was found.
74+
*
75+
* @return int The stack pointer to the token containing the start of the match.
76+
*/
77+
private function find_token_in_multiline_string( $stackPtr, $content, $match_offset ) {
78+
$newline_count = 0;
79+
if ( $match_offset > 0 ) {
80+
$newline_count = substr_count( $content, "\n", 0, $match_offset );
81+
}
82+
83+
// Account for heredoc/nowdoc text starting at the token *after* the opener.
84+
if ( isset( Tokens::$heredocTokens[ $this->tokens[ $stackPtr ]['code'] ] ) === true ) {
85+
++$newline_count;
86+
}
87+
88+
return ( $stackPtr + $newline_count );
89+
}
90+
91+
}

0 commit comments

Comments
 (0)