[wp-trac] [WordPress Trac] #26897: Widgets that share callback functions don't get displayed - wp_list_widgets (wp-admin/includes/widgets.php)

WordPress Trac noreply at wordpress.org
Tue Jan 21 11:51:06 UTC 2014


#26897: Widgets that share callback functions don't get displayed - wp_list_widgets
(wp-admin/includes/widgets.php)
------------------------------+-----------------------------
 Reporter:  benjamin.jakobus  |      Owner:
     Type:  defect (bug)      |     Status:  new
 Priority:  normal            |  Milestone:  Awaiting Review
Component:  Widgets           |    Version:  trunk
 Severity:  normal            |   Keywords:  has-patch
------------------------------+-----------------------------
 '''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.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/26897>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list