Skip to content

Commit 97167b2

Browse files
committed
PrefixAllGlobals: prevent false negatives for autoloaded user-defined global functions
The `PrefixAllGlobals` sniff verifies that functions declared in the global namespace are prefixed with one of the whitelisted prefixes as passed to the sniff in the `prefixes` property in a custom ruleset. The sniff prevents false positives for polyfills for PHP native functions - which should be named exactly as named in PHP without prefix for them to be usable as a polyfill - by checking that the function didn't exist. Generally speaking this works fine in 95% of all cases as PHPCS is normally run stand-alone and doesn't contain any functions defined in the global namespace. Similarly, when PHPCS is installed via Composer, this would normally work fine as the commonly used `autoload` options are `PSR-0`, `PSR-4` and `classmap` which are all based on code being in classes. However, if the Composer `autoload` `files` option is used to load, for instance, a functions file declaring functions in the global namespace, this "polyfill false positive prevention" would incorrectly cause errors _not_ to be thrown for functions declared in the global namespace which were now autoloaded via Composer. I have now fixed this by, instead of using `function_exists()`, using a check against a functions list retrieved via `get_defined_functions()`. This change does not have unit tests as: * Preventing false positives for polyfills is already unit tested. * Checking that autoloaded user defined functions are not recognized as PHP native functions is not something which can be unit tested as such. This would need an integration test including a composer setup to be tested. Based on the test case provided in the issue which originally reported this, I have confirmed that this PR fixes the issue though. Fixes 1632
1 parent 75fc071 commit 97167b2

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ class PrefixAllGlobalsSniff extends AbstractFunctionParameterSniff {
173173
'WP_DEFAULT_THEME' => true,
174174
);
175175

176+
/**
177+
* List of all PHP native functions.
178+
*
179+
* Using this list rather than a call to `function_exists()` prevents
180+
* false negatives from user-defined functions when those would be
181+
* autoloaded via a Composer autoload files directives.
182+
*
183+
* @var array
184+
*/
185+
private $built_in_functions;
186+
187+
176188
/**
177189
* Returns an array of tokens this test wants to listen for.
178190
*
@@ -181,6 +193,11 @@ class PrefixAllGlobalsSniff extends AbstractFunctionParameterSniff {
181193
* @return array
182194
*/
183195
public function register() {
196+
// Get a list of all PHP native functions.
197+
$all_functions = get_defined_functions();
198+
$this->built_in_functions = array_flip( $all_functions['internal'] );
199+
200+
// Set the sniff targets.
184201
$targets = array(
185202
\T_NAMESPACE => \T_NAMESPACE,
186203
\T_FUNCTION => \T_FUNCTION,
@@ -345,7 +362,7 @@ public function process_token( $stackPtr ) {
345362
}
346363

347364
$item_name = $this->phpcsFile->getDeclarationName( $stackPtr );
348-
if ( function_exists( '\\' . $item_name ) ) {
365+
if ( isset( $this->built_in_functions[ $item_name ] ) ) {
349366
// Backfill for PHP native function.
350367
return;
351368
}

0 commit comments

Comments
 (0)