From 5bc1d817a7b9bbef65df2cd55406bf6996efa899 Mon Sep 17 00:00:00 2001 From: Nilambar Sharma Date: Tue, 12 Nov 2024 16:02:07 +0545 Subject: [PATCH 1/2] Add sniff for required function parameter --- phpcs-rulesets/plugin-review.xml | 7 +- .../RequiredFunctionParametersSniff.php | 81 +++++++++++++++++++ .../RequiredFunctionParametersUnitTest.inc | 11 +++ .../RequiredFunctionParametersUnitTest.php | 59 ++++++++++++++ phpcs-sniffs/PluginCheck/ruleset.xml | 1 + .../test-plugin-review-phpcs-errors/load.php | 2 + .../Plugin_Review_PHPCS_Check_Tests.php | 3 + 7 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/RequiredFunctionParametersSniff.php create mode 100644 phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/RequiredFunctionParametersUnitTest.inc create mode 100644 phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/RequiredFunctionParametersUnitTest.php diff --git a/phpcs-rulesets/plugin-review.xml b/phpcs-rulesets/plugin-review.xml index b4d5eede..8a78cb56 100644 --- a/phpcs-rulesets/plugin-review.xml +++ b/phpcs-rulesets/plugin-review.xml @@ -141,7 +141,7 @@ 7 - + 6 @@ -151,4 +151,9 @@ 7 + + + 7 + + diff --git a/phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/RequiredFunctionParametersSniff.php b/phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/RequiredFunctionParametersSniff.php new file mode 100644 index 00000000..61200990 --- /dev/null +++ b/phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/RequiredFunctionParametersSniff.php @@ -0,0 +1,81 @@ +> Function name as key, array with target parameter and name as value. + */ + protected $target_functions = array( + 'parse_str' => array( + 'position' => 2, + 'name' => 'result', + ), + ); + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.3.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @return int|void Integer stack pointer to skip forward or void to continue normal file processing. + */ + public function process_token( $stackPtr ) { + if ( isset( $this->target_functions[ strtolower( $this->tokens[ $stackPtr ]['content'] ) ] ) ) { + // Disallow excluding function groups for this sniff. + $this->exclude = array(); + + return parent::process_token( $stackPtr ); + } + } + + /** + * Process the parameters of a matched function call. + * + * @since 1.3.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched in lowercase. + * @param array $parameters Array with information about the parameters. + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $target_param = $this->target_functions[ $matched_content ]; + + $found_param = PassedParameters::getParameterFromStack( $parameters, $target_param['position'], $target_param['name'] ); + + if ( false === $found_param ) { + $this->phpcsFile->addError( + 'The "%s" parameter for function %s() is missing.', + $stackPtr, + 'Missing', + array( $target_param['name'], $matched_content ) + ); + } + } +} diff --git a/phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/RequiredFunctionParametersUnitTest.inc b/phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/RequiredFunctionParametersUnitTest.inc new file mode 100644 index 00000000..a115ffa0 --- /dev/null +++ b/phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/RequiredFunctionParametersUnitTest.inc @@ -0,0 +1,11 @@ + => + */ + public function getErrorList() { + return array( + 4 => 1, + 8 => 1, + 11 => 1, + ); + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + } + + /** + * Returns the fully qualified class name (FQCN) of the sniff. + * + * @return string The fully qualified class name of the sniff. + */ + protected function get_sniff_fqcn() { + return RequiredFunctionParametersSniff::class; + } + + /** + * Sets the parameters for the sniff. + * + * @throws \RuntimeException If unable to set the ruleset parameters required for the test. + * + * @param Sniff $sniff The sniff being tested. + */ + public function set_sniff_parameters( Sniff $sniff ) { + } +} diff --git a/phpcs-sniffs/PluginCheck/ruleset.xml b/phpcs-sniffs/PluginCheck/ruleset.xml index e07fe0d2..4243c328 100644 --- a/phpcs-sniffs/PluginCheck/ruleset.xml +++ b/phpcs-sniffs/PluginCheck/ruleset.xml @@ -7,5 +7,6 @@ + diff --git a/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php b/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php index 96e8669a..d069d1b8 100644 --- a/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php +++ b/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php @@ -24,3 +24,5 @@ query_posts( 'cat=3' ); wp_reset_query(); + +parse_str( 'first=value&arr[]=foo+bar&arr[]=baz' ); diff --git a/tests/phpunit/tests/Checker/Checks/Plugin_Review_PHPCS_Check_Tests.php b/tests/phpunit/tests/Checker/Checks/Plugin_Review_PHPCS_Check_Tests.php index 29171a71..1a27c5da 100644 --- a/tests/phpunit/tests/Checker/Checks/Plugin_Review_PHPCS_Check_Tests.php +++ b/tests/phpunit/tests/Checker/Checks/Plugin_Review_PHPCS_Check_Tests.php @@ -38,6 +38,9 @@ public function test_run_with_errors() { $this->assertArrayHasKey( 'code', $errors['load.php'][12][5][0] ); $this->assertEquals( 'WordPress.WP.DeprecatedFunctions.the_author_emailFound', $errors['load.php'][12][5][0]['code'] ); + // Check for PluginCheck.CodeAnalysis.RequiredFunctionParameters.Missing error on Line no 28 and column no at 1. + $this->assertSame( 'PluginCheck.CodeAnalysis.RequiredFunctionParameters.Missing', $errors['load.php'][28][1][0]['code'] ); + // Check for WordPress.Security.ValidatedSanitizedInput warnings on Line no 15 and column no at 27. $this->assertCount( 1, wp_list_filter( $warnings['load.php'][15][27], array( 'code' => 'WordPress.Security.ValidatedSanitizedInput.InputNotValidated' ) ) ); $this->assertCount( 1, wp_list_filter( $warnings['load.php'][15][27], array( 'code' => 'WordPress.Security.ValidatedSanitizedInput.MissingUnslash' ) ) ); From f8ac867a21714040b5fc2bf2a856ef485138e13c Mon Sep 17 00:00:00 2001 From: Nilambar Sharma Date: Sun, 24 Nov 2024 21:24:24 +0545 Subject: [PATCH 2/2] Update test --- .../testdata/plugins/test-plugin-review-phpcs-errors/load.php | 4 ++-- .../tests/Checker/Checks/Plugin_Review_PHPCS_Check_Tests.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php b/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php index 32e42dc3..9e59cf50 100644 --- a/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php +++ b/tests/phpunit/testdata/plugins/test-plugin-review-phpcs-errors/load.php @@ -25,11 +25,11 @@ query_posts( 'cat=3' ); wp_reset_query(); -parse_str( 'first=value&arr[]=foo+bar&arr[]=baz' ); - $str = <<assertArrayHasKey( 'code', $errors['load.php'][12][5][0] ); $this->assertEquals( 'WordPress.WP.DeprecatedFunctions.the_author_emailFound', $errors['load.php'][12][5][0]['code'] ); - // Check for PluginCheck.CodeAnalysis.RequiredFunctionParameters.Missing error on Line no 28 and column no at 1. - $this->assertSame( 'PluginCheck.CodeAnalysis.RequiredFunctionParameters.Missing', $errors['load.php'][28][1][0]['code'] ); + // Check for PluginCheck.CodeAnalysis.RequiredFunctionParameters.Missing error on Line no 34 and column no at 1. + $this->assertSame( 'PluginCheck.CodeAnalysis.RequiredFunctionParameters.Missing', $errors['load.php'][34][1][0]['code'] ); // Check for WordPress.Security.ValidatedSanitizedInput warnings on Line no 15 and column no at 27. $this->assertCount( 1, wp_list_filter( $warnings['load.php'][15][27], array( 'code' => 'WordPress.Security.ValidatedSanitizedInput.InputNotValidated' ) ) );