From a26035209fb013bc4a672af595637d7f15ab08bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 22:35:44 +0000 Subject: [PATCH 1/9] Initial plan From a3ccc4d77da8a9513538d68ba8265025127b5582 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 22:39:11 +0000 Subject: [PATCH 2/9] Add --verbose flag for doctor check command Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/check.feature | 44 ++++++++++++++++++++++++++++++++++++++++++ src/Command.php | 36 +++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/features/check.feature b/features/check.feature index 998e054..e1641e0 100644 --- a/features/check.feature +++ b/features/check.feature @@ -185,3 +185,47 @@ Feature: Basic check usage And STDOUT should be a table containing rows: | name | status | | autoload-options-size | success | + + Scenario: Use --verbose flag to see check progress + Given a WP install + + When I run `wp doctor check autoload-options-size --verbose` + Then STDOUT should contain: + """ + Running check: autoload-options-size + """ + And STDOUT should contain: + """ + Status: + """ + + Scenario: Use --verbose flag with multiple checks + Given a WP install + + When I run `wp doctor check autoload-options-size core-update --verbose` + Then STDOUT should contain: + """ + Running check: autoload-options-size + """ + And STDOUT should contain: + """ + Running check: core-update + """ + + Scenario: Use --verbose flag with file checks + Given a WP install + And a wp-content/uploads/foo.php file: + """ + $args ) ); if ( empty( $checks ) ) { @@ -125,7 +130,7 @@ public function check( $args, $assoc_args ) { } $file_checks = array(); $progress = false; - if ( $all && 'table' === $assoc_args['format'] ) { + if ( $all && 'table' === $assoc_args['format'] && ! $verbose ) { $progress = Utils\make_progress_bar( 'Running checks', count( $checks ) ); } foreach ( $checks as $name => $check ) { @@ -133,12 +138,19 @@ public function check( $args, $assoc_args ) { if ( $when ) { WP_CLI::add_hook( $when, - static function () use ( $name, $check, &$completed, &$progress ) { + static function () use ( $name, $check, &$completed, &$progress, $verbose ) { + if ( $verbose ) { + WP_CLI::log( "Running check: {$name}" ); + } $check->run(); $completed[ $name ] = $check; if ( $progress ) { $progress->tick(); } + if ( $verbose ) { + $results = $check->get_results(); + WP_CLI::log( " Status: {$results['status']}" ); + } } ); } else { @@ -151,12 +163,20 @@ static function () use ( $name, $check, &$completed, &$progress ) { if ( ! empty( $file_checks ) ) { WP_CLI::add_hook( 'after_wp_config_load', - static function () use ( $file_checks, &$completed, &$progress ) { + static function () use ( $file_checks, &$completed, &$progress, $verbose ) { + if ( $verbose ) { + WP_CLI::log( 'Scanning filesystem for file checks...' ); + } try { $directory = new RecursiveDirectoryIterator( ABSPATH, RecursiveDirectoryIterator::SKIP_DOTS ); $iterator = new RecursiveIteratorIterator( $directory, RecursiveIteratorIterator::CHILD_FIRST ); $wp_content_dir = defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR : ABSPATH . 'wp-content'; + $file_count = 0; foreach ( $iterator as $file ) { + ++$file_count; + if ( $verbose && 0 === $file_count % 1000 ) { + WP_CLI::log( " Scanned {$file_count} files..." ); + } foreach ( $file_checks as $name => $check ) { $options = $check->get_options(); if ( ! empty( $options['only_wp_content'] ) @@ -174,15 +194,25 @@ static function () use ( $file_checks, &$completed, &$progress ) { $check->check_file( $file ); } } + if ( $verbose ) { + WP_CLI::log( " Total files scanned: {$file_count}" ); + } } catch ( Exception $e ) { WP_CLI::warning( $e->getMessage() ); } foreach ( $file_checks as $name => $check ) { + if ( $verbose ) { + WP_CLI::log( "Running check: {$name}" ); + } $check->run(); $completed[ $name ] = $check; if ( $progress ) { $progress->tick(); } + if ( $verbose ) { + $results = $check->get_results(); + WP_CLI::log( " Status: {$results['status']}" ); + } } } ); From 2aa3efe410a13ed00fa4bc3d8bc0a2b0a541b3d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 22:40:57 +0000 Subject: [PATCH 3/9] Extract magic number to named constant Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Command.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Command.php b/src/Command.php index b9f41d7..b5dd82c 100644 --- a/src/Command.php +++ b/src/Command.php @@ -36,6 +36,11 @@ */ class Command { + /** + * Number of files to scan before showing progress in verbose mode. + */ + const VERBOSE_FILE_SCAN_INTERVAL = 1000; + /** * Run a series of checks against WordPress to diagnose issues. * @@ -174,7 +179,7 @@ static function () use ( $file_checks, &$completed, &$progress, $verbose ) { $file_count = 0; foreach ( $iterator as $file ) { ++$file_count; - if ( $verbose && 0 === $file_count % 1000 ) { + if ( $verbose && 0 === $file_count % self::VERBOSE_FILE_SCAN_INTERVAL ) { WP_CLI::log( " Scanned {$file_count} files..." ); } foreach ( $file_checks as $name => $check ) { From 2a2a5fac664db8e732dad99dc4bb5a24c03ceec5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 17:05:38 +0000 Subject: [PATCH 4/9] Fix test: use file-based check instead of php-in-upload Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/check.feature | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/features/check.feature b/features/check.feature index e1641e0..b88d834 100644 --- a/features/check.feature +++ b/features/check.feature @@ -214,18 +214,20 @@ Feature: Basic check usage Scenario: Use --verbose flag with file checks Given a WP install - And a wp-content/uploads/foo.php file: + And a wp-content/plugins/foo.php file: """ Date: Tue, 10 Mar 2026 16:22:58 +0100 Subject: [PATCH 5/9] Update features/check.feature Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- features/check.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/check.feature b/features/check.feature index b88d834..9235a4f 100644 --- a/features/check.feature +++ b/features/check.feature @@ -202,14 +202,14 @@ Feature: Basic check usage Scenario: Use --verbose flag with multiple checks Given a WP install - When I run `wp doctor check autoload-options-size core-update --verbose` + When I run `wp doctor check autoload-options-size plugin-deactivated --verbose` Then STDOUT should contain: """ Running check: autoload-options-size """ And STDOUT should contain: """ - Running check: core-update + Running check: plugin-deactivated """ Scenario: Use --verbose flag with file checks From 95c5ec1ba7a7babbb7e3fcf801e6878e16ddbc28 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:26:16 +0000 Subject: [PATCH 6/9] Change file count wording to "items visited" for accuracy Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Command.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Command.php b/src/Command.php index 586ad06..f8b635e 100644 --- a/src/Command.php +++ b/src/Command.php @@ -176,11 +176,11 @@ static function () use ( $file_checks, &$completed, &$progress, $verbose ) { $directory = new RecursiveDirectoryIterator( ABSPATH, RecursiveDirectoryIterator::SKIP_DOTS ); $iterator = new RecursiveIteratorIterator( $directory, RecursiveIteratorIterator::CHILD_FIRST ); $wp_content_dir = defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR : ABSPATH . 'wp-content'; - $file_count = 0; + $item_count = 0; foreach ( $iterator as $file ) { - ++$file_count; - if ( $verbose && 0 === $file_count % self::VERBOSE_FILE_SCAN_INTERVAL ) { - WP_CLI::log( " Scanned {$file_count} files..." ); + ++$item_count; + if ( $verbose && 0 === $item_count % self::VERBOSE_FILE_SCAN_INTERVAL ) { + WP_CLI::log( " Visited {$item_count} items..." ); } foreach ( $file_checks as $name => $check ) { $options = $check->get_options(); @@ -200,7 +200,7 @@ static function () use ( $file_checks, &$completed, &$progress, $verbose ) { } } if ( $verbose ) { - WP_CLI::log( " Total files scanned: {$file_count}" ); + WP_CLI::log( " Total items visited: {$item_count}" ); } } catch ( Exception $e ) { WP_CLI::warning( $e->getMessage() ); From 4dd11d583c90745abe74f2bec217fe92dc5c1b23 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:21:04 +0000 Subject: [PATCH 7/9] Suppress verbose mode for non-table formats to prevent output corruption Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/check.feature | 13 +++++++++++++ src/Command.php | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/features/check.feature b/features/check.feature index 9235a4f..fa237b8 100644 --- a/features/check.feature +++ b/features/check.feature @@ -231,3 +231,16 @@ Feature: Basic check usage """ Running check: cache-flush """ + + Scenario: Verbose flag is ignored with non-table formats to prevent output corruption + Given a WP install + + When I run `wp doctor check autoload-options-size --verbose --format=json` + Then STDOUT should not contain: + """ + Running check: + """ + And STDOUT should be JSON containing: + """ + [{"name":"autoload-options-size"}] + """ diff --git a/src/Command.php b/src/Command.php index f8b635e..5a3136f 100644 --- a/src/Command.php +++ b/src/Command.php @@ -123,6 +123,10 @@ public function check( $args, $assoc_args ) { } $verbose = Utils\get_flag_value( $assoc_args, 'verbose', false ); + // Verbose mode only works with table format to avoid corrupting machine-readable output + if ( $verbose && 'table' !== $assoc_args['format'] ) { + $verbose = false; + } $completed = array(); $checks = Checks::get_checks( array( 'name' => $args ) ); From 2a4516d47d31ede3ce657410254ca84f90f46268 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 10 Mar 2026 19:39:35 +0000 Subject: [PATCH 8/9] Replace --verbose flag with WP_CLI::debug() using --debug=doctor Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/check.feature | 34 +++++++++++++--------------- src/Command.php | 51 +++++++++++++----------------------------- 2 files changed, 30 insertions(+), 55 deletions(-) diff --git a/features/check.feature b/features/check.feature index fa237b8..de5cd1f 100644 --- a/features/check.feature +++ b/features/check.feature @@ -186,33 +186,33 @@ Feature: Basic check usage | name | status | | autoload-options-size | success | - Scenario: Use --verbose flag to see check progress + Scenario: Use --debug=doctor flag to see check progress Given a WP install - When I run `wp doctor check autoload-options-size --verbose` - Then STDOUT should contain: + When I run `wp doctor check autoload-options-size --debug=doctor` + Then STDERR should contain: """ Running check: autoload-options-size """ - And STDOUT should contain: + And STDERR should contain: """ Status: """ - Scenario: Use --verbose flag with multiple checks + Scenario: Use --debug=doctor flag with multiple checks Given a WP install - When I run `wp doctor check autoload-options-size plugin-deactivated --verbose` - Then STDOUT should contain: + When I run `wp doctor check autoload-options-size plugin-deactivated --debug=doctor` + Then STDERR should contain: """ Running check: autoload-options-size """ - And STDOUT should contain: + And STDERR should contain: """ Running check: plugin-deactivated """ - Scenario: Use --verbose flag with file checks + Scenario: Use --debug=doctor flag with file checks Given a WP install And a wp-content/plugins/foo.php file: """ @@ -222,25 +222,21 @@ Feature: Basic check usage wp_cache_flush(); """ - When I run `wp doctor check cache-flush --verbose` - Then STDOUT should contain: + When I run `wp doctor check cache-flush --debug=doctor` + Then STDERR should contain: """ Scanning filesystem for file checks... """ - And STDOUT should contain: + And STDERR should contain: """ Running check: cache-flush """ - Scenario: Verbose flag is ignored with non-table formats to prevent output corruption + Scenario: Debug output does not corrupt machine-readable formats Given a WP install - When I run `wp doctor check autoload-options-size --verbose --format=json` - Then STDOUT should not contain: - """ - Running check: - """ - And STDOUT should be JSON containing: + When I run `wp doctor check autoload-options-size --debug=doctor --format=json` + Then STDOUT should be JSON containing: """ [{"name":"autoload-options-size"}] """ diff --git a/src/Command.php b/src/Command.php index 5a3136f..2f6d6db 100644 --- a/src/Command.php +++ b/src/Command.php @@ -37,9 +37,9 @@ class Command { /** - * Number of files to scan before showing progress in verbose mode. + * Number of files to scan before showing progress in debug mode. */ - const VERBOSE_FILE_SCAN_INTERVAL = 1000; + const DEBUG_FILE_SCAN_INTERVAL = 1000; /** * Run a series of checks against WordPress to diagnose issues. @@ -81,9 +81,6 @@ class Command { * - count * --- * - * [--verbose] - * : Display more information about what each check is doing. - * * ## AVAILABLE FIELDS * * These fields will be displayed by default for each check: @@ -122,12 +119,6 @@ public function check( $args, $assoc_args ) { WP_CLI::error( 'Please specify one or more checks, or use --all.' ); } - $verbose = Utils\get_flag_value( $assoc_args, 'verbose', false ); - // Verbose mode only works with table format to avoid corrupting machine-readable output - if ( $verbose && 'table' !== $assoc_args['format'] ) { - $verbose = false; - } - $completed = array(); $checks = Checks::get_checks( array( 'name' => $args ) ); if ( empty( $checks ) ) { @@ -139,7 +130,7 @@ public function check( $args, $assoc_args ) { } $file_checks = array(); $progress = false; - if ( $all && 'table' === $assoc_args['format'] && ! $verbose ) { + if ( $all && 'table' === $assoc_args['format'] ) { $progress = Utils\make_progress_bar( 'Running checks', count( $checks ) ); } foreach ( $checks as $name => $check ) { @@ -147,19 +138,15 @@ public function check( $args, $assoc_args ) { if ( $when ) { WP_CLI::add_hook( $when, - static function () use ( $name, $check, &$completed, &$progress, $verbose ) { - if ( $verbose ) { - WP_CLI::log( "Running check: {$name}" ); - } + static function () use ( $name, $check, &$completed, &$progress ) { + WP_CLI::debug( "Running check: {$name}", 'doctor' ); $check->run(); $completed[ $name ] = $check; if ( $progress ) { $progress->tick(); } - if ( $verbose ) { - $results = $check->get_results(); - WP_CLI::log( " Status: {$results['status']}" ); - } + $results = $check->get_results(); + WP_CLI::debug( " Status: {$results['status']}", 'doctor' ); } ); } else { @@ -172,10 +159,8 @@ static function () use ( $name, $check, &$completed, &$progress, $verbose ) { if ( ! empty( $file_checks ) ) { WP_CLI::add_hook( 'after_wp_config_load', - static function () use ( $file_checks, &$completed, &$progress, $verbose ) { - if ( $verbose ) { - WP_CLI::log( 'Scanning filesystem for file checks...' ); - } + static function () use ( $file_checks, &$completed, &$progress ) { + WP_CLI::debug( 'Scanning filesystem for file checks...', 'doctor' ); try { $directory = new RecursiveDirectoryIterator( ABSPATH, RecursiveDirectoryIterator::SKIP_DOTS ); $iterator = new RecursiveIteratorIterator( $directory, RecursiveIteratorIterator::CHILD_FIRST ); @@ -183,8 +168,8 @@ static function () use ( $file_checks, &$completed, &$progress, $verbose ) { $item_count = 0; foreach ( $iterator as $file ) { ++$item_count; - if ( $verbose && 0 === $item_count % self::VERBOSE_FILE_SCAN_INTERVAL ) { - WP_CLI::log( " Visited {$item_count} items..." ); + if ( 0 === $item_count % self::DEBUG_FILE_SCAN_INTERVAL ) { + WP_CLI::debug( " Visited {$item_count} items...", 'doctor' ); } foreach ( $file_checks as $name => $check ) { $options = $check->get_options(); @@ -203,25 +188,19 @@ static function () use ( $file_checks, &$completed, &$progress, $verbose ) { $check->check_file( $file ); } } - if ( $verbose ) { - WP_CLI::log( " Total items visited: {$item_count}" ); - } + WP_CLI::debug( " Total items visited: {$item_count}", 'doctor' ); } catch ( Exception $e ) { WP_CLI::warning( $e->getMessage() ); } foreach ( $file_checks as $name => $check ) { - if ( $verbose ) { - WP_CLI::log( "Running check: {$name}" ); - } + WP_CLI::debug( "Running check: {$name}", 'doctor' ); $check->run(); $completed[ $name ] = $check; if ( $progress ) { $progress->tick(); } - if ( $verbose ) { - $results = $check->get_results(); - WP_CLI::log( " Status: {$results['status']}" ); - } + $results = $check->get_results(); + WP_CLI::debug( " Status: {$results['status']}", 'doctor' ); } } ); From bbb111f3523ac73bd95748ccecc6a085a972e239 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 10 Mar 2026 21:43:34 +0100 Subject: [PATCH 9/9] Update tests --- features/check.feature | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/features/check.feature b/features/check.feature index de5cd1f..ba4eb00 100644 --- a/features/check.feature +++ b/features/check.feature @@ -189,7 +189,7 @@ Feature: Basic check usage Scenario: Use --debug=doctor flag to see check progress Given a WP install - When I run `wp doctor check autoload-options-size --debug=doctor` + When I try `wp doctor check autoload-options-size --debug=doctor` Then STDERR should contain: """ Running check: autoload-options-size @@ -202,7 +202,7 @@ Feature: Basic check usage Scenario: Use --debug=doctor flag with multiple checks Given a WP install - When I run `wp doctor check autoload-options-size plugin-deactivated --debug=doctor` + When I try `wp doctor check autoload-options-size plugin-deactivated --debug=doctor` Then STDERR should contain: """ Running check: autoload-options-size @@ -222,7 +222,7 @@ Feature: Basic check usage wp_cache_flush(); """ - When I run `wp doctor check cache-flush --debug=doctor` + When I try `wp doctor check cache-flush --debug=doctor` Then STDERR should contain: """ Scanning filesystem for file checks... @@ -231,12 +231,3 @@ Feature: Basic check usage """ Running check: cache-flush """ - - Scenario: Debug output does not corrupt machine-readable formats - Given a WP install - - When I run `wp doctor check autoload-options-size --debug=doctor --format=json` - Then STDOUT should be JSON containing: - """ - [{"name":"autoload-options-size"}] - """