Add class to before_widget for all widgets with a dropdown and a counter

The CSS classes are applied in the function dynamic_sidebar(). There is no specific filter for that:

// Substitute HTML id and class attributes into before_widget
$classname_ = '';
foreach ( (array) $wp_registered_widgets[$id]['classname'] as $cn ) {
    if ( is_string($cn) )
        $classname_ .= '_' . $cn;
    elseif ( is_object($cn) )
        $classname_ .= '_' . get_class($cn);
}
$classname_ = ltrim($classname_, '_');
$params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_);

But there is a filter for $params right after this code block:

$params = apply_filters( 'dynamic_sidebar_params', $params );

To get the settings for the current widget, we have to search in the global variable $wp_registered_widgets for an entry with the key $params[ 0 ][ 'widget_id' ].
If it exists, it has a class instance as callback, and we can use that object’s method get_settings() to … well … get the settings.
The returned array has probably a key that equals $params[1][ 'number' ].
Associated with this key is an array again, and here we might find another key dropdown (or count) with a value of 0 or 1.
If it is 1, we add the new classes to the string in $params[0]['before_widget'].

I think this easier to read as code:

is_admin() || add_filter( 'dynamic_sidebar_params', 'wpse_widget_classes' );

/**
 * Add classes for widgets with counters or dropdowns.
 *
 * @param  array $params
 * @return array
 */
function wpse_widget_classes( $params ) {

    global $wp_registered_widgets;

    $classes     = array();
    $instance_id = $params[1][ 'number' ];
    $widget_id   = $params[ 0 ][ 'widget_id' ];
    $settings    = $wp_registered_widgets[ $widget_id ][ 'callback' ][ 0 ]->get_settings();

    if ( empty ( $settings[ $instance_id ] ) )
        return $params;

    if ( ! empty ( $settings[ $instance_id ][ 'dropdown' ] ) )
        $classes[] = 'widget-with-dropdown';

    if ( ! empty ( $settings[ $instance_id ][ 'count' ] ) )
        $classes[] = 'widget-with-counters';

    if ( empty ( $classes ) )
        return $params;

    $params[0]['before_widget'] = str_replace(
        'class="',
        'class="' . join( ' ', $classes ) . ' ',
        $params[0]['before_widget']
    );

    return $params;
}

Leave a Comment