diff --git a/includes/Checker/Checks/Plugin_Repo/Plugin_Readme_Check.php b/includes/Checker/Checks/Plugin_Repo/Plugin_Readme_Check.php index 638f6f32b..d4cc2da9a 100644 --- a/includes/Checker/Checks/Plugin_Repo/Plugin_Readme_Check.php +++ b/includes/Checker/Checks/Plugin_Repo/Plugin_Readme_Check.php @@ -101,6 +101,9 @@ protected function check_files( Check_Result $result, array $files ) { // Check the readme file for warnings. $this->check_for_warnings( $result, $readme_file, $parser ); + + // Check the readme file for contributors. + $this->check_for_contributors( $result, $readme_file ); } /** @@ -652,6 +655,57 @@ private function check_for_warnings( Check_Result $result, string $readme_file, } } + /** + * Checks the readme file for contributors. + * + * @since 1.2.0 + * + * @param Check_Result $result The Check Result to amend. + * @param string $readme_file Readme file. + */ + private function check_for_contributors( Check_Result $result, string $readme_file ) { + $regex = '/Contributors\s?:(.*?)\R/'; + + $matches = array(); + + self::file_preg_match( $regex, array( $readme_file ), $matches ); + + // Bail if no "Contributors" found. + if ( empty( $matches ) ) { + return; + } + + $usernames = explode( ',', $matches[1] ); + + $usernames = array_map( 'trim', $usernames ); + + $valid = true; + + foreach ( $usernames as $username ) { + if ( 1 !== preg_match( '/^[a-z0-9\s_.\-@]+$/', $username ) ) { + $valid = false; + break; + } + } + + if ( ! $valid ) { + $this->add_result_warning_for_file( + $result, + sprintf( + /* translators: %s: plugin header field */ + __( 'The "%s" header in the readme file must be a comma-separated list of WordPress.org-formatted usernames.', 'plugin-check' ), + 'Contributors' + ), + 'readme_invalid_contributors', + $readme_file, + 0, + 0, + '', + 6 + ); + } + } + /** * Returns current major WordPress version. * diff --git a/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-md-with-errors/readme.md b/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-md-with-errors/readme.md index 06c49edf3..a6e6ce7e9 100644 --- a/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-md-with-errors/readme.md +++ b/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-md-with-errors/readme.md @@ -1,7 +1,7 @@ === Plugin Check === -Contributors: wordpressdotorg +Contributors: https://johndoe.com Requires at least: 6.0 Tested up to: 6.1 Requires PHP: 5.6 @@ -10,4 +10,4 @@ License: Oculus VR Inc. Software Development Kit License License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: performance, testing, security -Here is a short description of the plugin. \ No newline at end of file +Here is a short description of the plugin. diff --git a/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-parser-warnings/readme.txt b/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-parser-warnings/readme.txt index ee4efb62c..6dd95d4e8 100644 --- a/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-parser-warnings/readme.txt +++ b/tests/phpunit/testdata/plugins/test-plugin-plugin-readme-parser-warnings/readme.txt @@ -1,7 +1,7 @@ === Test Plugin Readme Errors Parser Warnings === -Contributors: plugin-check +Contributors: plugin check, wordpressdotorg Requires at least: 6.0 Tested up to: Latest Requires PHP: 5.6 diff --git a/tests/phpunit/tests/Checker/Checks/Plugin_Readme_Check_Tests.php b/tests/phpunit/tests/Checker/Checks/Plugin_Readme_Check_Tests.php index d2d4e06b4..73c63a97f 100644 --- a/tests/phpunit/tests/Checker/Checks/Plugin_Readme_Check_Tests.php +++ b/tests/phpunit/tests/Checker/Checks/Plugin_Readme_Check_Tests.php @@ -221,6 +221,7 @@ public function test_run_md_with_errors() { $this->assertCount( 1, wp_list_filter( $warnings['readme.md'][0][0], array( 'code' => 'invalid_license' ) ) ); $this->assertCount( 1, wp_list_filter( $warnings['readme.md'][0][0], array( 'code' => 'license_mismatch' ) ) ); $this->assertCount( 1, wp_list_filter( $warnings['readme.md'][0][0], array( 'code' => 'mismatched_plugin_name' ) ) ); + $this->assertCount( 1, wp_list_filter( $warnings['readme.md'][0][0], array( 'code' => 'readme_invalid_contributors' ) ) ); } public function test_single_file_plugin_without_error_for_trademarks() { @@ -479,4 +480,17 @@ public function test_run_with_errors_tested_up_to_latest_stable_version() { delete_transient( 'wp_plugin_check_latest_wp_version' ); } + + public function test_run_without_errors_readme_contributors_warning() { + $readme_check = new Plugin_Readme_Check(); + $check_context = new Check_Context( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-plugin-readme-parser-warnings/load.php' ); + $check_result = new Check_Result( $check_context ); + + $readme_check->run( $check_result ); + + $warnings = $check_result->get_warnings(); + + // Should not contain contributors warning. + $this->assertCount( 0, wp_list_filter( $warnings['readme.txt'][0][0], array( 'code' => 'readme_invalid_contributors' ) ) ); + } }