From 7119647971747278ee6f6e0ee06f26c0694abceb Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Sun, 9 Aug 2026 01:45:50 +0600 Subject: [PATCH 1/3] Add plugin-check-info.json manifest to suppress third-party warnings Add a standalone plugin-check-info.json manifest that lets plugin authors declare bundled third-party paths. After checks run, warning messages inside declared paths are removed from results while errors and all other findings stay untouched. The shared runner applies this to both CLI and admin check runs. Missing or invalid manifest entries are ignored, so existing behavior is preserved when no configuration exists. --- docs/README.md | 1 + docs/plugin-check-info.md | 16 +++ includes/Checker/Abstract_Check_Runner.php | 14 +++ includes/Utilities/Plugin_Config.php | 113 ++++++++++++++++++ .../phpunit/testdata/Checks/Warning_Check.php | 52 ++++++++ .../load.php | 4 + .../plugin-check-info.json | 1 + .../test-plugin-plugin-check-info/load.php | 4 + .../plugin-check-info.json | 6 + .../tests/Checker/CLI_Runner_Tests.php | 27 +++++ .../tests/Checker/Check_Result_Tests.php | 28 +++++ .../tests/Utilities/Plugin_Config_Tests.php | 43 +++++++ 12 files changed, 309 insertions(+) create mode 100644 docs/plugin-check-info.md create mode 100644 includes/Utilities/Plugin_Config.php create mode 100644 tests/phpunit/testdata/Checks/Warning_Check.php create mode 100644 tests/phpunit/testdata/plugins/test-plugin-plugin-check-info-invalid/load.php create mode 100644 tests/phpunit/testdata/plugins/test-plugin-plugin-check-info-invalid/plugin-check-info.json create mode 100644 tests/phpunit/testdata/plugins/test-plugin-plugin-check-info/load.php create mode 100644 tests/phpunit/testdata/plugins/test-plugin-plugin-check-info/plugin-check-info.json create mode 100644 tests/phpunit/tests/Utilities/Plugin_Config_Tests.php diff --git a/docs/README.md b/docs/README.md index 0e509769f..23e57419b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,7 @@ * [Available Checks](checks.md) * [AI-Powered Features & Configuration](ai-features.md) * [WordPress Functions Compatibility Data](wp-functions-compatibility-data.md) +* [Plugin Check manifest](plugin-check-info.md) * [CLI Commands](CLI.md) * [Running Unit tests](running-unit-tests.md) * [Releasing a New Version of Plugin](releasing.md) diff --git a/docs/plugin-check-info.md b/docs/plugin-check-info.md new file mode 100644 index 000000000..7720f25f2 --- /dev/null +++ b/docs/plugin-check-info.md @@ -0,0 +1,16 @@ +# Plugin Check manifest + +Plugin authors can add `plugin-check-info.json` to plugin root to identify bundled third-party code. + +```json +{ + "third_parties": [ + "vendor/phpseclib", + "libraries/legacy" + ] +} +``` + +Plugin Check keeps errors from declared paths, but hides warning-level findings for those paths. This reduces recommendations intended for plugin authors, such as replacing a library's native PHP function with a WordPress wrapper, without hiding possible errors. Findings outside declared paths remain unchanged. + +Manifest is committed with plugin code, so reviewers can inspect declarations. Missing, malformed, or invalid manifest entries are ignored. Paths are relative to plugin root and use `/` separators. Entries match their declared path and files below it, not similarly named paths. diff --git a/includes/Checker/Abstract_Check_Runner.php b/includes/Checker/Abstract_Check_Runner.php index 8f66010ac..7fe7744bb 100644 --- a/includes/Checker/Abstract_Check_Runner.php +++ b/includes/Checker/Abstract_Check_Runner.php @@ -12,6 +12,7 @@ use WordPress\Plugin_Check\Checker\Exception\Invalid_Check_Slug_Exception; use WordPress\Plugin_Check\Checker\Preparations\Universal_Runtime_Preparation; use WordPress\Plugin_Check\Traits\AI_Analyzer; +use WordPress\Plugin_Check\Utilities\Plugin_Config; use WordPress\Plugin_Check\Utilities\Plugin_Request_Utility; /** @@ -444,6 +445,19 @@ final public function run() { $results = $this->get_checks_instance()->run_checks( $this->get_check_context(), $checks, $this ); + $third_party_paths = Plugin_Config::get_third_party_paths( $this->get_check_context()->path() ); + if ( ! empty( $third_party_paths ) ) { + $results->transform_messages( + function ( $message, $is_error, $file ) use ( $third_party_paths ) { + if ( ! $is_error && Plugin_Config::is_third_party_file( $file, $third_party_paths ) ) { + return false; + } + + return $message; + } + ); + } + $ai_analysis = array(); $ai_stats = array(); diff --git a/includes/Utilities/Plugin_Config.php b/includes/Utilities/Plugin_Config.php new file mode 100644 index 000000000..b738601ae --- /dev/null +++ b/includes/Utilities/Plugin_Config.php @@ -0,0 +1,113 @@ +add_message( + false, + 'Warning message', + array( + 'code' => 'check_warning', + 'file' => 'vendor/phpseclib/file.php', + ) + ); + $check_result->add_message( + false, + 'Outside warning message', + array( + 'code' => 'check_warning_outside', + 'file' => 'includes/file.php', + ) + ); + $check_result->add_message( + true, + 'Error message', + array( + 'code' => 'check_error', + 'file' => 'vendor/phpseclib/file.php', + ) + ); + } + + public function get_categories() { + return array( Check_Categories::CATEGORY_GENERAL ); + } + + public function get_description(): string { + return ''; + } + + public function get_documentation_url(): string { + return ''; + } +} diff --git a/tests/phpunit/testdata/plugins/test-plugin-plugin-check-info-invalid/load.php b/tests/phpunit/testdata/plugins/test-plugin-plugin-check-info-invalid/load.php new file mode 100644 index 000000000..51c490e05 --- /dev/null +++ b/tests/phpunit/testdata/plugins/test-plugin-plugin-check-info-invalid/load.php @@ -0,0 +1,4 @@ +assertNotEmpty( $results->get_errors() ); } + public function test_run_filters_third_party_warnings() { + $_SERVER['argv'] = array( + 'wp', + 'plugin', + 'check', + UNIT_TESTS_PLUGIN_DIR . 'test-plugin-plugin-check-info', + '--checks=warning-check', + ); + + add_filter( + 'wp_plugin_check_checks', + function () { + return array( 'warning-check' => new Warning_Check() ); + } + ); + + $runner = new CLI_Runner(); + $cleanup = $runner->prepare(); + $this->cleanups[] = $cleanup; + $results = $runner->run(); + + $this->assertArrayNotHasKey( 'vendor/phpseclib/file.php', $results->get_warnings() ); + $this->assertArrayHasKey( 'includes/file.php', $results->get_warnings() ); + $this->assertArrayHasKey( 'vendor/phpseclib/file.php', $results->get_errors() ); + } + public function test_runner_initialized_early_throws_plugin_basename_exception() { global $wp_actions; diff --git a/tests/phpunit/tests/Checker/Check_Result_Tests.php b/tests/phpunit/tests/Checker/Check_Result_Tests.php index 3015eddc9..95466ba32 100644 --- a/tests/phpunit/tests/Checker/Check_Result_Tests.php +++ b/tests/phpunit/tests/Checker/Check_Result_Tests.php @@ -188,4 +188,32 @@ public function test_get_error_count_with_message() { $this->assertEquals( 1, $this->check_result->get_error_count() ); } + + public function test_transform_messages_removes_messages_and_updates_counts() { + $this->check_result->add_message( + false, + 'Third-party warning', + array( + 'file' => 'test-plugin/vendor/library/file.php', + ) + ); + $this->check_result->add_message( + true, + 'Third-party error', + array( + 'file' => 'test-plugin/vendor/library/file.php', + ) + ); + + $this->check_result->transform_messages( + function ( $message, $is_error, $file ) { + return $is_error || 0 !== strpos( $file, 'vendor/library/' ) ? $message : false; + } + ); + + $this->assertSame( 0, $this->check_result->get_warning_count() ); + $this->assertSame( 1, $this->check_result->get_error_count() ); + $this->assertEmpty( $this->check_result->get_warnings() ); + $this->assertNotEmpty( $this->check_result->get_errors() ); + } } diff --git a/tests/phpunit/tests/Utilities/Plugin_Config_Tests.php b/tests/phpunit/tests/Utilities/Plugin_Config_Tests.php new file mode 100644 index 000000000..9ab1b2ef3 --- /dev/null +++ b/tests/phpunit/tests/Utilities/Plugin_Config_Tests.php @@ -0,0 +1,43 @@ +assertSame( array( 'vendor/phpseclib', 'libraries/legacy' ), $paths ); + } + + public function test_get_third_party_paths_ignores_missing_config() { + $this->assertSame( array(), Plugin_Config::get_third_party_paths( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-wp-functions-compatibility-with-errors' ) ); + } + + public function test_get_third_party_paths_ignores_invalid_config() { + $this->assertSame( array(), Plugin_Config::get_third_party_paths( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-plugin-check-info-invalid' ) ); + } + + /** + * @dataProvider third_party_file_provider + */ + public function test_is_third_party_file( $file, $expected ) { + $this->assertSame( $expected, Plugin_Config::is_third_party_file( $file, array( 'vendor/phpseclib' ) ) ); + } + + public function third_party_file_provider() { + return array( + 'in declared directory' => array( 'vendor/phpseclib/Crypt/Hash.php', true ), + 'declared file' => array( 'vendor/phpseclib', true ), + 'near matching directory' => array( 'vendor/phpseclib2/Crypt/Hash.php', false ), + 'outside directory' => array( 'includes/Plugin.php', false ), + 'normalizes backslashes' => array( 'vendor\\phpseclib\\Crypt\\Hash.php', true ), + 'rejects traversal' => array( 'vendor/phpseclib/../other.php', false ), + ); + } +} From a0ea751bb3777ba13f5888682750a613c2a15574 Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Sun, 9 Aug 2026 02:09:26 +0600 Subject: [PATCH 2/3] fix(ci): resolve PHPMD NPath complexity in runner - extract third-party warning filtering from run() to filter_third_party_warnings() PHPMD: Abstract_Check_Runner run() NPath 384 over 200 threshold PHP 7.4-compatible. All CI checks passing. Refs #1439 --- includes/Checker/Abstract_Check_Runner.php | 40 +++++++++++++++------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/includes/Checker/Abstract_Check_Runner.php b/includes/Checker/Abstract_Check_Runner.php index 7fe7744bb..8ca38efa5 100644 --- a/includes/Checker/Abstract_Check_Runner.php +++ b/includes/Checker/Abstract_Check_Runner.php @@ -445,18 +445,7 @@ final public function run() { $results = $this->get_checks_instance()->run_checks( $this->get_check_context(), $checks, $this ); - $third_party_paths = Plugin_Config::get_third_party_paths( $this->get_check_context()->path() ); - if ( ! empty( $third_party_paths ) ) { - $results->transform_messages( - function ( $message, $is_error, $file ) use ( $third_party_paths ) { - if ( ! $is_error && Plugin_Config::is_third_party_file( $file, $third_party_paths ) ) { - return false; - } - - return $message; - } - ); - } + $this->filter_third_party_warnings( $results ); $ai_analysis = array(); $ai_stats = array(); @@ -487,6 +476,33 @@ function ( $message, $is_error, $file ) use ( $third_party_paths ) { return $results; } + /** + * Removes warning-level findings from declared third-party paths. + * + * Errors and findings outside declared paths are kept unchanged. + * + * @since 2.1.0 + * + * @param Check_Result $results Check results to filter, modified in place. + */ + private function filter_third_party_warnings( Check_Result $results ) { + $third_party_paths = Plugin_Config::get_third_party_paths( $this->get_check_context()->path() ); + + if ( empty( $third_party_paths ) ) { + return; + } + + $results->transform_messages( + function ( $message, $is_error, $file ) use ( $third_party_paths ) { + if ( ! $is_error && Plugin_Config::is_third_party_file( $file, $third_party_paths ) ) { + return false; + } + + return $message; + } + ); + } + /** * Determines if any of the checks are a runtime check. * From 21b313938f0ae782a38fa4c16ad677a086c52d19 Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Mon, 10 Aug 2026 14:30:14 +0600 Subject: [PATCH 3/3] feat(checker): add opt-out and visibility for third-party warning suppression Add a reviewer-visible and opt-out layer for the plugin-check-info.json manifest warning suppression, addressing the consensus concern that silently skipping vendor warnings is not acceptable. Opt-out (disable suppression to show all warnings): - CLI: --ignore-third-party-warnings flag - REST/AJAX: ignore-third-party-warnings=1 POST param - Programmatic: wp_plugin_check_ignore_third_party_warnings filter Visibility (report suppressed warnings instead of silent drop): - CLI table output shows a notice with the count of suppressed warnings - AJAX response includes suppressed_warnings count field - Check_Result tracks the count via a new property and accessors Errors from declared third-party paths remain reported. Findings outside declared paths remain unchanged. --- docs/plugin-check-info.md | 18 ++++++ includes/Admin/Admin_AJAX.php | 9 ++- includes/CLI/Plugin_Check_Command.php | 24 ++++++++ includes/Checker/Abstract_Check_Runner.php | 47 ++++++++++++++- includes/Checker/Check_Result.php | 30 ++++++++++ .../tests/Checker/CLI_Runner_Tests.php | 59 +++++++++++++++++++ .../tests/Checker/Check_Result_Tests.php | 9 +++ 7 files changed, 192 insertions(+), 4 deletions(-) diff --git a/docs/plugin-check-info.md b/docs/plugin-check-info.md index 7720f25f2..460a66ce1 100644 --- a/docs/plugin-check-info.md +++ b/docs/plugin-check-info.md @@ -1,3 +1,5 @@ +[Back to overview](./README.md) + # Plugin Check manifest Plugin authors can add `plugin-check-info.json` to plugin root to identify bundled third-party code. @@ -14,3 +16,19 @@ Plugin authors can add `plugin-check-info.json` to plugin root to identify bundl Plugin Check keeps errors from declared paths, but hides warning-level findings for those paths. This reduces recommendations intended for plugin authors, such as replacing a library's native PHP function with a WordPress wrapper, without hiding possible errors. Findings outside declared paths remain unchanged. Manifest is committed with plugin code, so reviewers can inspect declarations. Missing, malformed, or invalid manifest entries are ignored. Paths are relative to plugin root and use `/` separators. Entries match their declared path and files below it, not similarly named paths. + +## Visibility + +Suppressed warnings are reported, not silently dropped. In CLI table output, Plugin Check shows a notice with the number of suppressed warnings. The AJAX check response includes the `suppressed_warnings` count. + +## Opting out + +You can disable manifest-based suppression to show all warnings, including from declared third-party paths: + +- **CLI**: `wp plugin check --ignore-third-party-warnings`. +- **REST/AJAX**: pass `ignore-third-party-warnings=1` in the check request body. +- **Programmatic**: return `true` from the `wp_plugin_check_ignore_third_party_warnings` filter after the runner is created: + +```php +add_filter( 'wp_plugin_check_ignore_third_party_warnings', '__return_true' ); +``` diff --git a/includes/Admin/Admin_AJAX.php b/includes/Admin/Admin_AJAX.php index eef695078..69374019a 100644 --- a/includes/Admin/Admin_AJAX.php +++ b/includes/Admin/Admin_AJAX.php @@ -295,6 +295,7 @@ public function run_checks() { $include_experimental = 1 === filter_input( INPUT_POST, 'include-experimental', FILTER_VALIDATE_INT ); $use_ai = 1 === filter_input( INPUT_POST, 'use-ai', FILTER_VALIDATE_INT ); + $ignore_third_party = 1 === filter_input( INPUT_POST, 'ignore-third-party-warnings', FILTER_VALIDATE_INT ); $types = filter_input( INPUT_POST, 'types', FILTER_DEFAULT, FILTER_FORCE_ARRAY ); $types = is_null( $types ) ? array( 'error', 'warning' ) : $types; @@ -303,6 +304,7 @@ public function run_checks() { $runner->set_check_slugs( $checks ); $runner->set_plugin( $plugin ); $runner->set_use_ai( $use_ai ); + $runner->set_ignore_third_party_warnings( $ignore_third_party ); $results = $runner->run(); } catch ( Exception $error ) { wp_send_json_error( @@ -339,9 +341,10 @@ public function run_checks() { */ private function prepare_results_response( $results, array $types ) { $response = array( - 'message' => __( 'Checks run successfully', 'plugin-check' ), - 'errors' => array(), - 'warnings' => array(), + 'message' => __( 'Checks run successfully', 'plugin-check' ), + 'errors' => array(), + 'warnings' => array(), + 'suppressed_warnings' => $results->get_third_party_warning_filtered_count(), ); if ( in_array( 'error', $types, true ) ) { diff --git a/includes/CLI/Plugin_Check_Command.php b/includes/CLI/Plugin_Check_Command.php index fd10abbef..bc56b8e76 100644 --- a/includes/CLI/Plugin_Check_Command.php +++ b/includes/CLI/Plugin_Check_Command.php @@ -110,6 +110,9 @@ public function __construct( Plugin_Context $plugin_context ) { * [--ignore-errors] * : Limit displayed results to exclude errors. * + * [--ignore-third-party-warnings] + * : Do not suppress warnings from paths declared in plugin-check-info.json. + * * [--include-experimental] * : Include experimental checks. * @@ -190,6 +193,7 @@ public function check( $args, $assoc_args ) { 'format' => 'table', 'ignore-warnings' => false, 'ignore-errors' => false, + 'ignore-third-party-warnings' => false, 'include-experimental' => false, 'severity' => '', 'error-severity' => '', @@ -262,6 +266,7 @@ static function ( $dirs ) use ( $excluded_files ) { $runner->set_slug( $options['slug'] ); $runner->set_mode( $options['mode'] ); $runner->set_use_ai( $options['ai'] ); + $runner->set_ignore_third_party_warnings( (bool) $options['ignore-third-party-warnings'] ); if ( ! empty( $options['ai-model'] ) ) { $runner->set_ai_model_preference( $options['ai-model'] ); } @@ -281,6 +286,25 @@ static function ( $dirs ) use ( $excluded_files ) { Plugin_Request_Utility::destroy_runner(); + // Warn about third-party warnings suppressed by the manifest in human-readable table output. + if ( $result && 'table' === $options['format'] && empty( $options['ignore-third-party-warnings'] ) ) { + $filtered_count = $result->get_third_party_warning_filtered_count(); + if ( $filtered_count > 0 ) { + WP_CLI::warning( + sprintf( + /* translators: %d: number of suppressed warnings. */ + _n( + '%d warning was suppressed from paths declared in plugin-check-info.json (use --ignore-third-party-warnings to show it).', + '%d warnings were suppressed from paths declared in plugin-check-info.json (use --ignore-third-party-warnings to show them).', + $filtered_count, + 'plugin-check' + ), + $filtered_count + ) + ); + } + } + // Get errors and warnings from the results. $errors = array(); if ( $result && empty( $assoc_args['ignore-errors'] ) ) { diff --git a/includes/Checker/Abstract_Check_Runner.php b/includes/Checker/Abstract_Check_Runner.php index 8ca38efa5..c4b54ecde 100644 --- a/includes/Checker/Abstract_Check_Runner.php +++ b/includes/Checker/Abstract_Check_Runner.php @@ -43,6 +43,14 @@ abstract class Abstract_Check_Runner implements Check_Runner { */ protected $use_ai = false; + /** + * Whether to ignore manifest-based suppression of third-party warnings. + * + * @since 2.1.0 + * @var bool + */ + protected $ignore_third_party_warnings = false; + /** * AI model preference for analysis. * @@ -325,6 +333,17 @@ final public function set_use_ai( $use_ai ) { $this->use_ai = (bool) $use_ai; } + /** + * Sets whether to ignore manifest-based suppression of third-party warnings. + * + * @since 2.1.0 + * + * @param bool $ignore True to ignore the suppression and show all warnings, false to apply it. + */ + final public function set_ignore_third_party_warnings( $ignore ) { + $this->ignore_third_party_warnings = (bool) $ignore; + } + /** * Sets the AI model preference for analysis. * @@ -486,21 +505,47 @@ final public function run() { * @param Check_Result $results Check results to filter, modified in place. */ private function filter_third_party_warnings( Check_Result $results ) { + if ( $this->get_ignore_third_party_warnings() ) { + return; + } + $third_party_paths = Plugin_Config::get_third_party_paths( $this->get_check_context()->path() ); if ( empty( $third_party_paths ) ) { return; } + $filtered = 0; + $results->transform_messages( - function ( $message, $is_error, $file ) use ( $third_party_paths ) { + function ( $message, $is_error, $file ) use ( $third_party_paths, &$filtered ) { if ( ! $is_error && Plugin_Config::is_third_party_file( $file, $third_party_paths ) ) { + ++$filtered; return false; } return $message; } ); + + if ( $filtered > 0 ) { + $results->increment_third_party_warning_filtered_count( $filtered ); + } + } + + /** + * Determines whether manifest-based suppression of third-party warnings should be ignored. + * + * The suppression can be disabled via the runner setting or the + * `wp_plugin_check_ignore_third_party_warnings` filter. + * + * @since 2.1.0 + * + * @return bool True to ignore the suppression and show all warnings, false to apply it. + */ + private function get_ignore_third_party_warnings() { + return $this->ignore_third_party_warnings + || (bool) apply_filters( 'wp_plugin_check_ignore_third_party_warnings', false ); } /** diff --git a/includes/Checker/Check_Result.php b/includes/Checker/Check_Result.php index b2f43e033..9a868a382 100644 --- a/includes/Checker/Check_Result.php +++ b/includes/Checker/Check_Result.php @@ -56,6 +56,14 @@ final class Check_Result { */ protected $warning_count = 0; + /** + * Number of warnings suppressed from declared third-party paths. + * + * @since 2.1.0 + * @var int + */ + protected $third_party_warning_filtered_count = 0; + /** * AI analysis results for false positives. * @@ -260,6 +268,28 @@ public function get_warning_count() { return $this->warning_count; } + /** + * Increments the number of warnings suppressed from declared third-party paths. + * + * @since 2.1.0 + * + * @param int $count Number of suppressed warnings to add. Default 1. + */ + public function increment_third_party_warning_filtered_count( $count = 1 ) { + $this->third_party_warning_filtered_count += (int) $count; + } + + /** + * Returns the number of warnings suppressed from declared third-party paths. + * + * @since 2.1.0 + * + * @return int Number of suppressed warnings. + */ + public function get_third_party_warning_filtered_count() { + return $this->third_party_warning_filtered_count; + } + /** * Sets AI analysis results. * diff --git a/tests/phpunit/tests/Checker/CLI_Runner_Tests.php b/tests/phpunit/tests/Checker/CLI_Runner_Tests.php index 383c42e1b..53bb269a1 100644 --- a/tests/phpunit/tests/Checker/CLI_Runner_Tests.php +++ b/tests/phpunit/tests/Checker/CLI_Runner_Tests.php @@ -230,6 +230,65 @@ function () { $this->assertArrayNotHasKey( 'vendor/phpseclib/file.php', $results->get_warnings() ); $this->assertArrayHasKey( 'includes/file.php', $results->get_warnings() ); $this->assertArrayHasKey( 'vendor/phpseclib/file.php', $results->get_errors() ); + $this->assertSame( 1, $results->get_third_party_warning_filtered_count() ); + } + + public function test_run_ignores_third_party_filter_with_setter() { + $_SERVER['argv'] = array( + 'wp', + 'plugin', + 'check', + UNIT_TESTS_PLUGIN_DIR . 'test-plugin-plugin-check-info', + '--checks=warning-check', + ); + + add_filter( + 'wp_plugin_check_checks', + function () { + return array( 'warning-check' => new Warning_Check() ); + } + ); + + $runner = new CLI_Runner(); + $cleanup = $runner->prepare(); + $this->cleanups[] = $cleanup; + + $runner->set_ignore_third_party_warnings( true ); + $results = $runner->run(); + + $this->assertArrayHasKey( 'vendor/phpseclib/file.php', $results->get_warnings() ); + $this->assertArrayHasKey( 'includes/file.php', $results->get_warnings() ); + $this->assertArrayHasKey( 'vendor/phpseclib/file.php', $results->get_errors() ); + $this->assertSame( 0, $results->get_third_party_warning_filtered_count() ); + } + + public function test_run_ignores_third_party_filter_with_hook() { + $_SERVER['argv'] = array( + 'wp', + 'plugin', + 'check', + UNIT_TESTS_PLUGIN_DIR . 'test-plugin-plugin-check-info', + '--checks=warning-check', + ); + + add_filter( + 'wp_plugin_check_checks', + function () { + return array( 'warning-check' => new Warning_Check() ); + } + ); + + add_filter( 'wp_plugin_check_ignore_third_party_warnings', '__return_true' ); + + $runner = new CLI_Runner(); + $cleanup = $runner->prepare(); + $this->cleanups[] = $cleanup; + $results = $runner->run(); + + $this->assertArrayHasKey( 'vendor/phpseclib/file.php', $results->get_warnings() ); + $this->assertArrayHasKey( 'includes/file.php', $results->get_warnings() ); + $this->assertArrayHasKey( 'vendor/phpseclib/file.php', $results->get_errors() ); + $this->assertSame( 0, $results->get_third_party_warning_filtered_count() ); } public function test_runner_initialized_early_throws_plugin_basename_exception() { diff --git a/tests/phpunit/tests/Checker/Check_Result_Tests.php b/tests/phpunit/tests/Checker/Check_Result_Tests.php index 95466ba32..fc13e5e0a 100644 --- a/tests/phpunit/tests/Checker/Check_Result_Tests.php +++ b/tests/phpunit/tests/Checker/Check_Result_Tests.php @@ -216,4 +216,13 @@ function ( $message, $is_error, $file ) { $this->assertEmpty( $this->check_result->get_warnings() ); $this->assertNotEmpty( $this->check_result->get_errors() ); } + + public function test_third_party_warning_filtered_count_increments() { + $this->assertSame( 0, $this->check_result->get_third_party_warning_filtered_count() ); + + $this->check_result->increment_third_party_warning_filtered_count(); + $this->check_result->increment_third_party_warning_filtered_count(); + + $this->assertSame( 2, $this->check_result->get_third_party_warning_filtered_count() ); + } }