diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 42e7700b..f2651a80 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -64,6 +64,7 @@ When you introduce new `public` sniff properties, or your sniff extends a class ### Pre-requisites * VIP Coding Standards * WordPress-Coding-Standards +* PHPCSUtils 1.x * PHP_CodeSniffer 3.x * PHPUnit 4.x, 5.x, 6.x or 7.x diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f68fd0df..c089b1d2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -44,6 +44,7 @@ Use `php -v` and `composer show` to get versions. | ------------------------ | ------- | PHP version | x.y.z | PHP_CodeSniffer version | x.y.z +| PHPCSUtils version | x.y.z | VIPCS version | x.y.z | WordPressCS version | x.y.z | VariableAnalysis version | x.y.z diff --git a/README.md b/README.md index 6b5c15da..1bcb6465 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Go to https://docs.wpvip.com/technical-references/code-review/phpcs-report/ to l * PHP 5.4+ * [PHPCS 3.7.1+](https://github.com/squizlabs/PHP_CodeSniffer/releases) +* [PHPCSUtils 1.0.8+](https://github.com/PHPCSStandards/PHPCSUtils) * [WPCS 2.3.0+](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/releases) * [VariableAnalysis 2.11.17+](https://github.com/sirbrillig/phpcs-variable-analysis/releases) @@ -34,7 +35,7 @@ composer g config allow-plugins.dealerdirect/phpcodesniffer-composer-installer t composer g require automattic/vipwpcs ``` -This will install the latest compatible versions of PHPCS, WPCS and VariableAnalysis and register the external standards with PHP_CodeSniffer. +This will install the latest compatible versions of PHPCS, PHPCSUtils, WPCS and VariableAnalysis and register the external standards with PHP_CodeSniffer. Please refer to the [installation instructions for installing PHP_CodeSniffer for WordPress.com VIP](https://docs.wpvip.com/how-tos/code-review/php_codesniffer/) for more details. diff --git a/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php b/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php index 89234f2e..61d3ed7d 100644 --- a/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php +++ b/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php @@ -9,7 +9,8 @@ namespace WordPressVIPMinimum\Sniffs; -use WordPressVIPMinimum\Sniffs\Sniff; +use PHPCSUtils\Utils\GetTokensAsString; +use PHPCSUtils\Utils\MessageHelper; /** * Restricts usage of some variables. @@ -179,7 +180,7 @@ public function process_token( $stackPtr ) { if ( isset( $token['bracket_closer'] ) ) { $owner = $this->phpcsFile->findPrevious( \T_VARIABLE, $stackPtr ); - $inside = $this->phpcsFile->getTokensAsString( $stackPtr, $token['bracket_closer'] - $stackPtr + 1 ); + $inside = GetTokensAsString::normal( $this->phpcsFile, $stackPtr, $token['bracket_closer'] ); $var = implode( '', [ $this->tokens[ $owner ]['content'], $inside ] ); } } @@ -200,11 +201,13 @@ public function process_token( $stackPtr ) { continue; } - $this->addMessage( + $code = MessageHelper::stringToErrorcode( $groupName . '_' . $match[1] ); + MessageHelper::addMessage( + $this->phpcsFile, $group['message'], $stackPtr, $group['type'] === 'error', - $this->string_to_errorcode( $groupName . '_' . $match[1] ), + $code, [ $var ] ); diff --git a/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php b/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php index 9c76bd25..a1e80c97 100644 --- a/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php +++ b/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php @@ -9,6 +9,8 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHPCSUtils\Utils\FunctionDeclarations; +use PHPCSUtils\Utils\ObjectDeclarations; /** * Class WordPressVIPMinimum_Sniffs_Classes_DeclarationCompatibilitySniff @@ -201,15 +203,15 @@ public function __construct() { */ protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currScope ) { - $className = $phpcsFile->getDeclarationName( $currScope ); + $className = ObjectDeclarations::getName( $phpcsFile, $currScope ); if ( $className !== $this->currentClass ) { $this->currentClass = $className; } - $methodName = $phpcsFile->getDeclarationName( $stackPtr ); + $methodName = FunctionDeclarations::getName( $phpcsFile, $stackPtr ); - $parentClassName = $phpcsFile->findExtendedClassName( $currScope ); + $parentClassName = ObjectDeclarations::findExtendedClassName( $phpcsFile, $currScope ); if ( $parentClassName === false ) { // This class does not extend any other class. return; @@ -242,7 +244,7 @@ protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currSco return; } - $signatureParams = $phpcsFile->getMethodParameters( $stackPtr ); + $signatureParams = FunctionDeclarations::getParameters( $phpcsFile, $stackPtr ); $parentSignature = $this->checkClasses[ $parentClassName ][ $methodName ]; diff --git a/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php b/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php index 1cb40e9b..d0a2fb61 100644 --- a/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php +++ b/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php @@ -8,8 +8,9 @@ namespace WordPressVIPMinimum\Sniffs\Constants; -use WordPressVIPMinimum\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Utils\PassedParameters; +use WordPressVIPMinimum\Sniffs\Sniff; /** * Sniff for properly using constant name when checking whether a constant is defined. @@ -55,7 +56,7 @@ public function process_token( $stackPtr ) { return; } - $param = $this->get_function_call_parameter( $stackPtr, 1 ); + $param = PassedParameters::getParameter( $this->phpcsFile, $stackPtr, 1, 'constant_name' ); if ( $param === false ) { // Target parameter not found. return; diff --git a/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php b/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php index 5165f36c..09ec5081 100644 --- a/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php +++ b/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php @@ -9,6 +9,7 @@ use WordPressVIPMinimum\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\BackCompat\BCFile; /** * Ensure that non-PHP files are included via `file_get_contents()` instead of using `include/require[_once]`. @@ -59,7 +60,7 @@ public function register() { * @return void */ public function process_token( $stackPtr ) { - $end_of_statement = $this->phpcsFile->findEndOfStatement( $stackPtr ); + $end_of_statement = BCFile::findEndOfStatement( $this->phpcsFile, $stackPtr ); $curStackPtr = ( $end_of_statement + 1 ); do { diff --git a/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php b/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php index c069696f..ca2f2acc 100644 --- a/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php +++ b/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php @@ -8,6 +8,7 @@ namespace WordPressVIPMinimum\Sniffs\Functions; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Utils\TextStrings; use WordPressVIPMinimum\Sniffs\Sniff; /** @@ -139,7 +140,7 @@ private function collect_variables() { * If we reached the end of the loop and the $value_ptr was set, we know for sure * this was a plain text string variable assignment. */ - $current_var_value = $this->strip_quotes( $this->tokens[ $value_ptr ]['content'] ); + $current_var_value = TextStrings::stripQuotes( $this->tokens[ $value_ptr ]['content'] ); if ( isset( $this->disallowed_functions[ $current_var_value ] ) === false ) { // Text string is not one of the ones we're looking for. diff --git a/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php b/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php index 03cc8a78..f3544e6b 100644 --- a/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php +++ b/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php @@ -7,8 +7,10 @@ namespace WordPressVIPMinimum\Sniffs\Hooks; -use WordPressVIPMinimum\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Utils\Arrays; +use PHPCSUtils\Utils\FunctionDeclarations; +use WordPressVIPMinimum\Sniffs\Sniff; /** * This sniff validates that filters always return a value @@ -96,7 +98,7 @@ public function process_token( $stackPtr ) { */ private function processArray( $stackPtr ) { - $open_close = $this->find_array_open_close( $stackPtr ); + $open_close = Arrays::getOpenClose( $this->phpcsFile, $stackPtr ); if ( $open_close === false ) { return; } @@ -185,7 +187,7 @@ private function processFunctionBody( $stackPtr ) { $filterName = $this->tokens[ $this->filterNamePtr ]['content']; - $methodProps = $this->phpcsFile->getMethodProperties( $stackPtr ); + $methodProps = FunctionDeclarations::getProperties( $this->phpcsFile, $stackPtr ); if ( $methodProps['is_abstract'] === true ) { $message = 'The callback for the `%s` filter hook-in points to an abstract method. Please ensure that child class implementations of this method always return a value.'; $data = [ $filterName ]; diff --git a/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php b/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php index ddcf4fac..09ee720c 100644 --- a/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php +++ b/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php @@ -7,8 +7,9 @@ namespace WordPressVIPMinimum\Sniffs\Hooks; -use WordPressVIPMinimum\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Utils\Arrays; +use WordPressVIPMinimum\Sniffs\Sniff; /** * This sniff validates a proper usage of pre_get_posts action callback. @@ -97,7 +98,7 @@ public function process_token( $stackPtr ) { */ private function processArray( $stackPtr ) { - $open_close = $this->find_array_open_close( $stackPtr ); + $open_close = Arrays::getOpenClose( $this->phpcsFile, $stackPtr ); if ( $open_close === false ) { return; } diff --git a/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php b/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php index 7bc8ca32..54f2b19c 100644 --- a/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php +++ b/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php @@ -8,6 +8,7 @@ namespace WordPressVIPMinimum\Sniffs\Performance; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Utils\TextStrings; use WordPressCS\WordPress\AbstractFunctionParameterSniff; /** @@ -149,7 +150,7 @@ public function process_parameters( $stackPtr, $group_name, $matched_content, $p } if ( $this->tokens[ $i ]['code'] === T_CONSTANT_ENCAPSED_STRING ) { - $content = $this->strip_quotes( $this->tokens[ $i ]['content'] ); + $content = TextStrings::stripQuotes( $this->tokens[ $i ]['content'] ); if ( is_numeric( $content ) === true ) { $tokensAsString .= $content; continue; diff --git a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php index 416ae604..1341e590 100644 --- a/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -8,8 +8,10 @@ namespace WordPressVIPMinimum\Sniffs\Security; -use WordPressVIPMinimum\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\BackCompat\BCFile; +use PHPCSUtils\Utils\TextStrings; +use WordPressVIPMinimum\Sniffs\Sniff; /** * Checks whether proper escaping function is used. @@ -178,7 +180,7 @@ public function process_token( $stackPtr ) { if ( $this->in_short_echo !== false ) { $ignore[ T_COMMA ] = T_COMMA; } else { - $start_of_statement = $this->phpcsFile->findStartOfStatement( $stackPtr, T_COMMA ); + $start_of_statement = BCFile::findStartOfStatement( $this->phpcsFile, $stackPtr, T_COMMA ); if ( $this->tokens[ $start_of_statement ]['code'] === T_ECHO ) { $ignore[ T_COMMA ] = T_COMMA; } @@ -195,7 +197,7 @@ public function process_token( $stackPtr ) { $content = $this->tokens[ $html ]['content']; if ( isset( Tokens::$stringTokens[ $this->tokens[ $html ]['code'] ] ) === true ) { - $content = Sniff::strip_quotes( $content ); + $content = TextStrings::stripQuotes( $content ); } $escaping_type = $this->escaping_functions[ $function_name ]; diff --git a/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php b/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php index b15114ea..f76e773e 100644 --- a/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php +++ b/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php @@ -9,6 +9,7 @@ namespace WordPressVIPMinimum\Sniffs\Security; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Utils\TextStrings; use WordPressVIPMinimum\Sniffs\Sniff; /** @@ -72,7 +73,7 @@ public function process_token( $stackPtr ) { /* * Ignore Gruntfile.js files as they are configuration, not code. */ - $file_name = $this->strip_quotes( $this->phpcsFile->getFileName() ); + $file_name = TextStrings::stripQuotes( $this->phpcsFile->getFileName() ); $file_name = strtolower( basename( $file_name ) ); if ( $file_name === 'gruntfile.js' ) { @@ -120,7 +121,7 @@ public function process_token( $stackPtr ) { return; } - $content = $this->strip_quotes( $this->tokens[ $stackPtr ]['content'] ); + $content = TextStrings::stripQuotes( $this->tokens[ $stackPtr ]['content'] ); $match_count = preg_match_all( self::UNESCAPED_INTERPOLATE_REGEX, $content, $matches ); if ( $match_count > 0 ) { diff --git a/WordPressVIPMinimum/Sniffs/UserExperience/AdminBarRemovalSniff.php b/WordPressVIPMinimum/Sniffs/UserExperience/AdminBarRemovalSniff.php index 6d95cb34..20c1d853 100644 --- a/WordPressVIPMinimum/Sniffs/UserExperience/AdminBarRemovalSniff.php +++ b/WordPressVIPMinimum/Sniffs/UserExperience/AdminBarRemovalSniff.php @@ -9,6 +9,8 @@ namespace WordPressVIPMinimum\Sniffs\UserExperience; +use PHPCSUtils\Utils\GetTokensAsString; +use PHPCSUtils\Utils\TextStrings; use WordPressCS\WordPress\AbstractFunctionParameterSniff; use PHP_CodeSniffer\Util\Tokens; @@ -208,13 +210,13 @@ public function process_parameters( $stackPtr, $group_name, $matched_content, $p break; case 'add_filter': - $filter_name = $this->strip_quotes( $parameters[1]['raw'] ); + $filter_name = TextStrings::stripQuotes( $parameters[1]['raw'] ); if ( $filter_name !== 'show_admin_bar' ) { break; } $error = true; - if ( $this->remove_only === true && isset( $parameters[2]['raw'] ) && $this->strip_quotes( $parameters[2]['raw'] ) === '__return_true' ) { + if ( $this->remove_only === true && isset( $parameters[2]['raw'] ) && TextStrings::stripQuotes( $parameters[2]['raw'] ) === '__return_true' ) { $error = false; } break; @@ -343,7 +345,7 @@ protected function process_css_style( $stackPtr ) { } } $start = ( $i + 1 ); - $selector = trim( $this->phpcsFile->getTokensAsString( $start, $opener - $start ) ); + $selector = trim( GetTokensAsString::normal( $this->phpcsFile, $start, ( $opener - 1 ) ) ); unset( $i ); foreach ( $this->target_css_selectors as $target_selector ) { diff --git a/WordPressVIPMinimum/ruleset.xml b/WordPressVIPMinimum/ruleset.xml index ae8347d4..87394301 100644 --- a/WordPressVIPMinimum/ruleset.xml +++ b/WordPressVIPMinimum/ruleset.xml @@ -1,6 +1,16 @@ WordPress VIP Minimum Coding Standards + + + + diff --git a/composer.json b/composer.json index 1fc19981..005944eb 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.4", - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "phpcsstandards/phpcsutils": "^1.0.8", "sirbrillig/phpcs-variable-analysis": "^2.11.17", "squizlabs/php_codesniffer": "^3.7.1", "wp-coding-standards/wpcs": "^2.3" diff --git a/tests/bootstrap.php b/tests/bootstrap.php index bb063fdc..667f58a7 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -48,7 +48,8 @@ If you use Composer, please run `composer install`. Otherwise, make sure you set a `PHPCS_DIR` environment variable in your phpunit.xml file -pointing to the PHPCS directory. +pointing to the PHPCS directory and that PHPCSUtils is included in the `installed_paths` +for that PHPCS install. Please read the contributors guidelines for more information: https://github.com/Automattic/VIP-Coding-Standards/blob/develop/.github/CONTRIBUTING.md