From cebd9f3b7a98d1f2e6112f7fc8873488576f9fdc Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sat, 10 Aug 2024 18:33:36 +0200 Subject: [PATCH 01/27] first check known urls --- .../Plugin_Repo/Plugin_Remote_Files.php | 159 ++++++++++++++++++ includes/Checker/Default_Check_Repository.php | 1 + 2 files changed, 160 insertions(+) create mode 100644 includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php new file mode 100644 index 000000000..5163b5a93 --- /dev/null +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -0,0 +1,159 @@ +look_for_known_urls( $result, $php_files ); + } + + /** + * Looks for kwown urls that makes remote calls. + * + * @since n.e.x.t. + * + * @param Check_Result $result The check result to amend, including the plugin context to check. + * @param array $php_files List of absolute PHP file paths. + */ + protected function look_for_known_urls( Check_Result $result, array $php_files ) { + // Known offloading services. + $look_known_offloading_services = array( + 'code\.jquery\.com', + '(?add_result_error_for_file( + $result, + __( 'Offloaded Content.
Offloading images, js, css, and other scripts to your servers or any remote service is disallowed.', 'plugin-check' ), + 'external_offloaded', + $file['file'], + $file['line'], + $file['column'], + 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely' + ); + } + } + } + + /** + * Gets the description for the check. + * + * Every check must have a short description explaining what the check does. + * + * @since n.e.x.t. + * + * @return string Description. + */ + public function get_description(): string { + return __( 'Prevents using remote services that are not necessary.', 'plugin-check' ); + } + + /** + * Gets the documentation URL for the check. + * + * Every check must have a URL with further information about the check. + * + * @since n.e.x.t. + * + * @return string The documentation URL. + */ + public function get_documentation_url(): string { + return __( 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely', 'plugin-check' ); + } +} diff --git a/includes/Checker/Default_Check_Repository.php b/includes/Checker/Default_Check_Repository.php index 171fb117d..bbbec4e08 100644 --- a/includes/Checker/Default_Check_Repository.php +++ b/includes/Checker/Default_Check_Repository.php @@ -59,6 +59,7 @@ private function register_default_checks() { 'no_unfiltered_uploads' => new Checks\Plugin_Repo\No_Unfiltered_Uploads_Check(), 'trademarks' => new Checks\Plugin_Repo\Trademarks_Check(), 'non_blocking_scripts' => new Checks\Performance\Non_Blocking_Scripts_Check(), + 'plugin_remote_files' => new Checks\Plugin_Repo\Plugin_Remote_Files(), ) ); From 83a9ac7ca270f7edba45f1f51f4c0e5a219d82f8 Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sun, 11 Aug 2024 13:20:40 +0200 Subject: [PATCH 02/27] name changes --- .../Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php | 8 ++++---- includes/Checker/Default_Check_Repository.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php index 5163b5a93..aa2b59582 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -69,8 +69,8 @@ public function get_categories() { protected function check_files( Check_Result $result, array $files ) { $php_files = self::filter_files_by_extension( $files, 'php' ); - // Looks for Kwnown URLs. - $this->look_for_known_urls( $result, $php_files ); + // Looks for Kwnown External URLs. + $this->look_for_known_urls( $result, $files ); } /** @@ -81,7 +81,7 @@ protected function check_files( Check_Result $result, array $files ) { * @param Check_Result $result The check result to amend, including the plugin context to check. * @param array $php_files List of absolute PHP file paths. */ - protected function look_for_known_urls( Check_Result $result, array $php_files ) { + protected function look_for_known_urls( Check_Result $result, array $files ) { // Known offloading services. $look_known_offloading_services = array( 'code\.jquery\.com', @@ -114,7 +114,7 @@ protected function look_for_known_urls( Check_Result $result, array $php_files ) ); $offloaded_pattern = '/(' . implode( '|', $look_known_offloading_services ) . ')/i'; - $files = self::files_preg_match_all( $offloaded_pattern, $php_files ); + $files = self::files_preg_match_all( $offloaded_pattern, $files ); if ( ! empty( $files ) ) { foreach ( $files as $file ) { diff --git a/includes/Checker/Default_Check_Repository.php b/includes/Checker/Default_Check_Repository.php index bbbec4e08..ca0fb0e3d 100644 --- a/includes/Checker/Default_Check_Repository.php +++ b/includes/Checker/Default_Check_Repository.php @@ -59,7 +59,7 @@ private function register_default_checks() { 'no_unfiltered_uploads' => new Checks\Plugin_Repo\No_Unfiltered_Uploads_Check(), 'trademarks' => new Checks\Plugin_Repo\Trademarks_Check(), 'non_blocking_scripts' => new Checks\Performance\Non_Blocking_Scripts_Check(), - 'plugin_remote_files' => new Checks\Plugin_Repo\Plugin_Remote_Files(), + 'remote_files' => new Checks\Plugin_Repo\Plugin_Remote_Files(), ) ); From 37b6cfefb1e260c0d767119991d362d25d57cc82 Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sun, 11 Aug 2024 23:20:19 +0200 Subject: [PATCH 03/27] added extensions --- .../Plugin_Repo/Plugin_Remote_Files.php | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php index aa2b59582..b7448acee 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -70,7 +70,7 @@ protected function check_files( Check_Result $result, array $files ) { $php_files = self::filter_files_by_extension( $files, 'php' ); // Looks for Kwnown External URLs. - $this->look_for_known_urls( $result, $files ); + $this->look_for_offloading( $result, $php_files ); } /** @@ -81,7 +81,7 @@ protected function check_files( Check_Result $result, array $files ) { * @param Check_Result $result The check result to amend, including the plugin context to check. * @param array $php_files List of absolute PHP file paths. */ - protected function look_for_known_urls( Check_Result $result, array $files ) { + protected function look_for_offloading( Check_Result $result, array $files ) { // Known offloading services. $look_known_offloading_services = array( 'code\.jquery\.com', @@ -114,10 +114,32 @@ protected function look_for_known_urls( Check_Result $result, array $files ) { ); $offloaded_pattern = '/(' . implode( '|', $look_known_offloading_services ) . ')/i'; - $files = self::files_preg_match_all( $offloaded_pattern, $files ); + $files_urls = self::files_preg_match_all( $offloaded_pattern, $files ); - if ( ! empty( $files ) ) { - foreach ( $files as $file ) { + // Known offloading extensions. + $look_known_offloading_ext = array( + 'css', + 'svg', + 'jpg', + 'jpeg', + 'gif', + 'png', + 'webm', + 'mp4', + 'mpg', + 'mpeg', + 'mp3', + 'json' + ); + + $offloading_ext = '\.' . implode( '|\.', $look_known_offloading_ext ); + $offloaded_pattern = '/(https?:\/\/[www\.]?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*(' . $offloading_ext . '){1})[\/]?([\?|#]{1}[-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*)?[\s|\'|"]/'; + $files_ext = self::files_preg_match_all( $offloaded_pattern, $files ); + + $files_offloading = array_merge( $files_urls, $files_ext ); + + if ( ! empty( $files_offloading ) ) { + foreach ( $files_offloading as $file ) { $this->add_result_error_for_file( $result, __( 'Offloaded Content.
Offloading images, js, css, and other scripts to your servers or any remote service is disallowed.', 'plugin-check' ), From c48faa0f777cb8042bba3057090beddec36b440f Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sat, 17 Aug 2024 12:06:00 +0200 Subject: [PATCH 04/27] fixed error in merge --- includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php index b7448acee..9d0667ec7 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -115,6 +115,7 @@ protected function look_for_offloading( Check_Result $result, array $files ) { $offloaded_pattern = '/(' . implode( '|', $look_known_offloading_services ) . ')/i'; $files_urls = self::files_preg_match_all( $offloaded_pattern, $files ); + $files_urls = empty( $files_urls ) ? array() : $files_urls; // Known offloading extensions. $look_known_offloading_ext = array( @@ -135,6 +136,7 @@ protected function look_for_offloading( Check_Result $result, array $files ) { $offloading_ext = '\.' . implode( '|\.', $look_known_offloading_ext ); $offloaded_pattern = '/(https?:\/\/[www\.]?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*(' . $offloading_ext . '){1})[\/]?([\?|#]{1}[-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*)?[\s|\'|"]/'; $files_ext = self::files_preg_match_all( $offloaded_pattern, $files ); + $files_ext = empty( $files_ext ) ? array() : $files_ext; $files_offloading = array_merge( $files_urls, $files_ext ); From 6eedf4c68d10ec83d2183eca54a14259ddf222fe Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sun, 18 Aug 2024 11:30:16 +0200 Subject: [PATCH 05/27] start detecting functions offloading --- .../Plugin_Repo/Plugin_Remote_Files.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php index 9d0667ec7..87d8a8477 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -71,6 +71,8 @@ protected function check_files( Check_Result $result, array $files ) { // Looks for Kwnown External URLs. $this->look_for_offloading( $result, $php_files ); + + $this->look_functions_offloading( $result, $php_files ); } /** @@ -155,6 +157,36 @@ protected function look_for_offloading( Check_Result $result, array $files ) { } } + /** + * Looks for functions that makes remote calls. + * + * @since n.e.x.t. + * + * @param Check_Result $result The check result to amend, including the plugin context to check. + * @param array $php_files List of absolute PHP file paths. + */ + protected function look_functions_offloading( Check_Result $result, array $files ) { + $files_offloading = self::files_preg_match_all( '/wp_(register|enqueue)_(script|style)\s*\(/', $files ); + $files_offloading = empty( $files_offloading ) ? array() : $files_offloading; + + if ( ! empty( $files_offloading ) ) { + // TODO: filter functions that are using external services. + + + foreach ( $files_offloading as $file ) { + $this->add_result_error_for_file( + $result, + __( 'Offloaded Content.
Offloading images, js, css, and other scripts to your servers or any remote service is disallowed.', 'plugin-check' ), + 'external_offloaded', + $file['file'], + $file['line'], + $file['column'], + 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely' + ); + } + } + } + /** * Gets the description for the check. * From b97ac8a43b314d4a229155fabc8684ab99b830e7 Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sun, 18 Aug 2024 11:31:37 +0200 Subject: [PATCH 06/27] offloading --- includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php index 87d8a8477..545414597 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -166,6 +166,10 @@ protected function look_for_offloading( Check_Result $result, array $files ) { * @param array $php_files List of absolute PHP file paths. */ protected function look_functions_offloading( Check_Result $result, array $files ) { + + // TODO: preg_match for functions?. + + $files_offloading = self::files_preg_match_all( '/wp_(register|enqueue)_(script|style)\s*\(/', $files ); $files_offloading = empty( $files_offloading ) ? array() : $files_offloading; From 8d140d7a6376604b5e7c3cce6d027c9ebf00b989 Mon Sep 17 00:00:00 2001 From: davidperezgar Date: Sun, 18 Aug 2024 11:37:07 +0200 Subject: [PATCH 07/27] fix some typos --- .../Checks/Plugin_Repo/Plugin_Remote_Files.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php index 545414597..f1466fc12 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php @@ -17,7 +17,7 @@ /** * Check to detect plugin updater. * - * @since 1.0.0 + * @since n.e.x.t. */ class Plugin_Remote_Files extends Abstract_File_Check { @@ -27,7 +27,7 @@ class Plugin_Remote_Files extends Abstract_File_Check { /** * Bitwise flags to control check behavior. * - * @since 1.0.0 + * @since n.e.x.t. * @var int */ protected $flags = 0; @@ -35,9 +35,7 @@ class Plugin_Remote_Files extends Abstract_File_Check { /** * Constructor. * - * @since 1.0.0 - * - * @param int $flags Bitwise flags to control check behavior. + * @since n.e.x.t. */ public function __construct() { } @@ -47,7 +45,7 @@ public function __construct() { * * Every check must have at least one category. * - * @since 1.0.0 + * @since n.e.x.t. * * @return array The categories for the check. */ @@ -58,7 +56,7 @@ public function get_categories() { /** * Amends the given result by running the check on the given list of files. * - * @since 1.0.0 + * @since n.e.x.t. * * @param Check_Result $result The check result to amend, including the plugin context to check. * @param array $files List of absolute file paths. @@ -69,7 +67,7 @@ public function get_categories() { protected function check_files( Check_Result $result, array $files ) { $php_files = self::filter_files_by_extension( $files, 'php' ); - // Looks for Kwnown External URLs. + // Looks for Known External URLs. $this->look_for_offloading( $result, $php_files ); $this->look_functions_offloading( $result, $php_files ); @@ -80,8 +78,8 @@ protected function check_files( Check_Result $result, array $files ) { * * @since n.e.x.t. * - * @param Check_Result $result The check result to amend, including the plugin context to check. - * @param array $php_files List of absolute PHP file paths. + * @param Check_Result $result The check result to amend, including the plugin context to check. + * @param array $files List of absolute PHP file paths. */ protected function look_for_offloading( Check_Result $result, array $files ) { // Known offloading services. From 26e9e292459f2c5d4ae597d3c629cc8124911a7f Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 22 Aug 2024 13:18:23 +0200 Subject: [PATCH 08/27] Turn into PHPCS based sniff --- composer.json | 80 ++++--- composer.lock | 105 +++++++-- .../Checks/Plugin_Repo/Offloading_Files.php | 89 +++++++ .../Plugin_Repo/Plugin_Remote_Files.php | 217 ------------------ includes/Checker/Default_Check_Repository.php | 2 +- phpcs-sniffs/PluginCheck/ruleset.xml | 9 + phpcs-sniffs/composer.json | 72 ++++++ 7 files changed, 305 insertions(+), 269 deletions(-) create mode 100644 includes/Checker/Checks/Plugin_Repo/Offloading_Files.php delete mode 100644 includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php create mode 100644 phpcs-sniffs/PluginCheck/ruleset.xml create mode 100644 phpcs-sniffs/composer.json diff --git a/composer.json b/composer.json index ecdffd889..d6a11a3b7 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,17 @@ { "name": "wordpress/plugin-check", "description": "Plugin Check is a WordPress.org tool which provides checks to help plugins meet the directory requirements and follow various best practices.", - "type": "wordpress-plugin", "license": "GPL-2.0-or-later", + "type": "wordpress-plugin", "require": { "php": ">=7.2.24", + "ext-json": "*", + "afragen/wordpress-plugin-readme-parser": "dev-master#67fba498d0b112acf84386b95e4905c539a33f0b", + "automattic/vipwpcs": "^3.0.0", "composer/installers": "^2.2", "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0", - "wp-coding-standards/wpcs": "^3.1.0", - "automattic/vipwpcs": "^3.0.0", - "afragen/wordpress-plugin-readme-parser": "dev-master#67fba498d0b112acf84386b95e4905c539a33f0b", - "ext-json": "*" + "plugin-check/phpcs-sniffs": "@dev", + "wp-coding-standards/wpcs": "^3.1.0" }, "require-dev": { "phpcompatibility/php-compatibility": "^9.3", @@ -21,49 +22,58 @@ "szepeviktor/phpstan-wordpress": "^1.1", "wp-cli/extension-command": "^2.1", "wp-cli/wp-cli": "^2.8", - "wp-cli/wp-cli-tests": "^v4.2.9" + "wp-cli/wp-cli-tests": "^4.2.9" + }, + "repositories": [ + { + "type": "path", + "url": "./phpcs-sniffs", + "options": { + "symlink": false + } + } + ], + "autoload": { + "psr-4": { + "WordPress\\Plugin_Check\\": "includes/" + } + }, + "autoload-dev": { + "psr-4": { + "WordPress\\Plugin_Check\\Behat_Utils\\": "tests/behat/includes", + "WordPress\\Plugin_Check\\Test_Data\\": "tests/phpunit/testdata/Checks", + "WordPress\\Plugin_Check\\Test_Utils\\": "tests/phpunit/utils" + } + }, + "config": { + "allow-plugins": { + "composer/installers": true, + "cweagans/composer-patches": false, + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + }, + "platform": { + "php": "7.2.24" + } }, "scripts": { "behat": "BEHAT_FEATURES_FOLDER=tests/behat/features run-behat-tests", "behat-rerun": "BEHAT_FEATURES_FOLDER=tests/behat/features rerun-behat-tests", - "prepare-behat-tests": "install-package-tests", "format": "phpcbf --standard=phpcs.xml.dist", "lint": "phpcs --standard=phpcs.xml.dist", "phpmd": "phpmd . text phpmd.xml", "phpstan": "phpstan analyse --memory-limit=2048M", + "prepare-behat-tests": "install-package-tests", "test": "phpunit" }, "scripts-descriptions": { - "lint": "Detect coding standards issues", + "behat": "Run functional tests", + "behat-rerun": "Re-run failed functional tests", "format": "Detect and automatically fix most coding standards issues", - "test": "Run unit tests", + "lint": "Detect coding standards issues", "phpmd": "Run PHP mess detector", "phpstan": "Run static analysis", - "behat": "Run functional tests", - "behat-rerun": "Re-run failed functional tests", - "prepare-behat-tests": "Prepare functional tests" - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "composer/installers": true, - "phpstan/extension-installer": true, - "cweagans/composer-patches": false - }, - "platform": { - "php": "7.2.24" - } - }, - "autoload": { - "psr-4": { - "WordPress\\Plugin_Check\\": "includes/" - } - }, - "autoload-dev": { - "psr-4": { - "WordPress\\Plugin_Check\\Test_Data\\": "tests/phpunit/testdata/Checks", - "WordPress\\Plugin_Check\\Test_Utils\\": "tests/phpunit/utils", - "WordPress\\Plugin_Check\\Behat_Utils\\": "tests/behat/includes" - } + "prepare-behat-tests": "Prepare functional tests", + "test": "Run unit tests" } } diff --git a/composer.lock b/composer.lock index d145a4cc0..b8ad7c24b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8659a900d916eb86b5aab92af786710e", + "content-hash": "57475d38e66e7428a643b2275bdfcfba", "packages": [ { "name": "afragen/wordpress-plugin-readme-parser", @@ -547,6 +547,78 @@ ], "time": "2024-05-20T13:34:27+00:00" }, + { + "name": "plugin-check/phpcs-sniffs", + "version": "dev-486-check-calling-remote-files-js-css-images-etc-offloading-external", + "dist": { + "type": "path", + "url": "./phpcs-sniffs", + "reference": "4e233b645e1babb0aa1f9d840ba855a78b6c6e2a" + }, + "require": { + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", + "php": ">=7.0", + "phpcsstandards/phpcsutils": "^1.0.8", + "squizlabs/php_codesniffer": "^3.7.2" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^5.0 || ^6.0 || ^7.0", + "wp-coding-standards/wpcs": "^3.0" + }, + "suggest": { + "ext-mbstring": "For improved results" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-main": "2.12.x-dev" + } + }, + "scripts": { + "lint": [ + "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git" + ], + "check-cs": [ + "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs" + ], + "fix-cs": [ + "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf" + ], + "run-tests": [ + "@php ./vendor/phpunit/phpunit/phpunit --filter PluginCheck ./vendor/squizlabs/php_codesniffer/tests/AllTests.php --no-coverage" + ], + "check-all": [ + "@lint", + "@check-cs", + "@run-tests" + ] + }, + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/WordPress/plugin-check/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) for static checks in Plugin Check", + "keywords": [ + "phpcs", + "plugin-check", + "standards", + "static analysis" + ], + "transport-options": { + "symlink": false, + "relative": true + } + }, { "name": "sirbrillig/phpcs-variable-analysis", "version": "v2.11.19", @@ -954,26 +1026,26 @@ }, { "name": "composer/pcre", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "0e455b78ac53637929b29d5ab5bf3c978329c1eb" + "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/0e455b78ac53637929b29d5ab5bf3c978329c1eb", - "reference": "0e455b78ac53637929b29d5ab5bf3c978329c1eb", + "url": "https://api.github.com/repos/composer/pcre/zipball/06d0e49d6e136e4521c6bad18598bf0f6062ae37", + "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "conflict": { - "phpstan/phpstan": "<1.11.8" + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "phpstan/phpstan": "^1.11.8", + "phpstan/phpstan": "^1.11.10", "phpstan/phpstan-strict-rules": "^1.1", "phpunit/phpunit": "^8 || ^9" }, @@ -1013,7 +1085,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/2.2.0" + "source": "https://github.com/composer/pcre/tree/2.3.0" }, "funding": [ { @@ -1029,7 +1101,7 @@ "type": "tidelift" } ], - "time": "2024-07-25T09:28:32+00:00" + "time": "2024-08-19T19:14:31+00:00" }, { "name": "composer/semver", @@ -5091,16 +5163,16 @@ }, { "name": "wp-cli/config-command", - "version": "v2.3.5", + "version": "v2.3.6", "source": { "type": "git", "url": "https://github.com/wp-cli/config-command.git", - "reference": "a4ae2c73a03706b7f5b8c74426a44b4df198352c" + "reference": "82a64ae0dbd8bc91e2bf0446666ae24650223775" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/config-command/zipball/a4ae2c73a03706b7f5b8c74426a44b4df198352c", - "reference": "a4ae2c73a03706b7f5b8c74426a44b4df198352c", + "url": "https://api.github.com/repos/wp-cli/config-command/zipball/82a64ae0dbd8bc91e2bf0446666ae24650223775", + "reference": "82a64ae0dbd8bc91e2bf0446666ae24650223775", "shasum": "" }, "require": { @@ -5159,9 +5231,9 @@ "homepage": "https://github.com/wp-cli/config-command", "support": { "issues": "https://github.com/wp-cli/config-command/issues", - "source": "https://github.com/wp-cli/config-command/tree/v2.3.5" + "source": "https://github.com/wp-cli/config-command/tree/v2.3.6" }, - "time": "2024-07-22T10:31:46+00:00" + "time": "2024-08-05T13:34:06+00:00" }, { "name": "wp-cli/core-command", @@ -5764,7 +5836,8 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "afragen/wordpress-plugin-readme-parser": 20 + "afragen/wordpress-plugin-readme-parser": 20, + "plugin-check/phpcs-sniffs": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/includes/Checker/Checks/Plugin_Repo/Offloading_Files.php b/includes/Checker/Checks/Plugin_Repo/Offloading_Files.php new file mode 100644 index 000000000..4798ae97c --- /dev/null +++ b/includes/Checker/Checks/Plugin_Repo/Offloading_Files.php @@ -0,0 +1,89 @@ + 'php', + 'standard' => 'PluginCheck', + 'sniffs' => 'PluginCheck.EnqueuedResourceOffloading,PluginCheck.Offloading', + ); + } + + /** + * Gets the description for the check. + * + * Every check must have a short description explaining what the check does. + * + * @since n.e.x.t. + * + * @return string Description. + */ + public function get_description(): string { + return __( 'Prevents using remote services that are not necessary.', 'plugin-check' ); + } + + /** + * Gets the documentation URL for the check. + * + * Every check must have a URL with further information about the check. + * + * @since n.e.x.t. + * + * @return string The documentation URL. + */ + public function get_documentation_url(): string { + return __( 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely', 'plugin-check' ); + } +} diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php deleted file mode 100644 index f1466fc12..000000000 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Remote_Files.php +++ /dev/null @@ -1,217 +0,0 @@ -look_for_offloading( $result, $php_files ); - - $this->look_functions_offloading( $result, $php_files ); - } - - /** - * Looks for kwown urls that makes remote calls. - * - * @since n.e.x.t. - * - * @param Check_Result $result The check result to amend, including the plugin context to check. - * @param array $files List of absolute PHP file paths. - */ - protected function look_for_offloading( Check_Result $result, array $files ) { - // Known offloading services. - $look_known_offloading_services = array( - 'code\.jquery\.com', - '(?add_result_error_for_file( - $result, - __( 'Offloaded Content.
Offloading images, js, css, and other scripts to your servers or any remote service is disallowed.', 'plugin-check' ), - 'external_offloaded', - $file['file'], - $file['line'], - $file['column'], - 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely' - ); - } - } - } - - /** - * Looks for functions that makes remote calls. - * - * @since n.e.x.t. - * - * @param Check_Result $result The check result to amend, including the plugin context to check. - * @param array $php_files List of absolute PHP file paths. - */ - protected function look_functions_offloading( Check_Result $result, array $files ) { - - // TODO: preg_match for functions?. - - - $files_offloading = self::files_preg_match_all( '/wp_(register|enqueue)_(script|style)\s*\(/', $files ); - $files_offloading = empty( $files_offloading ) ? array() : $files_offloading; - - if ( ! empty( $files_offloading ) ) { - // TODO: filter functions that are using external services. - - - foreach ( $files_offloading as $file ) { - $this->add_result_error_for_file( - $result, - __( 'Offloaded Content.
Offloading images, js, css, and other scripts to your servers or any remote service is disallowed.', 'plugin-check' ), - 'external_offloaded', - $file['file'], - $file['line'], - $file['column'], - 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely' - ); - } - } - } - - /** - * Gets the description for the check. - * - * Every check must have a short description explaining what the check does. - * - * @since n.e.x.t. - * - * @return string Description. - */ - public function get_description(): string { - return __( 'Prevents using remote services that are not necessary.', 'plugin-check' ); - } - - /** - * Gets the documentation URL for the check. - * - * Every check must have a URL with further information about the check. - * - * @since n.e.x.t. - * - * @return string The documentation URL. - */ - public function get_documentation_url(): string { - return __( 'https://developer.wordpress.org/plugins/wordpress-org/common-issues/#calling-files-remotely', 'plugin-check' ); - } -} diff --git a/includes/Checker/Default_Check_Repository.php b/includes/Checker/Default_Check_Repository.php index ca0fb0e3d..f7f62f3be 100644 --- a/includes/Checker/Default_Check_Repository.php +++ b/includes/Checker/Default_Check_Repository.php @@ -59,7 +59,7 @@ private function register_default_checks() { 'no_unfiltered_uploads' => new Checks\Plugin_Repo\No_Unfiltered_Uploads_Check(), 'trademarks' => new Checks\Plugin_Repo\Trademarks_Check(), 'non_blocking_scripts' => new Checks\Performance\Non_Blocking_Scripts_Check(), - 'remote_files' => new Checks\Plugin_Repo\Plugin_Remote_Files(), + 'offloading_files' => new Checks\Plugin_Repo\Offloading_Files(), ) ); diff --git a/phpcs-sniffs/PluginCheck/ruleset.xml b/phpcs-sniffs/PluginCheck/ruleset.xml new file mode 100644 index 000000000..65f1cce45 --- /dev/null +++ b/phpcs-sniffs/PluginCheck/ruleset.xml @@ -0,0 +1,9 @@ + + + + Plugin Check Sniffs + + + + + diff --git a/phpcs-sniffs/composer.json b/phpcs-sniffs/composer.json new file mode 100644 index 000000000..02f5f3309 --- /dev/null +++ b/phpcs-sniffs/composer.json @@ -0,0 +1,72 @@ +{ + "name": "plugin-check/phpcs-sniffs", + "type": "phpcodesniffer-standard", + "description": "PHP_CodeSniffer rules (sniffs) for static checks in Plugin Check", + "keywords": [ + "phpcs", + "standards", + "static analysis", + "plugin-check" + ], + "license": "GPL-2.0-or-later", + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/WordPress/plugin-check/graphs/contributors" + } + ], + "require": { + "php": ">=7.0", + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", + "squizlabs/php_codesniffer": "^3.7.2", + "phpcsstandards/phpcsutils": "^1.0.8" + }, + "require-dev": { + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^5.0 || ^6.0 || ^7.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "wp-coding-standards/wpcs": "^3.0" + }, + "suggest": { + "ext-mbstring": "For improved results" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "extra": { + "branch-alias": { + "dev-main": "2.12.x-dev" + } + }, + "scripts": { + "lint": [ + "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git" + ], + "check-cs": [ + "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs" + ], + "fix-cs": [ + "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf" + ], + "run-tests": [ + "@php ./vendor/phpunit/phpunit/phpunit --filter PluginCheck ./vendor/squizlabs/php_codesniffer/tests/AllTests.php --no-coverage" + ], + "check-all": [ + "@lint", + "@check-cs", + "@run-tests" + ] + }, + "scripts-descriptions": { + "lint": "Lint PHP files against parse errors.", + "check-cs": "Run the PHPCS script against the entire codebase.", + "fix-cs": "Run the PHPCBF script to fix all the autofixable violations on the codebase.", + "run-tests": "Run all the unit tests for the Plugin Check Coding Standards sniffs.", + "check-all": "Run all checks (lint, phpcs) and tests." + } +} \ No newline at end of file From 48574fd28254a5af686bec0f2d31c57ae061a97f Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 22 Aug 2024 13:18:36 +0200 Subject: [PATCH 09/27] Add some test files --- .../load.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/phpunit/testdata/plugins/test-plugin-offloaded-files-check-with-errors/load.php diff --git a/tests/phpunit/testdata/plugins/test-plugin-offloaded-files-check-with-errors/load.php b/tests/phpunit/testdata/plugins/test-plugin-offloaded-files-check-with-errors/load.php new file mode 100644 index 000000000..18ae05645 --- /dev/null +++ b/tests/phpunit/testdata/plugins/test-plugin-offloaded-files-check-with-errors/load.php @@ -0,0 +1,29 @@ + + + + +