diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index c51751940a976..d2063a74a4a1e 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -2510,19 +2510,8 @@ function wp_ajax_delete_inactive_widgets() { /** This action is documented in wp-admin/widgets-form.php */ do_action( 'sidebar_admin_setup' ); - $sidebars_widgets = wp_get_sidebars_widgets(); - - foreach ( $sidebars_widgets['wp_inactive_widgets'] as $key => $widget_id ) { - $pieces = explode( '-', $widget_id ); - $multi_number = array_pop( $pieces ); - $id_base = implode( '-', $pieces ); - $widget = get_option( 'widget_' . $id_base ); - unset( $widget[ $multi_number ] ); - update_option( 'widget_' . $id_base, $widget ); - unset( $sidebars_widgets['wp_inactive_widgets'][ $key ] ); - } - - wp_set_sidebars_widgets( $sidebars_widgets ); + require_once ABSPATH . 'wp-admin/includes/widgets.php'; + wp_delete_inactive_widgets(); wp_die(); } diff --git a/src/wp-admin/includes/widgets.php b/src/wp-admin/includes/widgets.php index e751602866b0d..d9b9756fa2655 100644 --- a/src/wp-admin/includes/widgets.php +++ b/src/wp-admin/includes/widgets.php @@ -326,3 +326,32 @@ function wp_widget_control( $sidebar_args ) { function wp_widgets_access_body_class( $classes ) { return "$classes widgets_access "; } + +/** + * Removes all widgets from the inactive widgets sidebar and their corresponding settings. + * + * @since 7.2.0 + */ +function wp_delete_inactive_widgets(): void { + $sidebars_widgets = wp_get_sidebars_widgets(); + + $inactive_widgets = $sidebars_widgets['wp_inactive_widgets'] ?? array(); + if ( ! is_array( $inactive_widgets ) || 0 === count( $inactive_widgets ) ) { + return; + } + + foreach ( $inactive_widgets as $widget_id ) { + $pieces = explode( '-', $widget_id ); + $multi_number = array_pop( $pieces ); + $id_base = implode( '-', $pieces ); + $widget = get_option( 'widget_' . $id_base ); + + if ( is_array( $widget ) ) { + unset( $widget[ $multi_number ] ); + update_option( 'widget_' . $id_base, $widget ); + } + } + + $sidebars_widgets['wp_inactive_widgets'] = array(); + wp_set_sidebars_widgets( $sidebars_widgets ); +} diff --git a/src/wp-admin/widgets-form.php b/src/wp-admin/widgets-form.php index e47905c5d0099..1cf13aba5e508 100644 --- a/src/wp-admin/widgets-form.php +++ b/src/wp-admin/widgets-form.php @@ -206,17 +206,7 @@ check_admin_referer( 'remove-inactive-widgets', '_wpnonce_remove_inactive_widgets' ); if ( $_POST['removeinactivewidgets'] ) { - foreach ( $sidebars_widgets['wp_inactive_widgets'] as $key => $widget_id ) { - $pieces = explode( '-', $widget_id ); - $multi_number = array_pop( $pieces ); - $id_base = implode( '-', $pieces ); - $widget = get_option( 'widget_' . $id_base ); - unset( $widget[ $multi_number ] ); - update_option( 'widget_' . $id_base, $widget ); - unset( $sidebars_widgets['wp_inactive_widgets'][ $key ] ); - } - - wp_set_sidebars_widgets( $sidebars_widgets ); + wp_delete_inactive_widgets(); } wp_redirect( admin_url( 'widgets.php?message=0' ) ); diff --git a/tests/phpunit/tests/widgets/wpDeleteInactiveWidgets.php b/tests/phpunit/tests/widgets/wpDeleteInactiveWidgets.php new file mode 100644 index 0000000000000..31e8e5e481282 --- /dev/null +++ b/tests/phpunit/tests/widgets/wpDeleteInactiveWidgets.php @@ -0,0 +1,80 @@ +assertEmpty( wp_get_sidebars_widgets()['wp_inactive_widgets'] ); + } + + /** + * Tests that wp_delete_inactive_widgets() removes inactive widgets and their settings. + */ + public function test_wp_delete_inactive_widgets_removes_widgets() { + // Set up some inactive widgets. + $widget_id_1 = 'search-2'; + $widget_id_2 = 'text-3'; + $widget_id_3 = 'no-option-4'; + + update_option( + 'widget_search', + array( + 2 => array( + 'title' => 'Search', + ), + 3 => array( + 'title' => 'Active Search', + ), + '_multiwidget' => 1, + ) + ); + update_option( + 'widget_text', + array( + 3 => array( + 'text' => 'Some text', + ), + '_multiwidget' => 1, + ) + ); + + $sidebars_widgets = wp_get_sidebars_widgets(); + $sidebars_widgets['wp_inactive_widgets'] = array( $widget_id_1, $widget_id_2, $widget_id_3 ); + $sidebars_widgets['sidebar-1'] = array( 'search-3' ); + wp_set_sidebars_widgets( $sidebars_widgets ); + + // Run the function. + wp_delete_inactive_widgets(); + + $updated_sidebars = wp_get_sidebars_widgets(); + $this->assertEmpty( $updated_sidebars['wp_inactive_widgets'], 'Inactive widgets sidebar should be empty.' ); + $this->assertContains( 'search-3', $updated_sidebars['sidebar-1'], 'Active widgets should remain.' ); + + $search_option = get_option( 'widget_search' ); + $this->assertArrayNotHasKey( 2, $search_option, 'Inactive search widget setting should be removed.' ); + $this->assertArrayHasKey( 3, $search_option, 'Active search widget setting should remain.' ); + + $text_option = get_option( 'widget_text' ); + $this->assertArrayNotHasKey( 3, $text_option, 'Inactive text widget setting should be removed.' ); + + $this->assertFalse( get_option( 'widget_no-option' ), 'A missing widget option should not be created.' ); + } +}