diff --git a/features/sidebar.feature b/features/sidebar.feature index 5e5d4315..cf56f6a1 100644 --- a/features/sidebar.feature +++ b/features/sidebar.feature @@ -23,6 +23,27 @@ Feature: Manage WordPress sidebars 4 """ + Scenario: List inactive sidebars + When I run `wp sidebar list --inactive --format=count` + Then STDOUT should be: + """ + 0 + """ + + When I run `wp eval 'update_option( "sidebars_widgets", array_merge( wp_get_sidebars_widgets(), [ "orphaned-sidebar-1" => [] ] ) );'` + And I run `wp sidebar list --inactive --fields=id --format=csv` + Then STDOUT should be: + """ + id + orphaned-sidebar-1 + """ + + When I run `wp sidebar list --fields=id --format=ids` + Then STDOUT should not contain: + """ + orphaned-sidebar-1 + """ + Scenario: Get sidebar details When I run `wp sidebar get sidebar-1` Then STDOUT should contain: diff --git a/features/widget-reset.feature b/features/widget-reset.feature index 917caef8..6f923dc1 100644 --- a/features/widget-reset.feature +++ b/features/widget-reset.feature @@ -24,7 +24,7 @@ Feature: Reset WordPress sidebars When I try `wp widget reset` Then STDERR should be: """ - Error: Please specify one or more sidebars, or use --all. + Error: Please specify one or more sidebars, or use --all or --inactive. """ When I try `wp widget reset sidebar-1` @@ -153,3 +153,37 @@ Feature: Reset WordPress sidebars """ calendar-1 search-1 """ + + Scenario: Reset inactive sidebars + When I try `wp widget reset --inactive` + Then STDERR should be: + """ + Error: No inactive sidebars found. + """ + And the return code should be 1 + + When I run `wp widget add calendar sidebar-1 --title="Calendar"` + Then STDOUT should not be empty + + # Simulate an inactive (unregistered) sidebar by moving widget data to an orphaned key + When I run `wp eval '$w = wp_get_sidebars_widgets(); $w["orphaned-sidebar-1"] = $w["sidebar-1"]; $w["sidebar-1"] = []; update_option( "sidebars_widgets", $w );'` + + And I run `wp sidebar list --inactive --fields=id --format=ids` + Then STDOUT should be: + """ + orphaned-sidebar-1 + """ + + When I run `wp widget reset --inactive` + Then STDOUT should be: + """ + Sidebar 'orphaned-sidebar-1' reset. + Success: Reset 1 of 1 sidebars. + """ + And the return code should be 0 + + When I run `wp widget list wp_inactive_widgets --format=ids` + Then STDOUT should contain: + """ + calendar-1 + """ diff --git a/src/Sidebar_Command.php b/src/Sidebar_Command.php index 03a15b73..aa8439d4 100644 --- a/src/Sidebar_Command.php +++ b/src/Sidebar_Command.php @@ -29,6 +29,9 @@ class Sidebar_Command extends WP_CLI_Command { * * ## OPTIONS * + * [--inactive] + * : If set, only inactive sidebars will be listed. + * * [--fields=] * : Limit the output to specific object fields. * @@ -68,6 +71,10 @@ class Sidebar_Command extends WP_CLI_Command { * "Widget Area",sidebar-1 * "Inactive Widgets",wp_inactive_widgets * + * $ wp sidebar list --inactive --fields=id --format=csv + * id + * old-sidebar-1 + * * @subcommand list */ public function list_( $args, $assoc_args ) { @@ -75,16 +82,62 @@ public function list_( $args, $assoc_args ) { Utils\wp_register_unused_sidebar(); - if ( ! empty( $assoc_args['format'] ) && 'ids' === $assoc_args['format'] ) { - $sidebars = wp_list_pluck( $wp_registered_sidebars, 'id' ); + $inactive = Utils\get_flag_value( $assoc_args, 'inactive', false ); + + if ( $inactive ) { + $sidebars = []; + foreach ( self::get_inactive_sidebar_ids() as $sidebar_id ) { + $sidebars[ $sidebar_id ] = [ + 'name' => $sidebar_id, + 'id' => $sidebar_id, + 'description' => '', + 'class' => '', + 'before_widget' => '', + 'after_widget' => '', + 'before_title' => '', + 'after_title' => '', + ]; + } } else { $sidebars = $wp_registered_sidebars; } + if ( ! empty( $assoc_args['format'] ) && 'ids' === $assoc_args['format'] ) { + $sidebars = wp_list_pluck( $sidebars, 'id' ); + } + $formatter = new Formatter( $assoc_args, $this->fields ); $formatter->display_items( $sidebars ); } + /** + * Returns the IDs of sidebars that exist in the database but are not currently registered. + * + * @return string[] + */ + public static function get_inactive_sidebar_ids() { + global $wp_registered_sidebars; + + $sidebars_widgets = get_option( 'sidebars_widgets', [] ); + if ( ! is_array( $sidebars_widgets ) ) { + $sidebars_widgets = []; + } + if ( isset( $sidebars_widgets['array_version'] ) ) { + unset( $sidebars_widgets['array_version'] ); + } + + $registered_ids = array_keys( $wp_registered_sidebars ); + + return array_values( + array_filter( + array_diff( array_keys( $sidebars_widgets ), $registered_ids ), + static function ( $id ) { + return 'wp_inactive_widgets' !== $id; + } + ) + ); + } + /** * Get details about a specific sidebar. * diff --git a/src/Widget_Command.php b/src/Widget_Command.php index 8b8619f7..4eed6ebd 100644 --- a/src/Widget_Command.php +++ b/src/Widget_Command.php @@ -478,53 +478,85 @@ public function delete( $args, $assoc_args ) { * [--all] * : If set, all sidebars will be reset. * + * [--inactive] + * : If set, all inactive sidebars will also be reset, in addition to any sidebars specified via ... or selected with --all. + * * ## EXAMPLES * * # Reset a sidebar * $ wp widget reset sidebar-1 - * Success: Sidebar 'sidebar-1' reset. + * Sidebar 'sidebar-1' reset. * * # Reset multiple sidebars * $ wp widget reset sidebar-1 sidebar-2 - * Success: Sidebar 'sidebar-1' reset. - * Success: Sidebar 'sidebar-2' reset. + * Sidebar 'sidebar-1' reset. + * Sidebar 'sidebar-2' reset. * * # Reset all sidebars * $ wp widget reset --all - * Success: Sidebar 'sidebar-1' reset. - * Success: Sidebar 'sidebar-2' reset. - * Success: Sidebar 'sidebar-3' reset. + * Sidebar 'sidebar-1' reset. + * Sidebar 'sidebar-2' reset. + * Sidebar 'sidebar-3' reset. + * + * # Reset all inactive sidebars + * $ wp widget reset --inactive + * Sidebar 'old-sidebar-1' reset. */ public function reset( $args, $assoc_args ) { global $wp_registered_sidebars; - $all = Utils\get_flag_value( $assoc_args, 'all', false ); + $all = Utils\get_flag_value( $assoc_args, 'all', false ); + $inactive = Utils\get_flag_value( $assoc_args, 'inactive', false ); - // Bail if no arguments and no all flag. - if ( ! $all && empty( $args ) ) { - WP_CLI::error( 'Please specify one or more sidebars, or use --all.' ); + // Bail if no arguments and no --all or --inactive flag. + if ( ! $all && ! $inactive && empty( $args ) ) { + WP_CLI::error( 'Please specify one or more sidebars, or use --all or --inactive.' ); } - // Fetch all sidebars if all flag is set. + // Explicitly handle reserved sidebar ID for inactive widgets. + if ( in_array( 'wp_inactive_widgets', $args, true ) ) { + WP_CLI::error( "Sidebar 'wp_inactive_widgets' is reserved for inactive widgets and cannot be reset with this command. The --inactive flag only targets widgets from orphaned or unregistered sidebars, not 'wp_inactive_widgets' itself." ); + } + + // Fetch all registered sidebars if --all flag is set. if ( $all ) { $args = array_keys( $wp_registered_sidebars ); } // Sidebar ID wp_inactive_widgets is reserved by WP core for inactive widgets. - if ( isset( $args['wp_inactive_widgets'] ) ) { - unset( $args['wp_inactive_widgets'] ); + $args = array_values( + array_filter( + $args, + static function ( $id ) { + return 'wp_inactive_widgets' !== $id; + } + ) + ); + + // Collect inactive (unregistered) sidebar IDs if --inactive flag is set. + $inactive_args = []; + if ( $inactive ) { + $inactive_args = Sidebar_Command::get_inactive_sidebar_ids(); } - // Check if no registered sidebar. - if ( empty( $args ) ) { + $all_args = array_merge( $args, $inactive_args ); + $all_args = array_values( array_unique( $all_args ) ); + + // Check if there are no sidebars to reset. + if ( empty( $all_args ) ) { + if ( $inactive && empty( $inactive_args ) ) { + WP_CLI::error( 'No inactive sidebars found.' ); + } WP_CLI::error( 'No sidebar registered.' ); } $count = 0; $errors = 0; - foreach ( $args as $sidebar_id ) { - if ( ! array_key_exists( $sidebar_id, $wp_registered_sidebars ) ) { + foreach ( $all_args as $sidebar_id ) { + // Skip registration validation for sidebars resolved via --inactive. + if ( ! in_array( $sidebar_id, $inactive_args, true ) && + ! array_key_exists( $sidebar_id, $wp_registered_sidebars ) ) { WP_CLI::warning( sprintf( 'Invalid sidebar: %s', $sidebar_id ) ); ++$errors; continue; @@ -550,7 +582,7 @@ public function reset( $args, $assoc_args ) { } } - Utils\report_batch_operation_results( 'sidebar', 'reset', count( $args ), $count, $errors ); + Utils\report_batch_operation_results( 'sidebar', 'reset', count( $all_args ), $count, $errors ); } /**