Widgets: Store default options for uninitialized widgets.

Prevent unnecessary database queries on page load by initializing widget options. On sites with uninitialized widgets, this prevents one or two database queries per uninitialized widget on each page load.

Props Chouby, mvraghavan, costdev, peterwilsoncc, spacedmonkey, mukesh27.
Fixes #54677.


git-svn-id: https://develop.svn.wordpress.org/trunk@54112 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Peter Wilson 2022-09-09 02:17:33 +00:00
parent 48f17267fb
commit f042981494
2 changed files with 63 additions and 4 deletions

View File

@ -612,12 +612,16 @@ class WP_Widget {
$settings = get_option( $this->option_name );
if ( false === $settings ) {
$settings = array();
if ( isset( $this->alt_option_name ) ) {
$settings = get_option( $this->alt_option_name );
} else {
// Save an option so it can be autoloaded next time.
$this->save_settings( array() );
// Get settings from alternative (legacy) option.
$settings = get_option( $this->alt_option_name, array() );
// Delete the alternative (legacy) option as the new option will be created using `$this->option_name`.
delete_option( $this->alt_option_name );
}
// Save an option so it can be autoloaded next time.
$this->save_settings( $settings );
}
if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) {

View File

@ -686,6 +686,61 @@ class Tests_Widgets extends WP_UnitTestCase {
$this->assertArrayNotHasKey( 0, $never_used );
}
/**
* @ticket 54677
*
* @covers WP_Widget::get_settings
*/
public function test_wp_widget_initializes_widget_with_alt_option() {
/*
* Emulate a new the recent posts widget.
*
* The widget contains an alternative (legacy) option so both the
* current and the alternative option need to be deleted.
*/
delete_option( 'widget_recent-posts' );
delete_option( 'widget_recent_entries' );
$this->assertFalse( get_option( 'widget_recent-posts' ), 'The option widget_recent-posts was not deleted.' );
$this->assertFalse( get_option( 'widget_recent_entries' ), 'The option widget_recent_entries was not deleted.' );
wp_widgets_init();
$this->assertSameSetsWithIndex( array( '_multiwidget' => 1 ), get_option( 'widget_recent-posts' ), 'Option failed to be initialized.' );
$this->assertFalse( get_option( 'widget_recent_entries' ), 'Alternative option is set.' );
}
/**
* @ticket 54677
*
* @covers WP_Widget::get_settings
*/
public function test_wp_widget_migrates_widget_with_alt_option() {
$option = array(
2 => array(
'title' => 'Recent Posts',
'number' => 5,
'show_date' => false,
),
'_multiwidget' => 1,
);
/*
* Emulate the recent posts widget with an alternative option.
*
* The widget contains an alternative (legacy) option so the
* current option is deleted while the alternative option is created.
*/
delete_option( 'widget_recent-posts' );
update_option( 'widget_recent_entries', $option );
$this->assertFalse( get_option( 'widget_recent-posts' ), 'The option widget_recent-posts was not deleted.' );
$this->assertSameSetsWithIndex( $option, get_option( 'widget_recent_entries' ), 'The option widget_recent_entries was not set to the default.' );
wp_widgets_init();
$this->assertSameSetsWithIndex( $option, get_option( 'widget_recent-posts' ), 'Option failed to be converted to new name.' );
$this->assertFalse( get_option( 'widget_recent_entries' ), 'Alternative option was not deleted.' );
}
/**
* @see WP_Widget::save_settings()
*/