diff --git a/README.md b/README.md index 412b4143..9832e743 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ The available options are as follows: - `validUndefinedVariableNames` (string, default `null`): a space-separated list of names of placeholder variables that you want to ignore from undefined variable warnings. For example, to ignore the variables `$post` and `$undefined`, this could be set to `'post undefined'`. - `allowUnusedForeachVariables` (bool, default `false`): if set to true, unused keys or values created by the `as` statement in a `foreach` loop will never be marked as unused. - `sitePassByRefFunctions` (string, default `null`): a list of custom functions which pass in variables to be initialized by reference (eg `preg_match()`) and therefore should not require those variables to be defined ahead of time. The list is space separated and each entry is of the form `functionName:1,2`. The function name comes first followed by a colon and a comma-separated list of argument numbers (starting from 1) which should be considered variable definitions. The special value `...` in the arguments list will cause all arguments after the last number to be considered variable definitions. +- `allowWordPressPassByRefFunctions` (bool, default `false`): if set to true, a list of common WordPress pass-by-reference functions will be added to the list of PHP ones so that passing undefined variables to these functions (to be initialized by reference) will be allowed. To set these these options, you must use XML in your ruleset. For details, see the [phpcs customizable sniff properties page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Customisable-Sniff-Properties). Here is an example that ignores all variables that start with an underscore: diff --git a/VariableAnalysis/Lib/Constants.php b/VariableAnalysis/Lib/Constants.php index 665e134b..13021dca 100644 --- a/VariableAnalysis/Lib/Constants.php +++ b/VariableAnalysis/Lib/Constants.php @@ -238,6 +238,13 @@ public static function getPassByReferenceFunctions() { ]; } + public static function getWordPressPassByReferenceFunctions() { + return [ + 'wp_parse_str' => [2], + 'wp_cache_get' => [4], + ]; + } + /** * A regexp for matching variable names in double-quoted strings. */ diff --git a/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php b/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php index 134442a0..fe8c4d99 100644 --- a/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php +++ b/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php @@ -32,6 +32,12 @@ class VariableAnalysisSniff implements Sniff { */ public $sitePassByRefFunctions = null; + /** + * If set, allows common WordPress pass-by-reference functions in addition to + * the standard PHP ones. + */ + public $allowWordPressPassByRefFunctions = false; + /** * Allows exceptions in a catch block to be unused without provoking unused-var warning. * Set generic.codeanalysis.variableanalysis.allowUnusedCaughtExceptions to a true value. @@ -89,13 +95,15 @@ public function register() { private function getPassByReferenceFunction($functionName) { $passByRefFunctions = Constants::getPassByReferenceFunctions(); - // Magic to modfy $passByRefFunctions with any site-specific settings. if (!empty($this->sitePassByRefFunctions)) { foreach (preg_split('/\s+/', trim($this->sitePassByRefFunctions)) as $line) { list ($function, $args) = explode(':', $line); $passByRefFunctions[$function] = explode(',', $args); } } + if ($this->allowWordPressPassByRefFunctions) { + $passByRefFunctions = array_merge($passByRefFunctions, Constants::getWordPressPassByReferenceFunctions()); + } return isset($passByRefFunctions[$functionName]) ? $passByRefFunctions[$functionName] : null; } diff --git a/VariableAnalysis/Tests/CodeAnalysis/VariableAnalysisTest.php b/VariableAnalysis/Tests/CodeAnalysis/VariableAnalysisTest.php index 119dc53b..70540428 100644 --- a/VariableAnalysis/Tests/CodeAnalysis/VariableAnalysisTest.php +++ b/VariableAnalysis/Tests/CodeAnalysis/VariableAnalysisTest.php @@ -262,6 +262,7 @@ public function testFunctionWithReferenceWarnings() { 46, 59, 60, + 64, ]; $this->assertEquals($expectedWarnings, $lines); } @@ -287,6 +288,34 @@ public function testFunctionWithReferenceWarningsAllowsCustomFunctions() { 39, 40, 46, + 64, + ]; + $this->assertEquals($expectedWarnings, $lines); + } + + public function testFunctionWithReferenceWarningsAllowsWordPressFunctionsIfSet() { + $fixtureFile = $this->getFixture('FunctionWithReferenceFixture.php'); + $phpcsFile = $this->prepareLocalFileForSniffs($this->getSniffFiles(), $fixtureFile); + $phpcsFile->ruleset->setSniffProperty( + 'VariableAnalysis\Sniffs\CodeAnalysis\VariableAnalysisSniff', + 'allowWordPressPassByRefFunctions', + 'true' + ); + $phpcsFile->process(); + $lines = $this->getWarningLineNumbersFromFile($phpcsFile); + $expectedWarnings = [ + 8, + 20, + 32, + 33, + 34, + 36, + 37, + 39, + 40, + 46, + 59, + 60, ]; $this->assertEquals($expectedWarnings, $lines); } diff --git a/VariableAnalysis/Tests/CodeAnalysis/fixtures/FunctionWithReferenceFixture.php b/VariableAnalysis/Tests/CodeAnalysis/fixtures/FunctionWithReferenceFixture.php index 29295147..e4c11e6b 100644 --- a/VariableAnalysis/Tests/CodeAnalysis/fixtures/FunctionWithReferenceFixture.php +++ b/VariableAnalysis/Tests/CodeAnalysis/fixtures/FunctionWithReferenceFixture.php @@ -59,3 +59,7 @@ function function_with_ignored_reference_call() { my_reference_function($foo, $baz, $bip); another_reference_function($foo, $foo2, $foo3); } + +function function_with_wordpress_reference_calls() { + wp_parse_str('foo=bar', $vars); +}