Make WordPress Core

Changeset 61466


Ignore:
Timestamp:
01/10/2026 06:28:18 PM (8 months ago)
Author:
westonruter
Message:

Widgets: Ensure a widget is registered prior to checking its ID in is_active_widget().

This avoids a possible PHP warning due to an undefined array key.

Developed in https://github.com/WordPress/wordpress-develop/pull/10710

Follow-up to [11090], [7080].

Props sageth, josephscott, Ipstenu, mindctrl, westonruter.
See #8441, #6023.
Fixes #57518.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/widgets.php

    r61432 r61466  
    926926                                foreach ( $widgets as $widget ) {
    927927                                        if ( ( $callback && isset( $wp_registered_widgets[ $widget ]['callback'] ) && $wp_registered_widgets[ $widget ]['callback'] === $callback ) || ( $id_base && _get_widget_id_base( $widget ) === $id_base ) ) {
    928                                                 if ( ! $widget_id || $widget_id === $wp_registered_widgets[ $widget ]['id'] ) {
     928                                                if ( ! $widget_id || ( isset( $wp_registered_widgets[ $widget ]['id'] ) && $widget_id === $wp_registered_widgets[ $widget ]['id'] ) ) {
    929929                                                        return $sidebar;
    930930                                                }
  • trunk/tests/phpunit/tests/widgets.php

    r60732 r61466  
    14131413                $this->assertSame( array(), $new_sidebars['primary'], 'Primary sidebar should be an empty array after normalization.' );
    14141414        }
     1415
     1416        /**
     1417         * Tests that is_active_widget() does not generate a PHP warning when
     1418         * a widget ID exists in sidebars_widgets but is not in $wp_registered_widgets,
     1419         * and the function is called with id_base and widget_id parameters.
     1420         *
     1421         * This can happen when a widget is saved to a sidebar but the widget class
     1422         * has not yet been registered (e.g., during early plugin/theme loading).
     1423         *
     1424         * @ticket 57518
     1425         * @covers ::is_active_widget
     1426         */
     1427        public function test_is_active_widget_with_unregistered_widget_and_id_base_match() {
     1428                global $wp_registered_widgets;
     1429
     1430                // Set up a sidebar with a widget that is NOT registered in $wp_registered_widgets.
     1431                update_option(
     1432                        'sidebars_widgets',
     1433                        array(
     1434                                'wp_inactive_widgets' => array(),
     1435                                'sidebar-1'           => array( 'search-2' ),
     1436                                'array_version'       => 3,
     1437                        )
     1438                );
     1439
     1440                // Ensure the widget is NOT in $wp_registered_widgets.
     1441                unset( $wp_registered_widgets['search-2'] );
     1442
     1443                /*
     1444                 * Call is_active_widget() with id_base and widget_id parameters.
     1445                 * This should NOT generate a PHP warning about accessing array offset on null.
     1446                 *
     1447                 * The bug occurs because when matching by id_base, the code checks
     1448                 * _get_widget_id_base( $widget ) === $id_base without verifying
     1449                 * $wp_registered_widgets[ $widget ] exists, then tries to access
     1450                 * $wp_registered_widgets[ $widget ]['id'] on the next line.
     1451                 */
     1452                $result = is_active_widget( false, 'search-2', 'search', true );
     1453
     1454                $this->assertFalse( $result, 'The widget is not registered, so the function should return false.' );
     1455        }
    14151456}
  • trunk/tests/phpunit/tests/widgets/wpBlockThemeRegisterClassicSidebar.php

    r55200 r61466  
    3333                global $wp_registered_sidebars;
    3434
     35                // Register a sidebar for testing if none exist.
     36                if ( empty( $wp_registered_sidebars ) ) {
     37                        register_sidebar( array( 'id' => 'test-sidebar' ) );
     38                }
     39
    3540                $sidebar_id = array_key_first( $wp_registered_sidebars );
    3641                $this->assertNotEmpty( $sidebar_id );
     
    4247        public function test_should_reregister_previous_theme_sidebar() {
    4348                global $wp_registered_sidebars;
     49
     50                // Register a sidebar for testing if none exist.
     51                if ( empty( $wp_registered_sidebars ) ) {
     52                        register_sidebar( array( 'id' => 'test-sidebar' ) );
     53                }
    4454
    4555                $sidebar_id = array_key_first( $wp_registered_sidebars );
Note: See TracChangeset for help on using the changeset viewer.