-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathRestrictedConstantsSniff.php
More file actions
141 lines (123 loc) · 4.56 KB
/
RestrictedConstantsSniff.php
File metadata and controls
141 lines (123 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?php
/**
* WordPressVIPMinimum Coding Standard.
*
* @package VIPCS\WordPressVIPMinimum
* @link https://github.com/Automattic/VIP-Coding-Standards
* @license https://opensource.org/license/gpl-2-0 GPL-2.0
*/
namespace WordPressVIPMinimum\Sniffs\Constants;
use PHP_CodeSniffer\Util\Tokens;
use PHPCSUtils\Utils\TextStrings;
use WordPressVIPMinimum\Sniffs\Sniff;
/**
* Restricts usage of some constants.
*/
class RestrictedConstantsSniff extends Sniff {
/**
* List of restricted constant names.
*
* @var array<string>
*/
public $restrictedConstantNames = [
'A8C_PROXIED_REQUEST',
];
/**
* List of restricted constant declarations.
*
* @var array<string>
*/
public $restrictedConstantDeclaration = [
'JETPACK_DEV_DEBUG',
'WP_CRON_CONTROL_SECRET',
];
/**
* List of (global) constant names, which should not be referenced in userland code, nor (re-)declared.
*
* {@internal The `public` versions of these properties can't be removed until the next major,
* though a decision is still needed whether they should be removed at all.
* Also see: Automattic/VIP-Coding-Standards#234 for more context and discussion about this.}
*
* @var array<string, int> Key is the constant name, value is irrelevant.
*/
private $restrictedConstants = [];
/**
* List of (global) constants, which should not be (re-)declared, but may be referenced.
*
* {@internal The `public` versions of these properties can't be removed until the next major,
* though a decision is still needed whether they should be removed at all.
* Also see: Automattic/VIP-Coding-Standards#234 for more context and discussion about this.}
*
* @var array<string, int> Key is the constant name, value is irrelevant.
*/
private $restrictedRedeclaration = [];
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array<int|string>
*/
public function register() {
// For now, set the `private` properties based on the values of the `public` properties.
// This should be revisited when Automattic/VIP-Coding-Standards#234 gets actioned.
$this->restrictedConstants = array_flip( $this->restrictedConstantNames );
$this->restrictedRedeclaration = array_flip( $this->restrictedConstantDeclaration );
return [
T_CONSTANT_ENCAPSED_STRING,
T_STRING,
];
}
/**
* Process this test when one of its tokens is encountered
*
* @param int $stackPtr The position of the current token in the stack passed in $tokens.
*
* @return void
*/
public function process_token( $stackPtr ) {
if ( $this->tokens[ $stackPtr ]['code'] === T_STRING ) {
$constantName = $this->tokens[ $stackPtr ]['content'];
} else {
$constantName = TextStrings::stripQuotes( $this->tokens[ $stackPtr ]['content'] );
}
if ( isset( $this->restrictedConstants[ $constantName ] ) === false
&& isset( $this->restrictedRedeclaration[ $constantName ] ) === false
) {
// Not the constant we are looking for.
return;
}
if ( $this->tokens[ $stackPtr ]['code'] === T_STRING && isset( $this->restrictedConstants[ $constantName ] ) === true ) {
$message = 'Code is touching the `%s` constant. Make sure it\'s used appropriately.';
$data = [ $constantName ];
$this->phpcsFile->addWarning( $message, $stackPtr, 'UsingRestrictedConstant', $data );
return;
}
// Find the previous non-empty token.
$openBracket = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true );
if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) {
// Not a function call.
return;
}
if ( isset( $this->tokens[ $openBracket ]['parenthesis_closer'] ) === false ) {
// Not a function call.
return;
}
// Find the previous non-empty token.
$search = Tokens::$emptyTokens;
$search[] = T_BITWISE_AND;
$previous = $this->phpcsFile->findPrevious( $search, $openBracket - 1, null, true );
if ( $this->tokens[ $previous ]['code'] === T_FUNCTION ) {
// It's a function definition, not a function call.
return;
}
if ( $this->tokens[ $previous ]['code'] === T_STRING ) {
$data = [ $constantName ];
if ( $this->tokens[ $previous ]['content'] === 'define' ) {
$message = 'The definition of `%s` constant is prohibited. Please use a different name.';
$this->phpcsFile->addError( $message, $previous, 'DefiningRestrictedConstant', $data );
} elseif ( isset( $this->restrictedConstants[ $constantName ] ) === true ) {
$message = 'Code is touching the `%s` constant. Make sure it\'s used appropriately.';
$this->phpcsFile->addWarning( $message, $previous, 'UsingRestrictedConstant', $data );
}
}
}
}