Make WordPress Core

Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#53489 closed defect (bug) (fixed)

Widgets: Registered sidebar not showing in the widget editor

Reported by: walbo's profile walbo Owned by: timothyblynjacobs's profile timothyblynjacobs
Milestone: 5.8 Priority: normal
Severity: normal Version: 5.8
Component: Widgets Keywords: has-patch has-unit-tests commit
Focuses: Cc:

Description

When I register a new sidebar it doesn't show in the widget editor. I can access it from the customizer.

Once I added block in my sidebar from the customzier and saved, it shows up in the widget editor.

Steps to reproduce:

  1. Register a new sidebar. Ex:
    <?php
    register_sidebar(
      array(
        'name' => 'My sidebar',
        'id'   => 'my-sidebar',
      )
    );
    
  1. Insert the sidebar on your page. Ex in the footer.
    <?php
    if ( is_active_sidebar( 'my-sidebar' ) ) {
            dynamic_sidebar( 'my-sidebar' );
    }
    
  1. Visit wp-admin/widgets.php and My sidebar is not there.
  2. Visit the customizer widget section and confirm My sidebar is there
  3. Add a block into My sidebar from the customizer and publish.
  4. Revisit wp-admin/widgets.php and the sidebar area is visible.

Attachments (3)

53489-id-my-sidebar.png (733.2 KB) - added by hellofromTonya 3 years ago.
Reproduce testing: with id='my-sidebar' => reproduces bug
53489-id-sidebar-2.png (983.0 KB) - added by hellofromTonya 3 years ago.
Reproduce testing: with id='sidebar-2' => works
53489-test-after-pr.gif (8.6 MB) - added by hellofromTonya 3 years ago.
Testing after applying PR 1422. Results: works as expected ✅

Change History (27)

#1 @desrosj
3 years ago

  • Keywords needs-testing added
  • Milestone changed from Awaiting Review to 5.8

Moving to the milestone for investigation.

#2 @joyously
3 years ago

What hook are you using to register the sidebar?
I saw some comments that the new widget screen was changed to a different hook than it was before.
Also, has anyone tested with plugins that add sidebars, like https://wordpress.org/plugins/amr-shortcode-any-widget/ or that add fields to existing widgets like https://wordpress.org/plugins/dynamic-widgets/ ?

#3 @walbo
3 years ago

Are using widgets_init.

<?php
function twenty_twenty_one_widgets_init() {
        register_sidebar(
                array(
                        'name' => 'My sidebar',
                        'id'   => 'my-sidebar',
                )
        );
}
add_action( 'widgets_init', 'twenty_twenty_one_widgets_init' );

@hellofromTonya
3 years ago

Reproduce testing: with id='my-sidebar' => reproduces bug

@hellofromTonya
3 years ago

Reproduce testing: with id='sidebar-2' => works

#4 @hellofromTonya
3 years ago

Testing

Env:

  • OS: macOS Big Sur
  • Browser: Firefox and Chrome
  • WordPress: 5.8 Beta 3
  • Plugins: none
  • Theme: Twenty Twenty-One

Results:

  • When changing the 'id' to 'sidebar1', doesn't work ❌
  • When changing the 'id' to 'sidebar-m', doesn't work ❌

Findings:

Hmm, seems some code is doing a pattern match for the sidebar ID. Investigating 🕵️‍♀️.

#5 @walbo
3 years ago

sidebar-3 doesn't work so just sidebar-2 that works.

Does the wp install function have something to do with sidebar-2 working? https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/upgrade.php#L425

Havn't found the root cause of the bug yet.

#6 @hellofromTonya
3 years ago

Further testing

Same results on 5.8 Beta 2.

What happens when registering multiple sidebars:

<?php
        register_sidebar(
                array(
                        'name'          => esc_html__( 'My Sidebar', 'twentytwentyone' ),
                        'id'            => 'my-sidebar',
                )
        );

        register_sidebar(
                array(
                        'name'          => esc_html__( 'Sidebar #2', 'twentytwentyone' ),
                        'id'            => 'sidebar-2',
                )
        );
        
        register_sidebar(
                array(
                        'name'          => esc_html__( 'Sidebar1', 'twentytwentyone' ),
                        'id'            => 'sidebar1',
                )
        );
  • Go to Appearance > Widgets => Results: 'sidebar-2' renders but 'my-sidebar' and 'sidebar1' do not.
  • Go to another screen like Themes, then return to Widgets => Results: same
  • Go to Plugins > Add New > Classic Widgets and activate it
  • Go to Appearance > Widgets => Results: all sidebars appear
  • Go back to Plugins and deactivate the Classic Widgets plugin
  • Go back to Widgets => Results: All sidebars appear
  • Delete the new sidebars and refresh the screen => Results: the sidebars are gone
  • Add code back in and then refresh => Results: all sidebars appear again
  • Rename the ID of Sidebar #2 to sidebar-3 and refresh the screen => Results: that sidebar no longer renders
  • Repeat activating the Classic Widgets plugin, going to the Widgets screen, and then deactivating the plugin, and then going back to the Widgets screen => Results: sidebar renders as expected

#7 @hellofromTonya
3 years ago

Interesting finding:

When WP_REST_Sidebars_Controller::get_items() is invoked, here are the states:

  • global $wp_registered_sidebars has all of the sidebars registered in the theme via register_sidebar
  • get_option( 'sidebars_widgets', array() ) does not have the new sidebars as they haven't been updated yet
  • In the classic widgets-form.php, it's invoking retrieve_widgets() which updates global state to reflect only the registered sidebars. See it here.

As a test, I added retrieve_widgets() to the top of WP_REST_Sidebars_Controller::get_items() (here. Refreshed, and, bam, the registered sidebars displayed properly.

Doing testing to validate if this solves the problem without creating other problems or side effects.

This ticket was mentioned in PR #1422 on WordPress/wordpress-develop by hellofromtonya.


3 years ago
#8

  • Keywords has-patch has-unit-tests added

Trac ticket: https://core.trac.wordpress.org/ticket/53489

Uses the same strategy as the classic widgets screen by running retrieve_widgets() after wp_get_sidebars_widgets(). In doing so, newly added sidebars are displayed in the Widgets Block Editor.

#9 @hellofromTonya
3 years ago

  • Version set to trunk

PR 1422 resolves the problem by gathering all of the widgets before rendering the screen. Borrowed this strategy from the classic widgets screen. When a sidebar is newly added, it will render when the Widgets Block Editor screen loads.

@walbo can you validate if it resolves the issue for you.

Will drop ticket in appropriate channel to get feedback from the Widgets Block Editor crew.

#10 @hellofromTonya
3 years ago

  • Owner set to hellofromTonya
  • Status changed from new to assigned

Dropped into slack here for feedback.

#11 @noisysocks
3 years ago

Thanks for the patch @hellofromTonya. The code LGTM and the fix makes sense. Thanks for adding a regression test and for explaining the problem so thoughtfully. Paging @TimothyBlynJacobs in case he has any thoughts but I'm a 👍 for commit.

#12 @walbo
3 years ago

@hellofromTonya have tested the patch and it resolved the issue.

@hellofromTonya
3 years ago

Testing after applying PR 1422. Results: works as expected ✅

#13 @hellofromTonya
3 years ago

Testing after applying PR

Env:

  • OS: macOS Big Sur
  • WordPress: trunk with PR 1422 applied
  • Plugins: none
  • Theme: Twenty Twenty-One
  • Browser: Chrome (in gif), Safari, Firefox

Script:
The following code is added to wp-content/mu-plugins/test53489.php.

<?php

add_action( 'widgets_init', function() {
        register_sidebar(
                array(
                        'name'          => 'Announcements',
                        'id'            => 'announcements',
                )
        );

    register_sidebar(
                array(
                        'name'          => 'In Post CTA',
                        'id'            => 'in-post-cta',
                )
        );
} );

add_action( 'widgets_init', function() {
        register_sidebar(
                array(
                        'name'          => 'Footer 2',
                        'id'            => 'footer-2',
                )
        );

        register_sidebar(
                array(
                        'name'          => 'Footer 3',
                        'id'            => 'footer-3',
                )
        );         
}, 20 );

Test 1: Registering new sidebars:

Expected behavior:

  • Should remove the sidebar and move its widgets to the Inactive widgets sidebar.
  • No errors.

Testing steps:

  • Comment out each of the sidebars in the supplied must use file.
  • Start with a fresh install and add 2 extra posts.
  • Go to Appearance > Widgets. Notice the default sidebars: Footer and Inactive widgets. There should be no widgets in the Inactive widgets area.
  • Uncomment the Announcements sidebar in the must use file.
  • Refresh the Widgets screen. Notice the new Announcements sidebar is available.
  • Add a paragraph block to it with some test.
  • Click on Update. Then refresh the screen. => Notice: the state of the widgets is retained.
  • Repeat the process with each of the new sidebar registrations.

For my test, I also added the sidebars into the theme for them to display in the frontend and set the color to red for quick viewing.

Actual Behavior:

  • New registered sidebars appear upon refreshing or viewing the Widgets screen ✅
  • Widgets retain the location in each of the sidebars ✅
  • No console errors ✅
  • Nothing in the debug.log

Works as expected ✅

Test 2: Removing a sidebar:

Expected behavior:

  • Should remove the sidebar and move its widgets to the Inactive widgets sidebar.
  • No errors.

Testing steps:

  • Comment out the Announcements sidebar registration in the must-use plugin.
  • Refresh the Widgets screen => Notice the Announcements sidebar no longer appears in the screen or in the frontend.
  • Expand the Inactive widgets sidebar => Notice: The paragraph widget from Announcements appears in this area.
  • Repeat with each of the sidebars.

Actual behavior:

  • Sidebar is removed ✅
  • Widgets now appear in Inactive widgets sidebar ✅
  • No console errors ✅
  • Nothing in the debug.log

Works as expected ✅

TimothyBJacobs commented on PR #1422:


3 years ago
#14

We probably need to add retrieve_widgets to the other callbacks too, no?

hellofromtonya commented on PR #1422:


3 years ago
#15

We probably need to add retrieve_widgets to the other callbacks too, no?

@TimothyBJacobs such as? I'm seeing the problem anywhere else. It's updating, removing, and rendering as expected. Do you foresee another problem area that could use it?

TimothyBJacobs commented on PR #1422:


3 years ago
#16

I'm not sure to what degree Gutenberg is using those other callbacks and their responses. But if the data is missing for the get_items call, then won't it also be missing when getting a single sidebar?

hellofromtonya commented on PR #1422:


3 years ago
#17

I'm not sure to what degree Gutenberg is using those other callbacks and their responses. But if the data is missing for the get_items call, then won't it also be missing when getting a single sidebar?

Hmm, that's a good point. I'm not seeing that effect. But let me do a little bit more testing to see what happens with get_item callback.

hellofromtonya commented on PR #1422:


3 years ago
#18

I'm not sure to what degree Gutenberg is using those other callbacks and their responses. But if the data is missing for the get_items call, then won't it also be missing when getting a single sidebar?

@TimothyBJacobs In testing, seems get_item is _currently_ not called in Widgets or Customizer or in the frontend.

What if it were called in the future or by another plugin/theme?
Added it and did more testing. Also ran the test suite which passed. I think you're right. Added it to get_item() in this PR to guard against _future_ or _yet to be reported_ issues. (See commit https://github.com/WordPress/wordpress-develop/pull/1422/commits/ebef519b867f1cf82980b4a2efd0e492a83a4e82)

#19 @hellofromTonya
3 years ago

  • Keywords commit added; needs-testing removed

With multiple tests run and feedback from Timothy, marking for commit and ready for Beta 4.

TimothyBJacobs commented on PR #1422:


3 years ago
#20

Great, let's ship it!

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


3 years ago

#22 @desrosj
3 years ago

  • Owner changed from hellofromTonya to timothyblynjacobs

@timothyblynjacobs agreed to commit this later today!

#23 @TimothyBlynJacobs
3 years ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 51235:

REST API: Retrieve latest widgets before loading sidebars.

This fixes issues where sidebars would be unexpectedly missing from the new widgets screen. Running retrieve_widgets syncs sidebars that were registered after the last theme switch.

Props walbo, hellofromTonya, noisysocks.
Fixes #53489.

Note: See TracTickets for help on using tickets.