diff --git a/src/wp-includes/class-wp-widget-factory.php b/src/wp-includes/class-wp-widget-factory.php index 12b4553233..9b9214e238 100644 --- a/src/wp-includes/class-wp-widget-factory.php +++ b/src/wp-includes/class-wp-widget-factory.php @@ -49,24 +49,34 @@ class WP_Widget_Factory { * Registers a widget subclass. * * @since 2.8.0 + * @since 4.6.0 The `$widget` param can also be an instance object of `WP_Widget` instead of just a `WP_Widget` subclass name. * @access public * - * @param string $widget_class The name of a WP_Widget subclass. + * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. */ - public function register( $widget_class ) { - $this->widgets[$widget_class] = new $widget_class(); + public function register( $widget ) { + if ( $widget instanceof WP_Widget ) { + $this->widgets[ spl_object_hash( $widget ) ] = $widget; + } else { + $this->widgets[ $widget ] = new $widget(); + } } /** * Un-registers a widget subclass. * * @since 2.8.0 + * @since 4.6.0 The `$widget` param can also be an instance object of `WP_Widget` instead of just a `WP_Widget` subclass name. * @access public * - * @param string $widget_class The name of a WP_Widget subclass. + * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. */ - public function unregister( $widget_class ) { - unset( $this->widgets[ $widget_class ] ); + public function unregister( $widget ) { + if ( $widget instanceof WP_Widget ) { + unset( $this->widgets[ spl_object_hash( $widget ) ] ); + } else { + unset( $this->widgets[ $widget ] ); + } } /** diff --git a/tests/phpunit/tests/widgets.php b/tests/phpunit/tests/widgets.php index 0ac6d9258d..0d0234c2b9 100644 --- a/tests/phpunit/tests/widgets.php +++ b/tests/phpunit/tests/widgets.php @@ -43,6 +43,77 @@ class Tests_Widgets extends WP_UnitTestCase { $this->assertArrayNotHasKey( $widget_class, $wp_widget_factory->widgets ); } + /** + * Test that registering a widget class and registering a widget instance work together. + * + * @see register_widget() + * @see unregister_widget() + * @ticket 28216 + */ + function test_register_and_unregister_widget_instance() { + global $wp_widget_factory, $wp_registered_widgets; + $this->assertEmpty( $wp_widget_factory->widgets ); + $this->assertEmpty( $wp_registered_widgets ); + + update_option( 'widget_search', array( + 2 => array( 'title' => '' ), + '_multiwidget' => 1, + ) ); + update_option( 'widget_better_search', array( + 3 => array( 'title' => '' ), + '_multiwidget' => 1, + ) ); + update_option( 'widget_best_search', array( + 4 => array( 'title' => '' ), + '_multiwidget' => 1, + ) ); + + register_widget( 'WP_Widget_Search' ); + $this->assertArrayHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets ); + + $widget_better_search = new WP_Widget_Search(); + $widget_better_search->id_base = 'better_search'; + $widget_better_search->name = 'Better Search'; + $widget_better_search->option_name = 'widget_' . $widget_better_search->id_base; + $widget_better_search->widget_options['classname'] = 'widget_' . $widget_better_search->id_base; + $widget_better_search->control_options['id_base'] = $widget_better_search->id_base; + register_widget( $widget_better_search ); + $this->assertArrayHasKey( spl_object_hash( $widget_better_search ), $wp_widget_factory->widgets ); + + $widget_best_search = new WP_Widget_Search(); + $widget_best_search->id_base = 'best_search'; + $widget_best_search->name = 'Best Search'; + $widget_best_search->option_name = 'widget_' . $widget_best_search->id_base; + $widget_best_search->widget_options['classname'] = 'widget_' . $widget_best_search->id_base; + $widget_best_search->control_options['id_base'] = $widget_best_search->id_base; + register_widget( $widget_best_search ); + $this->assertArrayHasKey( spl_object_hash( $widget_best_search ), $wp_widget_factory->widgets ); + + $this->assertCount( 3, $wp_widget_factory->widgets ); + $this->assertArrayHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets ); + $this->assertArrayHasKey( spl_object_hash( $widget_better_search ), $wp_widget_factory->widgets ); + $this->assertArrayHasKey( spl_object_hash( $widget_best_search ), $wp_widget_factory->widgets ); + + $wp_widget_factory->_register_widgets(); + + $this->assertArrayHasKey( 'search-2', $wp_registered_widgets ); + $this->assertArrayHasKey( 'better_search-3', $wp_registered_widgets ); + $this->assertArrayHasKey( 'best_search-4', $wp_registered_widgets ); + $this->assertInstanceOf( 'WP_Widget_Search', $wp_registered_widgets['search-2']['callback'][0] ); + $this->assertSame( $widget_better_search, $wp_registered_widgets['better_search-3']['callback'][0] ); + $this->assertSame( $widget_best_search, $wp_registered_widgets['best_search-4']['callback'][0] ); + + $this->assertArrayHasKey( spl_object_hash( $widget_better_search ), $wp_widget_factory->widgets ); + $this->assertArrayHasKey( spl_object_hash( $widget_best_search ), $wp_widget_factory->widgets ); + $this->assertArrayHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets ); + unregister_widget( 'WP_Widget_Search' ); + unregister_widget( $widget_better_search ); + unregister_widget( $widget_best_search ); + $this->assertArrayNotHasKey( spl_object_hash( $widget_better_search ), $wp_widget_factory->widgets ); + $this->assertArrayNotHasKey( spl_object_hash( $widget_best_search ), $wp_widget_factory->widgets ); + $this->assertArrayNotHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets ); + } + /** * @group sidebar */