WordPress.org

Make WordPress Core

Opened 7 years ago

Last modified 16 months ago

#14876 reopened defect (bug)

wp_get_sidebars_widgets() assumes that widgets are enabled

Reported by: nacin Owned by:
Milestone: Future Release Priority: lowest
Severity: minor Version:
Component: Widgets Keywords: needs-patch
Focuses: Cc:

Description

When a theme does not have any sidebars defined, wp_get_sidebars_widgets() will return the database option anyway.

This reveals a bug where a theme that does not have any widgets may still get the recent comments CSS injected into it. is_active_widget() is returning true because that widget was active when the sidebar option was last used.

Change History (14)

#1 @nacin
6 years ago

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

(In [15994]) Return empty array in wp_get_sidebars_widgets() if no sidebars are defined. fixes #14876.

#2 @nacin
6 years ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

Turns out that is_active_widget() would be called before widgets_init, inside the default widget constructors. Thus, no sidebars would be registered, and we get false returned.

Reverting [15994] for now. This was noticed when trying to add a filter to #15493.

#3 @nacin
6 years ago

(In [16521]) Revert [15994] for now, as the default widgets then go through an identity crisis. see #14876, #15493.

#4 @nacin
6 years ago

(In [16522]) Add a simple filter to allow removing the recent comments default widget styles. fixes #15493, see #14876.

#5 @nacin
6 years ago

  • Milestone changed from 3.1 to Future Release

Maybe we just need a did_action() && ! doing_action() check in there.

Not a regression. Punting.

#6 @lancewillett
3 years ago

  • Milestone changed from Future Release to 3.8

Could we get this in for 3.8? Could allows us to remove temp. hack in Authors widget: #24856 (see latest patch, line 1284).

#7 @nacin
3 years ago

  • Milestone changed from 3.8 to Future Release

Unfortunately this requires a doing_action() function, which doesn't exist yet. I'm fine with duplicating the current_theme_supports() check in the Authors widget.

#8 follow-up: @needle
3 years ago

I think the following is related to this ticket, though it may be an edge case:

I have encountered a fatal error in WP_Customize_Widgets->customize_register() when opening the Theme Customizer. This was after switching to a theme that has only one (empty) widget area. I confirmed that $sidebars_widgets in wp_get_sidebars_widgets() is not set, which throws the error when customize_register() tries to include the result in an array_merge().

Thankfully there's a filter, so I can avoid the error with the following:

/** 
 * Avoid fatal error on Theme Customizer
 */
function my_sidebars_widgets( $array ) {
	if ( !is_array( $array ) ) {
		$array = array();
	}
	return $array;
}
add_filter( 'sidebars_widgets', 'my_sidebars_widgets', 999 );

Nonetheless, it would seem that some defensiveness is necessary to ensure that an array is always returned by wp_get_sidebars_widgets() even if it is empty. Could be as simple as declaring $sidebars_widgets = array() at the top of the function.

#9 in reply to: ↑ 8 ; follow-up: @westonruter
3 years ago

Replying to needle:

I have encountered a fatal error in WP_Customize_Widgets->customize_register() when opening the Theme Customizer. This was after switching to a theme that has only one (empty) widget area. I confirmed that $sidebars_widgets in wp_get_sidebars_widgets() is not set, which throws the error when customize_register() tries to include the result in an array_merge().

Strange, because wp_get_sidebars_widgets() is supplying array() as the default fallback value if the sidebars_widgets option has not been added:

$sidebars_widgets = get_option('sidebars_widgets', array());

So it shouldn't be returning anything other than an array. What does $sidebars_widgets get set to in your environment?

#10 in reply to: ↑ 9 @needle
3 years ago

Replying to westonruter:

Replying to needle:

I have encountered a fatal error in WP_Customize_Widgets->customize_register() when opening the Theme Customizer. This was after switching to a theme that has only one (empty) widget area. I confirmed that $sidebars_widgets in wp_get_sidebars_widgets() is not set, which throws the error when customize_register() tries to include the result in an array_merge().

Strange, because wp_get_sidebars_widgets() is supplying array() as the default fallback value if the sidebars_widgets option has not been added:

$sidebars_widgets = get_option('sidebars_widgets', array());

So it shouldn't be returning anything other than an array. What does $sidebars_widgets get set to in your environment?

It seems that the sidebars_widgets option itself has been set to null. This means that the fallback value is not used and therefore $sidebars_widgets is also set to null. I realise that this means digging into why the sidebars_widgets option has a null value, but that's why I suggested this might be an edge case.

#11 follow-up: @nacin
3 years ago

We can't get a null value from the database, so if the option is returning that, then it sounds like there is a callback on a filter somewhere. Possibly even more likely is that callback is not returning anything (improperly), thus the implicit null.

#12 in reply to: ↑ 11 @needle
3 years ago

Replying to nacin:

We can't get a null value from the database, so if the option is returning that, then it sounds like there is a callback on a filter somewhere. Possibly even more likely is that callback is not returning anything (improperly), thus the implicit null.

Ah yes, good point... since option_value is longtext, the return from get_option('sidebars_widgets', array()) is actually an empty string rather than null.

I'm fairly certain that the initial error is not of WP's making. I'm trying to find out how the option came to be cleared. Nevertheless, WP does not sanity check $sidebars_widgets before returning it to array_merge in customize_register().

#14 @chriscct7
16 months ago

  • Keywords needs-patch added
Note: See TracTickets for help on using tickets.