1 | <?php |
||
36 | { |
||
37 | |||
38 | /** |
||
39 | * Variable names, that are reserved in PHP. |
||
40 | * |
||
41 | * @var array |
||
42 | */ |
||
43 | protected $phpReservedVars = array( |
||
44 | '_SERVER', |
||
45 | '_GET', |
||
46 | '_POST', |
||
47 | '_REQUEST', |
||
48 | '_SESSION', |
||
49 | '_ENV', |
||
50 | '_COOKIE', |
||
51 | '_FILES', |
||
52 | 'GLOBALS', |
||
53 | 'http_response_header', |
||
54 | 'HTTP_RAW_POST_DATA', |
||
55 | 'php_errormsg', |
||
56 | ); |
||
57 | |||
58 | /** |
||
59 | * Member variable names that break the rules, but are allowed. |
||
60 | * |
||
61 | * @var array |
||
62 | */ |
||
63 | protected $memberExceptions = array( |
||
64 | // From "kBase". |
||
65 | 'Application', |
||
66 | 'Conn', |
||
67 | |||
68 | // From "kEvent". |
||
69 | 'Name', |
||
70 | 'MasterEvent', |
||
71 | 'Prefix', |
||
72 | 'Special', |
||
73 | |||
74 | // From "kDBItem". |
||
75 | 'IDField', |
||
76 | 'TableName', |
||
77 | 'IgnoreValidation', |
||
78 | ); |
||
79 | |||
80 | |||
81 | /** |
||
82 | * Processes this test, when one of its tokens is encountered. |
||
83 | * |
||
84 | * @param File $phpcsFile The file being scanned. |
||
85 | * @param int $stackPtr The position of the current token in the |
||
86 | * stack passed in $tokens. |
||
87 | * |
||
88 | * @return void |
||
89 | */ |
||
90 | 1 | protected function processVariable(File $phpcsFile, $stackPtr) |
|
91 | { |
||
92 | 1 | $tokens = $phpcsFile->getTokens(); |
|
93 | 1 | $varName = ltrim($tokens[$stackPtr]['content'], '$'); |
|
94 | |||
95 | // If it's a php reserved var, then its ok. |
||
96 | 1 | if (in_array($varName, $this->phpReservedVars) === true) { |
|
97 | 1 | return; |
|
98 | } |
||
99 | |||
100 | 1 | $objOperator = $phpcsFile->findPrevious(array(T_WHITESPACE), ($stackPtr - 1), null, true); |
|
101 | 1 | if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON |
|
102 | 1 | || $tokens[$objOperator]['code'] === T_OBJECT_OPERATOR |
|
103 | 1 | ) { |
|
104 | // Don't validate class/object property usage, |
||
105 | // because their declaration is already validated. |
||
106 | 1 | return; |
|
107 | } |
||
108 | |||
109 | 1 | if ($this->isSnakeCaps($varName) === false) { |
|
110 | 1 | $error = 'Variable "%s" is not in valid snake caps format'; |
|
111 | 1 | $data = array($varName); |
|
112 | 1 | $phpcsFile->addError($error, $stackPtr, 'NotSnakeCaps', $data); |
|
113 | 1 | } |
|
114 | 1 | }//end processVariable() |
|
115 | |||
116 | |||
117 | /** |
||
118 | * Processes class member variables. |
||
119 | * |
||
120 | * @param File $phpcsFile The file being scanned. |
||
121 | * @param int $stackPtr The position of the current token in the |
||
122 | * stack passed in $tokens. |
||
123 | * |
||
124 | * @return void |
||
125 | */ |
||
126 | 1 | protected function processMemberVar(File $phpcsFile, $stackPtr) |
|
127 | { |
||
128 | 1 | $tokens = $phpcsFile->getTokens(); |
|
129 | |||
130 | 1 | $varName = ltrim($tokens[$stackPtr]['content'], '$'); |
|
131 | 1 | $memberProps = $phpcsFile->getMemberProperties($stackPtr); |
|
132 | |||
133 | // @codeCoverageIgnoreStart |
||
134 | if (empty($memberProps) === true) { |
||
135 | // Couldn't get any info about this variable, which |
||
136 | // generally means it is invalid or possibly has a parse |
||
137 | // error. Any errors will be reported by the core, so |
||
138 | // we can ignore it. |
||
139 | return; |
||
140 | } |
||
141 | // @codeCoverageIgnoreEnd |
||
142 | |||
143 | 1 | $classToken = $phpcsFile->findPrevious( |
|
144 | 1 | array(T_CLASS, T_INTERFACE, T_TRAIT), |
|
145 | $stackPtr |
||
146 | 1 | ); |
|
147 | 1 | $className = $phpcsFile->getDeclarationName($classToken); |
|
|
|||
148 | |||
149 | 1 | $public = ($memberProps['scope'] !== 'private'); |
|
150 | 1 | $errorData = array($className.'::'.$varName); |
|
151 | |||
152 | 1 | if ($public === true) { |
|
153 | 1 | if (substr($varName, 0, 1) === '_') { |
|
154 | 1 | $error = '%s member variable "%s" must not contain a leading underscore'; |
|
155 | $data = array( |
||
156 | 1 | ucfirst($memberProps['scope']), |
|
157 | 1 | $errorData[0], |
|
158 | 1 | ); |
|
159 | 1 | $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); |
|
160 | 1 | return; |
|
161 | } |
||
162 | 1 | } else { |
|
163 | 1 | if (substr($varName, 0, 1) !== '_') { |
|
164 | 1 | $error = 'Private member variable "%s" must contain a leading underscore'; |
|
165 | 1 | $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); |
|
166 | 1 | return; |
|
167 | } |
||
168 | } |
||
169 | |||
170 | 1 | if ($this->isCamelCaps($varName, $public) === false) { |
|
171 | 1 | $error = '%s member variable "%s" is not in valid camel caps format'; |
|
172 | $data = array( |
||
173 | 1 | ucfirst($memberProps['scope']), |
|
174 | 1 | $errorData[0], |
|
175 | 1 | ); |
|
176 | 1 | $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $data); |
|
177 | 1 | } |
|
178 | 1 | }//end processMemberVar() |
|
179 | |||
180 | |||
181 | /** |
||
182 | * Processes the variable found within a double quoted string. |
||
183 | * |
||
184 | * @param File $phpcsFile The file being scanned. |
||
185 | * @param int $stackPtr The position of the double quoted |
||
186 | * string. |
||
187 | * |
||
188 | * @return void |
||
189 | */ |
||
190 | 1 | protected function processVariableInString(File $phpcsFile, $stackPtr) |
|
191 | { |
||
192 | 1 | $tokens = $phpcsFile->getTokens(); |
|
193 | 1 | $content = $tokens[$stackPtr]['content']; |
|
194 | 1 | $variablesFound = preg_match_all( |
|
195 | 1 | '|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', |
|
196 | 1 | $content, |
|
197 | 1 | $matches, |
|
198 | 1 | PREG_SET_ORDER + PREG_OFFSET_CAPTURE |
|
199 | 1 | ); |
|
200 | |||
201 | 1 | if ($variablesFound === 0) { |
|
202 | 1 | return; |
|
203 | } |
||
204 | |||
205 | 1 | foreach ($matches as $match) { |
|
206 | 1 | $varName = $match[1][0]; |
|
207 | 1 | $offset = $match[1][1]; |
|
208 | |||
209 | // If it's a php reserved var, then its ok. |
||
210 | 1 | if (in_array($varName, $this->phpReservedVars) === true) { |
|
211 | 1 | continue; |
|
212 | } |
||
213 | |||
214 | // Don't validate class/object property usage in strings, |
||
215 | // because their declaration is already validated. |
||
216 | 1 | $variablePrefix = substr($content, $offset - 3, 2); |
|
217 | 1 | if ($variablePrefix === '::' || $variablePrefix === '->') { |
|
218 | 1 | continue; |
|
219 | } |
||
220 | |||
221 | 1 | if ($this->isSnakeCaps($varName) === false) { |
|
222 | 1 | $error = 'Variable in string "%s" is not in valid snake caps format'; |
|
223 | 1 | $data = array($varName); |
|
224 | 1 | $phpcsFile->addError($error, $stackPtr, 'StringNotSnakeCaps', $data); |
|
225 | 1 | } |
|
226 | 1 | }//end foreach |
|
227 | 1 | }//end processVariableInString() |
|
228 | |||
229 | |||
230 | /** |
||
231 | * Determines if a variable is in camel caps case. |
||
232 | * |
||
233 | * @param string $string String. |
||
234 | * @param bool $public If true, the first character in the string |
||
235 | * must be an a-z character. If false, the |
||
236 | * character must be an underscore. This |
||
237 | * argument is only applicable if $classFormat |
||
238 | * is false. |
||
239 | * |
||
240 | * @return bool |
||
241 | */ |
||
242 | 1 | protected function isCamelCaps($string, $public = true) |
|
250 | |||
251 | |||
252 | /** |
||
253 | * Determines if a variable is in snake caps case. |
||
254 | * |
||
255 | * @param string $string String. |
||
256 | * |
||
257 | * @return bool |
||
258 | */ |
||
259 | 1 | protected function isSnakeCaps($string) |
|
263 | }//end class |
||
264 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.