diff --git a/src/wp-includes/class-wp-widget-factory.php b/src/wp-includes/class-wp-widget-factory.php index 9b9214e238..ae721542dd 100644 --- a/src/wp-includes/class-wp-widget-factory.php +++ b/src/wp-includes/class-wp-widget-factory.php @@ -45,6 +45,50 @@ class WP_Widget_Factory { self::__construct(); } + /** + * Memory for the number of times unique class instances have been hashed. + * + * This can be eliminated in favor of straight spl_object_hash() when 5.3 + * is the minimum requirement for PHP. + * + * @since 4.6.0 + * @access private + * @see WP_Widget_Factory::hash_object() + * + * @var array + */ + private $hashed_class_counts = array(); + + /** + * Hash an object, doing fallback of `spl_object_hash()` if not available. + * + * This can be eliminated in favor of straight spl_object_hash() when 5.3 + * is the minimum requirement for PHP. + * + * @since 4.6.0 + * @access private + * + * @param WP_Widget $widget Widget. + * @return string Object hash. + */ + private function hash_object( $widget ) { + if ( function_exists( 'spl_object_hash' ) ) { + return spl_object_hash( $widget ); + } else { + $class_name = get_class( $widget ); + $hash = $class_name; + if ( ! isset( $widget->_wp_widget_factory_hash_id ) ) { + if ( ! isset( $this->hashed_class_counts[ $class_name ] ) ) { + $this->hashed_class_counts[ $class_name ] = 0; + } + $this->hashed_class_counts[ $class_name ] += 1; + $widget->_wp_widget_factory_hash_id = $this->hashed_class_counts[ $class_name ]; + } + $hash .= ':' . $widget->_wp_widget_factory_hash_id; + return $hash; + } + } + /** * Registers a widget subclass. * @@ -56,7 +100,7 @@ class WP_Widget_Factory { */ public function register( $widget ) { if ( $widget instanceof WP_Widget ) { - $this->widgets[ spl_object_hash( $widget ) ] = $widget; + $this->widgets[ $this->hash_object( $widget ) ] = $widget; } else { $this->widgets[ $widget ] = new $widget(); } @@ -73,7 +117,7 @@ class WP_Widget_Factory { */ public function unregister( $widget ) { if ( $widget instanceof WP_Widget ) { - unset( $this->widgets[ spl_object_hash( $widget ) ] ); + unset( $this->widgets[ $this->hash_object( $widget ) ] ); } else { unset( $this->widgets[ $widget ] ); } diff --git a/tests/phpunit/tests/widgets.php b/tests/phpunit/tests/widgets.php index 0d0234c2b9..d0fe7ca9cb 100644 --- a/tests/phpunit/tests/widgets.php +++ b/tests/phpunit/tests/widgets.php @@ -78,7 +78,7 @@ class Tests_Widgets extends WP_UnitTestCase { $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 ); + $this->assertContains( $widget_better_search, $wp_widget_factory->widgets ); $widget_best_search = new WP_Widget_Search(); $widget_best_search->id_base = 'best_search'; @@ -87,12 +87,12 @@ class Tests_Widgets extends WP_UnitTestCase { $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->assertContains( $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 ); + $this->assertContains( $widget_better_search, $wp_widget_factory->widgets ); + $this->assertContains( $widget_best_search, $wp_widget_factory->widgets ); $wp_widget_factory->_register_widgets(); @@ -103,14 +103,14 @@ class Tests_Widgets extends WP_UnitTestCase { $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->assertContains( $widget_better_search, $wp_widget_factory->widgets ); + $this->assertContains( $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->assertNotContains( $widget_better_search, $wp_widget_factory->widgets ); + $this->assertNotContains( $widget_best_search, $wp_widget_factory->widgets ); $this->assertArrayNotHasKey( 'WP_Widget_Search', $wp_widget_factory->widgets ); }