Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e3f59a1
Refactor: Extract `wp_delete_inactive_widgets()` for reuse in widget …
Jun 4, 2026
fb40fd9
Change version number to 7.1.0 in docblock
pbearne Jun 5, 2026
a4da520
Add void return type to wp_delete_inactive_widgets()
t-hamano Aug 2, 2026
3fab2e4
Simplify inactive widgets guard clause using null coalescing
t-hamano Aug 2, 2026
6904654
Empty inactive widgets array instead of unsetting each key
t-hamano Aug 2, 2026
ab7e373
Update src/wp-admin/includes/widgets.php
pbearne Aug 11, 2026
7ea85a4
Merge branch 'trunk' into impove-wp_delete_inactive_widgets-routine
pbearne Aug 11, 2026
34c7eca
Refactor: Replace inlined widget cleanup logic with `wp_delete_inacti…
Aug 11, 2026
dc5a171
Apply suggestions from code review
pbearne Aug 14, 2026
6054978
Update widgets-form.php
pbearne Aug 14, 2026
ac8dd6d
Add unit tests for `wp_delete_inactive_widgets()` functionality
Aug 14, 2026
5304460
Merge remote-tracking branch 'origin/impove-wp_delete_inactive_widget…
Aug 14, 2026
12f1e2b
Merge branch 'trunk' into impove-wp_delete_inactive_widgets-routine
pbearne Aug 14, 2026
ea76949
Format widget option updates in unit tests for better readability
Aug 14, 2026
8865b8f
Merge remote-tracking branch 'origin/impove-wp_delete_inactive_widget…
Aug 14, 2026
bcdbcca
Align indentation in `wp_delete_inactive_widgets` unit tests for cons…
Aug 14, 2026
32a4737
Potential fix for pull request finding
t-hamano Aug 18, 2026
4b97587
Tests: Remove the redundant `widgets.php` require in the inactive wid…
t-hamano Aug 18, 2026
1ccf2df
Coding Standards: Add a blank line after `set_up()` in the inactive w…
t-hamano Aug 18, 2026
0728eb6
Tests: Remove a redundant `widget_search` option update in the inacti…
t-hamano Aug 18, 2026
4fa891b
Tests: Assert that a widget without a stored option is not created on…
t-hamano Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions src/wp-admin/includes/ajax-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
29 changes: 29 additions & 0 deletions src/wp-admin/includes/widgets.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
12 changes: 1 addition & 11 deletions src/wp-admin/widgets-form.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Comment thread
pbearne marked this conversation as resolved.

wp_redirect( admin_url( 'widgets.php?message=0' ) );
Expand Down
80 changes: 80 additions & 0 deletions tests/phpunit/tests/widgets/wpDeleteInactiveWidgets.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

/**
* Test wp_delete_inactive_widgets().
*
* @group widgets
* @covers ::wp_delete_inactive_widgets
*/
class Tests_Widgets_WpDeleteInactiveWidgets extends WP_UnitTestCase {
public function set_up() {
parent::set_up();
require_once ABSPATH . 'wp-admin/includes/widgets.php';
}

/**
* Tests that wp_delete_inactive_widgets() does nothing when there are no inactive widgets.
*/
public function test_wp_delete_inactive_widgets_empty() {
$sidebars_widgets = wp_get_sidebars_widgets();
$sidebars_widgets['wp_inactive_widgets'] = array();
wp_set_sidebars_widgets( $sidebars_widgets );

wp_delete_inactive_widgets();

$this->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.' );
}
}
Loading