Opened 12 years ago
Closed 12 years ago
#26897 closed defect (bug) (wontfix)
Widgets that share callback functions don't get displayed - wp_list_widgets (wp-admin/includes/widgets.php)
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Priority: | normal | |
| Severity: | normal | Version: | 3.9 |
| Component: | Widgets | Keywords: | |
| Focuses: | Cc: |
Description
Summary: When registering widgets that share the same callback function using wp_register_sidebar_widget , Wordpress will only ever display the first widget registered - all other widgets that share the callback function will be ignored. BUT all widgets are being registered - they just weren't displayed. I examined the core and the culprit lies in wp_list_widgets:
However now that we have a list of static widgets as well as custom widgets created by the user (e.g. My Custom Files Widget, My Custom Communities Widget etc), we only need one callback function - that is, each widget is registered using its unique ID, BUT a common callback function is used - this function pulls the settings from the database and then decides on what to do. A key aspect here is that the wp_register_sidebar_widget function requires the function name of the callback function as a string (it can't deal with anonymous functions).
Now to the bug: when creating custom widgets, Wordpress would only ever display the first widgets - all other widgets were being ignored. BUT all widgets were being registered - they just weren't displayed. I examined the core and the culprit lies in wp_list_widgets:
foreach ( $sort as $widget ) {
if ( in_array( $widget['callback'], $done, true ) ) // We already showed this multi-widget
continue;
$sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false );
$done[] = $widget['callback'];
if ( ! isset( $widget['params'][0] ) )
$widget['params'][0] = array();
$args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template' );
if ( isset($wp_registered_widget_controls[$widget['id']]['id_base']) && isset($widget['params'][0]['number']) ) {
$id_base = $wp_registered_widget_controls[$widget['id']]['id_base'];
$args['_temp_id'] = "$id_base-__i__";
$args['_multi_num'] = next_widget_id_number($id_base);
$args['_add'] = 'multi';
} else {
$args['_add'] = 'single';
if ( $sidebar )
$args['_hide'] = '1';
}
$args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) );
call_user_func_array( 'wp_widget_control', $args );
}
to ensure that widgets aren't being listed twice, it keeps track of those that are already being displayed using the $done array - this array however uses the callback function and NOT the widget ID. Which in essence means that users can only ever created one custom widgets - as opposed to N. Using the ID fixes this problem. i.e.
foreach ( $sort as $widget ) {
if ( in_array( $widget['callback'], $done, true ) ) // We already showed this multi-widget
continue;
$sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false );
$done[] = $widget['id'];
if ( ! isset( $widget['params'][0] ) )
$widget['params'][0] = array();
$args = array( 'widget_id' => $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template' );
if ( isset($wp_registered_widget_controls[$widget['id']]['id_base']) && isset($widget['params'][0]['number']) ) {
$id_base = $wp_registered_widget_controls[$widget['id']]['id_base'];
$args['_temp_id'] = "$id_base-__i__";
$args['_multi_num'] = next_widget_id_number($id_base);
$args['_add'] = 'multi';
} else {
$args['_add'] = 'single';
if ( $sidebar )
$args['_hide'] = '1';
}
$args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) );
call_user_func_array( 'wp_widget_control', $args );
}
Patch attached.
Attachments (1)
Change History (4)
#1
@
12 years ago
Hi Benjamin, you may have better luck with WP_Widget, which supports multiple instances and is generally just more flexible. I'm not particularly inclined to fix this as WP_Widget has been the "new" way to register a widget since early 2009, at this point.
#3
@
12 years ago
- Keywords has-patch removed
- Milestone Awaiting Review deleted
- Resolution set to wontfix
- Status changed from new to closed
I'm going to close this out per @nacin's suggestion. Thanks for the report and patch, @benjamin.jakobus. Please feel free to reopen this ticket if something is being missed.
Patch - replaced $donecallback? with $doneid?