Añadir un div para envolver el contenido del widget después del título
Estoy intentando añadir un div al contenido de un widget en mi barra lateral dinámica.
Aquí está el código de registro:
register_sidebar(array(
'name' => "Sidebar1",
'id' => 'home-sidebar-1',
'before_widget' => '<div class="sidebar-box">',
'after_widget' => '</div>',
'before_title' => '<div class="title">',
'after_title' => '</div><div class="content">',
));
Pero este código genera esto:
<div class="sidebar-box">
<div class="title">{TÍTULO DEL WIDGET}</div>
{CONTENIDO DEL WIDGET}
</div>
Esto es lo que estoy tratando de lograr:
<div class="sidebar-box">
<div class="title">{TÍTULO DEL WIDGET}</div>
<div class="content">
{CONTENIDO DEL WIDGET}
</div>
</div>
¿Cómo se puede hacer?

Además de la respuesta de Toscho, aquí está lo que necesitas para una solución robusta:
// si no hay título, entonces añade el contenedor de contenido del widget antes del widget
add_filter( 'dynamic_sidebar_params', 'check_sidebar_params' );
function check_sidebar_params( $params ) {
global $wp_registered_widgets;
$settings_getter = $wp_registered_widgets[ $params[0]['widget_id'] ]['callback'][0];
$settings = $settings_getter->get_settings();
$settings = $settings[ $params[1]['number'] ];
if ( $params[0][ 'after_widget' ] == '</div></div>' && isset( $settings[ 'title' ] ) && empty( $settings[ 'title' ] ) )
$params[0][ 'before_widget' ] .= '<div class="content">';
return $params;
}
De la respuesta de Toscho:
register_sidebar(array(
'name' => "Sidebar1",
'id' => 'home-sidebar-1',
'before_widget' => '<div class="sidebar-box">',
'after_widget' => '</div></div>',
'before_title' => '<div class="title">',
'after_title' => '</div><div class="content">',
));
Lo que esto hace es:
- verifica la configuración de la barra lateral registrada para widgets que terminan con 2 cierres de
<div>
- comprueba si no hay título
- si no lo hay, modifica la salida de
before_widget
para mostrar el div de apertura del contenido del widget
Podrías usar este enfoque para cambiar los argumentos de la barra lateral de otras formas basadas en la configuración de la instancia del widget.

Tengo un problema con eso: algunos widgets (como los predeterminados de WP, por ejemplo) establecen un título por defecto si lo dejas en blanco. Entonces tu función añade el div porque no hay un título en los parámetros en ese momento, pero el widget lo añade después y el código queda desordenado. ¿Sabes cómo verificar el título "desde dentro" del widget? Gracias

No sin añadir una verificación widget por widget o algún código terriblemente complejo para renderizar el widget en silencio y luego analizarlo en busca de un título... Lo pensaré

¿Quizás engancharse a esto http://codex.wordpress.org/Function_Reference/the_widget ayudaría? Lo usan (por otro motivo) en este artículo http://wp.smashingmagazine.com/2012/12/11/inserting-widgets-with-shortcodes/

Me gustó la idea de ambas respuestas de @tosco y @sanchothefat, sin embargo tuve problemas con esa combinación porque aunque empty( $settings[ 'title' ]
podría devolver verdadero, el widget en sí podría mostrar un título por defecto si no se establece ninguno. Este título luego se envuelve en el marcado before_title
y after_title
y de nuevo la página se rompe. Ese es el caso con algunos de los widgets por defecto de WordPress.
Es más fácil simplemente apegarse a los parámetros estándar de registro de widgets:
register_sidebar(array(
'id' => 'sidebar1',
'name' => __( 'Sidebar 1', 'bonestheme' ),
'description' => __( 'The first (primary) sidebar.', 'bonestheme' ),
'before_widget' => '<div class="block">',
'after_widget' => '</div>',
'before_title' => '<div class="block-title">',
'after_title' => '</div>',
));
Y luego añadir una acción de filtro como en la respuesta de Marventus aquí:
http://wordpress.org/support/topic/add-html-wrapper-around-widget-content
function widget_content_wrap($content) {
$content = '<div class="block-content">'.$content.'</div>';
return $content;
}
add_filter('widget_text', 'widget_content_wrap');

Añade el segundo div
al parámetro del título:
register_sidebar(array(
'name' => "Sidebar1",
'id' => 'home-sidebar-1',
'before_widget' => '<div class="sidebar-box">',
'after_widget' => '</div></div>',
'before_title' => '<div class="title">',
'after_title' => '</div><div class="content">',
));

Eso falla si no hay un título para el widget - aunque se puede solucionar

Esto es lo que debes hacer para lograrlo:
register_sidebar(array(
'name' => "Sidebar1",
'id' => 'home-sidebar-1',
'before_widget' => '<div class="sidebar-box"><div class="content">',
'after_widget' => '</div></div>',
'before_title' => '</div><div class="title">',
'after_title' => '</div><div class="content">',
))
Cuando no hay título obtendrás:
<div class="sidebar-box"><div class="content">
{CONTENIDO}
</div></div>
Cuando hay un título obtendrás:
<div class="sidebar-box"><div class="content">
</div><div class="title">
{TÍTULO}
<div class="content">
{CONTENIDO}
</div></div>
Para asegurarte de que el primer div de contenido vacío no se muestre en el último caso, añade esto a tu css:
.sidebar-box .content:empty {display:none !important;}

Después de revisar las respuestas anteriores, creo que solucioné el problema que Cmorales identificó con la respuesta de sanchothefat. Define tu widget de la siguiente manera:
register_sidebar( array(
'name' => 'Barra lateral',
'id' => 'sidebar',
'before_widget' => '<div class="panel panel-default %2$s" id="%1$s">',
'after_widget' => '</div>',
'before_title' => '',
'after_title' => ''
) );
Es importante eliminar los valores predeterminados de before_title
y after_title
. Después de varias pruebas, noté que el primer filtro que mostraba un título predeterminado era widget_title
. Luego usa el filtro widget_title
de la siguiente manera:
function widget_title( $title ) {
if ( $title )
$title = '<div class="panel-heading"><h3 class="panel-title">' . $title . '</h3></div>';
$title .= '<div class="panel-body">';
return $title;
}
Básicamente, <div class="panel-heading"><h3 class="panel-title">
es mi before_title
y </h3></div>
es mi after_title
. Finalmente, usa dynamic_sidebar_params
para anteponer un div de cierre para nuestro contenedor de contenido:
function dynamic_sidebar_params( $params ) {
$params[0]['after_widget'] = '</div>' . $params[0]['after_widget'];
return $params;
}
No es la solución más elegante, pero funciona.

Acabo de modificar ligeramente el código para no tener que tocar register_sidebar. Registrar una barra lateral de la manera habitual:
register_sidebar(array(
'name' => "Barra Lateral 1",
'id' => 'home-sidebar-1',
'before_widget' => '<div class="sidebar-box">',
'after_widget' => '</div>',
'before_title' => '<div class="title">',
'after_title' => '</div>',
));
Y a continuación, el código modificado de la solución de Sanchothefat:
/**
* Si no se proporciona un título, añade el envoltorio widget-content a before_widget
* Si se proporciona un título, añade el envoltorio de contenido a before_widget
*/
add_filter('dynamic_sidebar_params', 'check_widget_template');
function check_widget_template($params){
global $wp_registered_widgets;
$settings_obj = $wp_registered_widgets[$params[0]['widget_id']]['callback'][0];
$the_settings = $settings_obj->get_settings();
$the_settings = $the_settings[$params[1]['number']];
if (isset($params[0]['id']) && $params[0]['id'] == 'home-sidebar-1') {
if (!isset($the_settings['title']) && empty($the_settings['title'])) {
$params[0]['before_widget'] .= '<div class="widget-inner">';
$params[0]['after_widget'] .= '</div>';
} else {
$params[0]['after_widget'] .= '</div>';
$params[0]['after_title'] .= '<div class="widget-inner">';
}
}
return $params;
}

Como se mencionó en los comentarios, algunos widgets principales agregan su propio título que luego se envuelve dos veces con el div de contenido. Para eliminarlos, podrías simplemente devolver una cadena vacía. El único inconveniente es que tienes que ingresar todos los títulos manualmente.
function remove_default_widget_title( $title, $instance = [], $id = '' ) {
if ( isset($instance['title']) && trim($instance['title']) == '' ) {
return '';
}
return $title;
};
add_filter( 'widget_title', 'remove_default_widget_title', 10, 3 );
Corrígeme si me equivoco en algo aquí, pero creo que es bastante sólido.
