diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8bdf38b2..f01a03d2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,9 @@ --- name: Bug report about: Create a report to help us improve +title: '' +labels: '' +assignees: '' --- @@ -50,3 +53,4 @@ Use `php -v` and `composer show` to get versions. ## Tested Against `master` branch? - [ ] I have verified the issue still exists in the `master` branch of VIPCS. +- [ ] I have verified the issue still exists in the `develop` branch of VIPCS. diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 980c3c1f..8015ab5e 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,6 +1,9 @@ --- name: Enhancement about: Suggest an improvement for this project +title: '' +labels: '' +assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/release-template.md b/.github/ISSUE_TEMPLATE/release-template.md new file mode 100644 index 00000000..534e45e4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/release-template.md @@ -0,0 +1,24 @@ +--- +name: Release template +about: Internally used for new releases +title: Release 2.x.y +labels: 'Type: Maintenance' +assignees: GaryJones, rebeccahum + +--- + +⚠️ DO NOT MERGE (YET) ⚠️ + +Please do add approvals if you agree. + +PR for tracking changes for the 2.x.y release. Target release date: DOW DD MMMM. + +- [ ] Add changelog for this release. +- [ ] Merge this PR. +- [ ] Add release tag against `master`. +- [ ] Close the current milestone. +- [ ] Open a new milestone for the next release. +- [ ] If any open PRs/issues which were milestoned for this release do not make it into the release, update their milestone. +- [ ] Write a Lobby post. +- [ ] Write an internal P2 post. +- [ ] Open PR to update [Review Bot dependencies](https://github.com/Automattic/vip-go-ci/blob/master/tools-init.sh). diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist index 5096365e..db53aea3 100644 --- a/.phpcs.xml.dist +++ b/.phpcs.xml.dist @@ -34,6 +34,11 @@ + + + + + diff --git a/.travis.yml b/.travis.yml index 9707c948..97020ee1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,27 @@ -dist: xenial - -cache: - directories: - - $HOME/.cache/composer/files - -language: - - php - -before_install: - # Speed up build time by disabling Xdebug. - # https://johnblackbourn.com/reducing-travis-ci-build-times-for-wordpress-projects/ - # https://twitter.com/kelunik/status/954242454676475904 - - phpenv config-rm xdebug.ini || echo 'No xdebug config.' - -install: - - composer require squizlabs/php_codesniffer:"$PHPCS_BRANCH" --update-no-dev --no-suggest --no-scripts - - composer install --dev --no-suggest - -script: - # Run the unit tests. - - ./bin/unit-tests - - # Run ruleset tests. - - ./bin/ruleset-tests +language: php +os: linux +dist: trusty env: # `master` is now 3.x. - PHPCS_BRANCH="dev-master" # Lowest supported release in the 3.x series with which VIPCS is compatible. - - PHPCS_BRANCH="3.3.1" + - PHPCS_BRANCH="3.5.5" + +cache: + directories: + - $HOME/.cache/composer/files php: + - 5.4 + - 5.5 - 5.6 - 7.0 - 7.1 - 7.2 - 7.3 - - "7.4snapshot" + - 7.4 + - "nightly" # Rather than a `matrix` property, we use build stages. This allows early # build failure for basic linting and sniffing issues. @@ -49,15 +34,15 @@ stages: jobs: allow_failures: - - php: "7.4snapshot" + - php: "nightly" include: - stage: lint - php: 7.3 + php: 7.4 env: PHPCS_BRANCH="dev-master" before_install: phpenv config-rm xdebug.ini || echo 'No xdebug config.' - install: false - cache: false + install: skip + cache: skip script: # Lint the PHP files against parse errors. - ./bin/php-lint @@ -76,12 +61,42 @@ jobs: - libxml2-utils - stage: sniff - php: 7.3 + php: 7.4 env: PHPCS_BRANCH="dev-master" before_install: phpenv config-rm xdebug.ini || echo 'No xdebug config.' - install: composer install --dev --no-suggest + install: composer install --no-suggest script: # Run PHPCS against VIPCS. - ./bin/phpcs +before_install: + # Speed up build time by disabling Xdebug. + # https://johnblackbourn.com/reducing-travis-ci-build-times-for-wordpress-projects/ + # https://twitter.com/kelunik/status/954242454676475904 + - phpenv config-rm xdebug.ini || echo 'No xdebug config.' + + # On stable PHPCS versions, allow for PHP deprecation notices. + # Unit tests don't need to fail on those for stable releases where those issues won't get fixed anymore. + - | + if [[ "$TRAVIS_BUILD_STAGE_NAME" != "Sniff" && $PHPCS_BRANCH != "dev-master" ]]; then + echo 'error_reporting = E_ALL & ~E_DEPRECATED' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini + fi + +install: + - composer require squizlabs/php_codesniffer:"$PHPCS_BRANCH" --no-update --no-suggest --no-scripts + - | + if [[ $TRAVIS_PHP_VERSION == "nightly" ]]; then + # PHPUnit 7.x does not allow for installation on PHP 8, so ignore platform + # requirements to get PHPUnit 7.x to install on nightly. + composer install --ignore-platform-reqs --no-suggest + else + composer install --no-suggest + fi + +script: + # Run the unit tests. + - ./bin/unit-tests + + # Run ruleset tests. + - ./bin/ruleset-tests diff --git a/CHANGELOG.md b/CHANGELOG.md index ff9762f0..d82cf157 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,37 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.1.0] - 2020-07-07 + +Bumps requirements to PHPCS 3.5.5+ and WPCS 2.3.0+. + +### Added + +- `get_page_by_path()` restricted function warning, to suggest `wpcom_vip_get_page_by_path()` function. +- `stats_get_csv()` restricted function error, since this is a Jetpack-only function. +- Expanded list of HTMLExecutingFunctions to include `after`, `appendTo`, `before`, `insertAfter`, `insertBefore`, `prepend`, `prependTo`, `replaceAll` and `replaceWith`. +- Support PHP 5.4+ (down from 5.6+). +- PHP 8 nightly testing. + +### Changed + +- Expand message for `wp_remote_get()` usage. +- Downgrade `append()` usage violation from Error to Warning for VIP Go, to be consistent with the other HTMLExecutingFunctions. +- Downgrade AdminBarRemoval sniff from Error to Warning for VIP Go. +- Add `get_parent_theme_file_path()` to safelist of path functions for `WordPressVIPMinimum.Files.IncludingFile` sniff. +- Allow short array syntax and fix tests within the VIPCS own coding standards. +- Update issue templates. + +### Fixed + +- Use new `WordPress.DateTime.RestrictedFunctions` sniff instead of deprecated `WordPress.WP.TimezoneChange`. +- Fixed warnings and information items in Travis. + +### Removed + +- `get_super_admins()` restricted function rule for VIP Go. +- `WordPressVIPMinimum.VersionControl.MergeConflict` sniff in favour of `Generic.VersionControl.GitMergeConflict`. + ## [2.0.0] - 2019-07-12 This release switches from having WPCS `1.*` as a dependency, to WPCS `2.*`. It is not compatible with WPCS `1.*`. @@ -367,5 +398,6 @@ This release contains breaking changes. - `wpcom_vip_get_page_by_path` from `WordPressVIPMinimum.VIP.RestrictedFunctions` - Version check for PHP 7 or less in `WordPressVIPMinimum.Variables.VariableAnalysis` unit test since tests are not failing anymore. +[2.1.0]: https://github.com/Automattic/VIP-Coding-Standards/compare/2.0.0...2.1.0 [2.0.0]: https://github.com/Automattic/VIP-Coding-Standards/compare/1.0.0...2.0.0 [1.0.0]: https://github.com/Automattic/VIP-Coding-Standards/compare/0.4.0...1.0.0 diff --git a/README.md b/README.md index 4ac0c9c4..ee2d7938 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ Go to https://wpvip.com/documentation/phpcs-review-feedback/ to learn about why ## Minimal requirements -* [PHPCS 3.3.1+](https://github.com/squizlabs/PHP_CodeSniffer/releases) -* [WPCS 2.*](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/releases) +* PHP 5.4+ +* [PHPCS 3.5.5+](https://github.com/squizlabs/PHP_CodeSniffer/releases) +* [WPCS 2.3.0+](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/releases) ## Installation @@ -31,7 +32,7 @@ We recommend the [PHP_CodeSniffer Standards Composer Installer Plugin](https://g Alternatively, you should register the standard to PHPCS by appending the VIPCS directory to the end of the installed paths. e.g. -`phpcs --config-set installed_paths [/path/to/wpcsstandard],[path/to/vipcsstandard],etc` +`phpcs --config-set installed_paths /path/to/wpcsstandard,path/to/vipcsstandard,etc.` ## Contribution diff --git a/WordPress-VIP-Go/ruleset-test.inc b/WordPress-VIP-Go/ruleset-test.inc index 22a10859..8e3be3f1 100644 --- a/WordPress-VIP-Go/ruleset-test.inc +++ b/WordPress-VIP-Go/ruleset-test.inc @@ -218,11 +218,11 @@ function foo_bar_foo() { } // WordPressVIPMinimum.UserExperience.AdminBarRemoval -add_filter( 'show_admin_bar', '__return_false' ); // Error. +add_filter( 'show_admin_bar', '__return_false' ); // Warning. add_filter( 'show_admin_bar', '__return_true' ); // Ok. -show_admin_bar( false ); // Error. +show_admin_bar( false ); // Warning. show_admin_bar( true ); // Ok. -add_filter( 'show_admin_bar', 'my_own_return_false' ); // Error. +add_filter( 'show_admin_bar', 'my_own_return_false' ); // Warning. echo ''; ?> flush_rules(); // Error. @@ -510,7 +510,7 @@ $query_args = array( // WordPressVIPMinimum.Security.EscapingVoidReturnFunctions.Found esc_js( _deprecated_argument() ); // Error. esc_js( _deprecated_constructor() ); // Error. -esc_js( _deprecated_file() ); // Error. +// esc_js( _deprecated_file() ); // Error. esc_js( _deprecated_function() ); // Error. esc_js( _deprecated_hook() ); // Error. esc_js( _doing_it_wrong() ); // Error. @@ -567,12 +567,8 @@ $_SERVER['HTTP_X_FORWARDED_FOR']; // Error. $_SERVER["REMOTE_ADDR"]; // Error. // phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -// WordPressVIPMinimum.VersionControl.MergeConflict -function is_prime( $n ) { - if ( 2 === $n ) { - } -//phpcs:ignore Generic.PHP.Syntax.PHPSyntax -======= // Error. - if ( $n % 2 === 0 ) { - } -} +// Generic.VersionControl.GitMergeConflict +?> +<<<<<<< HEAD // Error. + +>>>>>>> // Error. diff --git a/WordPress-VIP-Go/ruleset-test.php b/WordPress-VIP-Go/ruleset-test.php index 68fbc156..b653b83d 100644 --- a/WordPress-VIP-Go/ruleset-test.php +++ b/WordPress-VIP-Go/ruleset-test.php @@ -25,18 +25,6 @@ 181 => 1, 187 => 1, 188 => 1, - 221 => 1, - 223 => 1, - 225 => 1, - 228 => 1, - 229 => 1, - 230 => 1, - 235 => 1, - 236 => 1, - 237 => 1, - 245 => 1, - 246 => 1, - 247 => 1, 252 => 1, 255 => 1, 256 => 1, @@ -56,7 +44,6 @@ 353 => 1, 354 => 1, 355 => 1, - 356 => 1, 357 => 1, 358 => 1, 359 => 1, @@ -111,7 +98,7 @@ 507 => 1, 511 => 1, 512 => 1, - 513 => 1, + // 513 => 1, 514 => 1, 515 => 1, 516 => 1, @@ -128,7 +115,8 @@ 565 => 1, 566 => 1, 567 => 1, - 575 => 1, + 572 => 1, + 574 => 1, ], 'warnings' => [ 4 => 1, @@ -197,6 +185,18 @@ 208 => 1, 212 => 1, 217 => 1, + 221 => 1, + 223 => 1, + 225 => 1, + 228 => 1, + 229 => 1, + 230 => 1, + 235 => 1, + 236 => 1, + 237 => 1, + 245 => 1, + 246 => 1, + 247 => 1, 265 => 1, 269 => 1, 273 => 1, diff --git a/WordPress-VIP-Go/ruleset.xml b/WordPress-VIP-Go/ruleset.xml index 34cd751a..57c751a8 100644 --- a/WordPress-VIP-Go/ruleset.xml +++ b/WordPress-VIP-Go/ruleset.xml @@ -82,6 +82,16 @@ 6 File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://wpvip.com/documentation/vip-go/writing-files-on-vip-go/ + + warning + 6 + Removal of admin bar is highly discouraged for user roles of "administrator" and "vip_support" -- if these roles are already excluded, this warning can be ignored. + + + warning + 6 + Hiding of admin bar is highly discouraged for user roles of "administrator" and "vip_support" -- if these roles are already excluded, this warning can be ignored. + error 6 @@ -112,9 +122,6 @@ warning File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://wpvip.com/documentation/vip-go/writing-files-on-vip-go/ - - error - warning %s() is uncached. If the function is being used to fetch a remote file (e.g. a URL starting with https://), please use wpcom_vip_file_get_contents() to ensure the results are cached. For more details, please see https://wpvip.com/documentation/vip-go/fetching-remote-data/ @@ -298,6 +305,9 @@ 0 + + 0 + 0 diff --git a/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php b/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php index 2b6efd09..0f383800 100644 --- a/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php +++ b/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php @@ -31,6 +31,7 @@ class IncludingFileSniff extends AbstractFunctionRestrictionsSniff { 'get_stylesheet_directory', 'get_template_directory', 'locate_template', + 'get_parent_theme_file_path', ]; /** diff --git a/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php b/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php index 05318571..e1f6a22e 100644 --- a/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php +++ b/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php @@ -106,9 +106,7 @@ private function collect_variables() { return; } - $current_var_name = $this->tokens[ - $this->stackPtr - ]['content']; + $current_var_name = $this->tokens[ $this->stackPtr ]['content']; /* * Find assignments ( $foo = "bar"; ) @@ -202,9 +200,7 @@ private function find_dynamic_calls() { */ if ( ! isset( - $this->variables_arr[ - $this->tokens[ $this->stackPtr ]['content'] - ] + $this->variables_arr[ $this->tokens[ $this->stackPtr ]['content'] ] ) ) { return; } @@ -220,16 +216,12 @@ private function find_dynamic_calls() { $i++; } while ( 'T_WHITESPACE' === - $this->tokens[ - $this->stackPtr + $i - ]['type'] + $this->tokens[ $this->stackPtr + $i ]['type'] ); if ( 'T_OPEN_PARENTHESIS' !== - $this->tokens[ - $this->stackPtr + $i - ]['type'] + $this->tokens[ $this->stackPtr + $i ]['type'] ) { return; } @@ -242,9 +234,7 @@ private function find_dynamic_calls() { */ if ( ! in_array( - $this->variables_arr[ - $this->tokens[ $this->stackPtr ]['content'] - ], + $this->variables_arr[ $this->tokens[ $this->stackPtr ]['content'] ], $this->blacklisted_functions, true ) ) { diff --git a/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php b/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php index 658af707..164021cf 100644 --- a/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php +++ b/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php @@ -268,6 +268,13 @@ public function getGroups() { 'delete_site_option', ], ], + 'stats_get_csv' => [ + 'type' => 'error', + 'message' => 'Using `%s` outside of Jetpack context pollutes the stats_cache entry in the wp_options table. We recommend building a custom function instead.', + 'functions' => [ + 'stats_get_csv', + ], + ], 'wp_mail' => [ 'type' => 'warning', 'message' => '`%s` should be used sparingly. For any bulk emailing should be handled by a 3rd party service, in order to prevent domain or IP addresses being flagged as spam.', @@ -295,7 +302,7 @@ public function getGroups() { // @link VIP Go: https://wpvip.com/documentation/vip-go/code-review-blockers-warnings-notices/#remote-calls 'wp_remote_get' => [ 'type' => 'warning', - 'message' => '%s() is highly discouraged, please use vip_safe_wp_remote_get() instead.', + 'message' => '%s() is highly discouraged. Please use vip_safe_wp_remote_get() instead which is designed to more gracefully handle failure than wp_remote_get() does.', 'functions' => [ 'wp_remote_get', ], @@ -326,6 +333,13 @@ public function getGroups() { 'create_function', ], ], + 'get_page_by_path' => [ + 'type' => 'warning', + 'message' => '%s() is highly discouraged due to not being cached; please use wpcom_vip_get_page_by_path() instead.', + 'functions' => [ + 'get_page_by_path', + ], + ], ]; $deprecated_vip_helpers = [ diff --git a/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php b/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php index a06b0aa2..dc76da4a 100644 --- a/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php +++ b/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php @@ -22,13 +22,26 @@ class HTMLExecutingFunctionsSniff extends Sniff { /** * List of HTML executing functions. * + * Name of function => content or target. + * Value indicates whether the function's arg is the content to be inserted, or the target where the inserted + * content is to be inserted before/after/replaced. For the latter, the content is in the preceding method's arg. + * * @var array */ public $HTMLExecutingFunctions = [ - 'html', - 'append', - 'write', - 'writeln', + 'after' => 'content', // jQuery. + 'append' => 'content', // jQuery. + 'appendTo' => 'target', // jQuery. + 'before' => 'content', // jQuery. + 'html' => 'content', // jQuery. + 'insertAfter' => 'target', // jQuery. + 'insertBefore' => 'target', // jQuery. + 'prepend' => 'content', // jQuery. + 'prependTo' => 'target', // jQuery. + 'replaceAll' => 'target', // jQuery. + 'replaceWith' => 'content', // jQuery. + 'write' => 'content', + 'writeln' => 'content', ]; /** @@ -58,29 +71,63 @@ public function register() { */ public function process_token( $stackPtr ) { - if ( false === in_array( $this->tokens[ $stackPtr ]['content'], $this->HTMLExecutingFunctions, true ) ) { + if ( ! isset( $this->HTMLExecutingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) ) { // Looking for specific functions only. return; } - $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + if ( 'content' === $this->HTMLExecutingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); - if ( T_OPEN_PARENTHESIS !== $this->tokens[ $nextToken ]['code'] ) { - // Not a function. - return; - } + if ( T_OPEN_PARENTHESIS !== $this->tokens[ $nextToken ]['code'] ) { + // Not a function. + return; + } + + $parenthesis_closer = $this->tokens[ $nextToken ]['parenthesis_closer']; + + while ( $nextToken < $parenthesis_closer ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); + if ( T_STRING === $this->tokens[ $nextToken ]['code'] ) { // Contains a variable, function call or something else dynamic. + $message = 'Any HTML passed to `%s` gets executed. Make sure it\'s properly escaped.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addWarning( $message, $stackPtr, $this->tokens[ $stackPtr ]['content'], $data ); + + return; + } + } + } elseif ( 'target' === $this->HTMLExecutingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) { + $prevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true ); + + if ( T_OBJECT_OPERATOR !== $this->tokens[ $prevToken ]['code'] ) { + return; + } - $parenthesis_closer = $this->tokens[ $nextToken ]['parenthesis_closer']; + $prevPrevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $prevToken - 1, null, true, null, true ); - while ( $nextToken < $parenthesis_closer ) { - $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); - if ( T_STRING === $this->tokens[ $nextToken ]['code'] ) { - $message = 'Any HTML passed to `%s` gets executed. Make sure it\'s properly escaped.'; + if ( T_CLOSE_PARENTHESIS !== $this->tokens[ $prevPrevToken ]['code'] ) { + // Not a function call, but may be a variable containing an element reference, so just + // flag all remaining instances of these target HTML executing functions. + $message = 'Any HTML used with `%s` gets executed. Make sure it\'s properly escaped.'; $data = [ $this->tokens[ $stackPtr ]['content'] ]; $this->phpcsFile->addWarning( $message, $stackPtr, $this->tokens[ $stackPtr ]['content'], $data ); return; } + + // Check if it's a function call (typically $() ) that contains a dynamic part. + $parenthesis_opener = $this->tokens[ $prevPrevToken ]['parenthesis_opener']; + + while ( $prevPrevToken > $parenthesis_opener ) { + $prevPrevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $prevPrevToken - 1, null, true, null, true ); + if ( T_STRING === $this->tokens[ $prevPrevToken ]['code'] ) { // Contains a variable, function call or something else dynamic. + $message = 'Any HTML used with `%s` gets executed. Make sure it\'s properly escaped.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addWarning( $message, $stackPtr, $this->tokens[ $stackPtr ]['content'], $data ); + + return; + } + } } } diff --git a/WordPressVIPMinimum/Sniffs/VersionControl/MergeConflictSniff.php b/WordPressVIPMinimum/Sniffs/VersionControl/MergeConflictSniff.php deleted file mode 100644 index a2922dac..00000000 --- a/WordPressVIPMinimum/Sniffs/VersionControl/MergeConflictSniff.php +++ /dev/null @@ -1,98 +0,0 @@ -tokens[ $stackPtr ]['code'] ) { - $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); - if ( T_SL !== $this->tokens[ $nextToken ]['code'] ) { - return; - } - $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); - if ( T_STRING !== $this->tokens[ $nextToken ]['code'] || 0 !== strpos( $this->tokens[ $nextToken ]['content'], '<<< HEAD' ) ) { - return; - } - - $message = 'Merge conflict detected. Found "<<<<<<< HEAD" string.'; - $this->phpcsFile->addError( $message, $stackPtr, 'Start' ); - - return; - } - - if ( T_ENCAPSED_AND_WHITESPACE === $this->tokens[ $stackPtr ]['code'] ) { - if ( 0 === strpos( $this->tokens[ $stackPtr ]['content'], '=======' ) ) { - $this->addSeparatorError( $stackPtr ); - - return; - } - - if ( 0 === strpos( $this->tokens[ $stackPtr ]['content'], '>>>>>>>' ) ) { - $message = 'Merge conflict detected. Found "%s" string.'; - $data = [ trim( $this->tokens[ $stackPtr ]['content'] ) ]; - $this->phpcsFile->addError( $message, $stackPtr, 'End', $data ); - - return; - } - } elseif ( T_IS_IDENTICAL === $this->tokens[ $stackPtr ]['code'] && T_IS_IDENTICAL === $this->tokens[ $stackPtr + 1 ]['code'] ) { - $this->addSeparatorError( $stackPtr ); - - return; - } - } - - /** - * Consolidated violation. - * - * @param int $stackPtr The position of the current token in the stack passed in $tokens. - */ - private function addSeparatorError( $stackPtr ) { - $message = 'Merge conflict detected. Found "=======" string.'; - $this->phpcsFile->addError( $message, $stackPtr, 'Separator' ); - } - -} diff --git a/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.inc b/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.inc index fa1d6b18..b225a4a7 100644 --- a/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.inc +++ b/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.inc @@ -12,6 +12,7 @@ require dirname( __FILE__ ) . '/my_file.php' ); require dirname( __FILE__, 2 ) . '/my_file.php' ); require dirname( dirname( __FILE__ ) ) . '/my_file.php' ); require dirname( dirname( __DIR__ ) ) . '/my_file.php' ); +require_once( get_parent_theme_file_path( '/my_file.php' ); ); // Warnings. include ( MY_CONSTANT . "my_file.php" ); // Custom constant. diff --git a/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.php b/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.php index c6a748de..5957cc5d 100644 --- a/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.php +++ b/WordPressVIPMinimum/Tests/Files/IncludingFileUnitTest.php @@ -22,11 +22,11 @@ class IncludingFileUnitTest extends AbstractSniffUnitTest { */ public function getErrorList() { return [ - 23 => 1, 24 => 1, 25 => 1, 26 => 1, 27 => 1, + 28 => 1, ]; } @@ -37,10 +37,10 @@ public function getErrorList() { */ public function getWarningList() { return [ - 17 => 1, 18 => 1, 19 => 1, 20 => 1, + 21 => 1, ]; } diff --git a/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.inc b/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.inc index b518275e..9b778b40 100644 --- a/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.inc +++ b/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.inc @@ -221,3 +221,9 @@ update_site_option( $bar, 'foo' ); // Warning. update_option( 'foo', $bar ); // Ok. delete_site_option( $foo ); // Warning. delete_option( $bar ); // Ok. + +wpcom_vip_get_page_by_path(); // Ok - VIP recommended version of get_page_by_path(). +get_page_by_path( $page_path ); // Warning. + +$popular = stats_get_csv( 'postviews', [ 'days' => 2, 'limit' => 20 ] ); // Error. +$popular = custom_stats_get_csv( 'postviews', [ 'days' => 2, 'limit' => 20 ] ); // Ok. \ No newline at end of file diff --git a/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.php b/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.php index 5a1fdf44..147c7cfa 100644 --- a/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.php +++ b/WordPressVIPMinimum/Tests/Functions/RestrictedFunctionsUnitTest.php @@ -109,6 +109,7 @@ public function getErrorList() { 218 => 1, 220 => 1, 222 => 1, + 228 => 1, ]; } @@ -133,6 +134,7 @@ public function getWarningList() { 138 => 1, 139 => 1, 208 => 1, + 226 => 1, ]; } diff --git a/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.js b/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.js index 1a59cc5f..ac9d31a0 100644 --- a/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.js +++ b/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.js @@ -1,13 +1,48 @@ (function(){ var el = document.querySelector(".myclass"); - el.html(''); // OK. - el.html('Hand written HTML'); // OK. - el.html( '' + variable + '' ); // NOK. - el.html( variable ); // NOK. - el.append( variable ); // NOK. + el.after(''); // OK. + el.after('Hand written HTML'); // OK. + el.after( '' + variable + '' ); // Warning. + el.after( variable ); // Warning. el.append( 'Hand written HTML' ); // OK. - el.append( '' + variable + '' ); // NOK. + el.append( '' + variable + '' ); // Warning. + el.append( variable ); // Warning. + el.before('Hand written HTML'); // OK. + el.before( '' + variable + '' ); // Warning. + el.before( variable ); // Warning. + el.html('Hand written HTML'); // OK. + el.html( '' + variable + '' ); // Warning. + el.html( variable ); // Warning. + el.prepend('Hand written HTML'); // OK. + el.prepend( '' + variable + '' ); // Warning. + el.prepend( variable ); // Warning. + el.replaceWith('Hand written HTML'); // OK. + el.replaceWith( '' + variable + '' ); // Warning. + el.replaceWith( variable ); // Warning. document.write( '' ); // OK. No variable, conscious. - document.write( hello ); // NOK. - document.writeln( hey ); // NOK. -})(); \ No newline at end of file + document.write( hello ); // Warning. + document + . writeln( hey ); // Warning. + + $('').appendTo(el); // OK. + $('Hand written HTML').appendTo( el ); // OK. + $( '' + variable + '' ).appendTo( el ); // Warning. + $( variable ).appendTo( el ); // Warning. + $('Hand written HTML').insertAfter( el ); // OK. + $( '' + variable + '' ).insertAfter( el ); // Warning. + $( variable ).insertAfter( el ); // Warning. + $('Hand written HTML').insertBefore( el ); // OK. + $( '' + variable + '' ).insertBefore( el ); // Warning. + $( variable ).insertBefore( el ); // Warning. + $('Hand written HTML').prependTo( el ); // OK. + $( '' + variable + '' ).prependTo( el ); // Warning. + $( variable ).prependTo( el ); // Warning. + $('Hand written HTML').replaceAll( el ); // OK. + $( '' + variable + '' ).replaceAll( el ); // Warning. + $( variable ) + . replaceAll( el ); // Warning. +})(); + + $( foo_that_contains_script_element() ).appendTo( el ); // Warning. + var $foo = $( '.my-selector' ); + $foo.appendTo( el ); // Warning. diff --git a/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.php b/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.php index 7fc534a4..794ec61f 100644 --- a/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.php +++ b/WordPressVIPMinimum/Tests/JS/HTMLExecutingFunctionsUnitTest.php @@ -34,10 +34,30 @@ public function getWarningList() { return [ 5 => 1, 6 => 1, - 7 => 1, + 8 => 1, 9 => 1, 11 => 1, 12 => 1, + 14 => 1, + 15 => 1, + 17 => 1, + 18 => 1, + 20 => 1, + 21 => 1, + 23 => 1, + 25 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 35 => 1, + 36 => 1, + 38 => 1, + 39 => 1, + 41 => 1, + 43 => 1, + 46 => 1, + 48 => 1, ]; } diff --git a/WordPressVIPMinimum/Tests/VersionControl/MergeConflictUnitTest.inc b/WordPressVIPMinimum/Tests/VersionControl/MergeConflictUnitTest.inc deleted file mode 100644 index 31965cc3..00000000 --- a/WordPressVIPMinimum/Tests/VersionControl/MergeConflictUnitTest.inc +++ /dev/null @@ -1,13 +0,0 @@ ->>>>>> branch-a -} diff --git a/WordPressVIPMinimum/Tests/VersionControl/MergeConflictUnitTest.php b/WordPressVIPMinimum/Tests/VersionControl/MergeConflictUnitTest.php deleted file mode 100644 index f0e40e67..00000000 --- a/WordPressVIPMinimum/Tests/VersionControl/MergeConflictUnitTest.php +++ /dev/null @@ -1,41 +0,0 @@ - => - */ - public function getErrorList() { - return [ - 4 => 1, - 8 => 1, - 12 => 1, - ]; - } - - /** - * Returns the lines where warnings should occur. - * - * @return array => - */ - public function getWarningList() { - return []; - } - -} diff --git a/WordPressVIPMinimum/ruleset-test.inc b/WordPressVIPMinimum/ruleset-test.inc index d3a894cb..632d0aa4 100644 --- a/WordPressVIPMinimum/ruleset-test.inc +++ b/WordPressVIPMinimum/ruleset-test.inc @@ -41,7 +41,7 @@ $args = array( _query_posts( 'posts_per_page=999' ); // Warning. $query_args['posts_per_page'] = 999; // Warning. -// WordPress.WP.TimezoneChange +// WordPress.DateTime.RestrictedFunctions date_default_timezone_set( 'FooBar' ); // Error. // WordPress.DB.PreparedSQL @@ -180,7 +180,7 @@ $output = shell_exec( 'ls -lart' ); // Error. var_dump(); // Warning. var_export(); // Warning. print_r(); // Warning. -trigger_error(); // Warning. +// trigger_error(); // Warning. set_error_handler(); // Warning. debug_backtrace(); // Warning. debug_print_backtrace(); // Warning. @@ -508,7 +508,7 @@ $query_args = array( // WordPressVIPMinimum.Security.EscapingVoidReturnFunctions.Found esc_js( _deprecated_argument() ); // Error. esc_js( _deprecated_constructor() ); // Error. -esc_js( _deprecated_file() ); // Error. +// esc_js( _deprecated_file() ); // Error. esc_js( _deprecated_function() ); // Error. esc_js( _deprecated_hook() ); // Error. esc_js( _doing_it_wrong() ); // Error. @@ -604,15 +604,12 @@ function foo() { $c = compact( $a, $b ); // Warning x 2. } -// WordPressVIPMinimum.VersionControl.MergeConflict -function is_prime( $n ) { - if ( 2 === $n ) { - } -//phpcs:ignore Generic.PHP.Syntax.PHPSyntax -======= // Error. - if ( $n % 2 === 0 ) { - } -} +// Generic.VersionControl.GitMergeConflict +?> +<<<<<<< HEAD // Error. + +>>>>>>> // Error. + diff --git a/WordPressVIPMinimum/ruleset-test.php b/WordPressVIPMinimum/ruleset-test.php index a4dd1efd..b3376134 100644 --- a/WordPressVIPMinimum/ruleset-test.php +++ b/WordPressVIPMinimum/ruleset-test.php @@ -177,7 +177,7 @@ 505 => 1, 509 => 1, 510 => 1, - 511 => 1, + // 511 => 1, 512 => 1, 513 => 1, 514 => 1, @@ -206,8 +206,9 @@ 595 => 1, 596 => 1, 597 => 1, - 612 => 1, - 618 => 1, + 609 => 1, + 611 => 1, + 615 => 1, ], 'warnings' => [ 32 => 1, @@ -234,7 +235,7 @@ 180 => 1, 181 => 1, 182 => 1, - 183 => 1, + // 183 => 1, 184 => 1, 185 => 1, 186 => 1, diff --git a/WordPressVIPMinimum/ruleset.xml b/WordPressVIPMinimum/ruleset.xml index 68084c8e..7e0d0d68 100644 --- a/WordPressVIPMinimum/ruleset.xml +++ b/WordPressVIPMinimum/ruleset.xml @@ -26,7 +26,7 @@ - + @@ -42,6 +42,7 @@ + diff --git a/composer.json b/composer.json index c37ec9f9..27133da1 100644 --- a/composer.json +++ b/composer.json @@ -15,17 +15,17 @@ } ], "require": { - "php": ">=5.6", - "squizlabs/php_codesniffer": "^3.3.1", - "wp-coding-standards/wpcs": "^2.1" + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.5.5", + "wp-coding-standards/wpcs": "^2.3" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", "phpcompatibility/php-compatibility": "^9", - "phpunit/phpunit": "^5 || ^6 || ^7" + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will manage the PHPCS 'installed_paths' automatically." }, "minimum-stability": "RC", "scripts": {