Cuando comencé esta respuesta, debería ser solo una pequeña nota. Bueno, fallé. ¡Lo siento! Quédate conmigo, hay un regalo escondido en el fondo ...
Cómo se almacenan los widgets de WordPress
La lista de widgets se almacena en una opción llamada 'sidebars_widgets'
. A var_export()
puede dar algo como lo siguiente:
array (
'wp_inactive_widgets' =>
array (
),
'top-widget' =>
array (
),
'bottom-widget' =>
array (
),
'array_version' => 3,
)
Ignorar 'wp_inactive_widgets'
y 'array_version'
. No tenemos que preocuparnos por eso.
Las otras claves son identificativas para las barras laterales registradas. En este caso, las barras laterales pueden haberse registrado con este código:
// Register two sidebars.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
register_sidebar(
array (
'name' => $sidebar,
'id' => $sidebar,
'before_widget' => '',
'after_widget' => ''
)
);
}
Por defecto, las barras laterales están vacías después del registro. Por supuesto.
Para cada clase de widget registrada, se crea una opción separada que contiene todas las opciones necesarias. La opción está precedida por la cadena widget_
. Para obtener las opciones para todos los widgets RSS activos, tenemos que buscar ...
get_option( 'widget_rss' );
Salida posible:
array (
2 =>
array (
'title' => 'WordPress Stack Exchange',
'url' => 'http://wordpress.stackexchange.com/feeds',
'link' => 'http://wordpress.stackexchange.com/questions',
'items' => 5,
'show_summary' => 1,
'show_author' => 0,
'show_date' => 0,
),
)
Tenga en cuenta el número 2 . Los argumentos para las instancias múltiples se almacenan en esta única opción ordenada por números.
Para ver qué clases de widgets ya son conocidas por WordPress, vaya wp-admin/options.php
y desplácese hacia abajo hasta que vea algo como esto:
Sí, datos serializados. No, no puedes leerlos aquí. No te preocupes, no tienes que hacerlo.
Un widget de demostración
Para ilustrar mejor el funcionamiento interno, he escrito un widget de demostración muy simple:
/**
* Super simple widget.
*/
class T5_Demo_Widget extends WP_Widget
{
public function __construct()
{ // id_base , visible name
parent::__construct( 't5_demo_widget', 'T5 Demo Widget' );
}
public function widget( $args, $instance )
{
echo $args['before_widget'], wpautop( $instance['text'] ), $args['after_widget'];
}
public function form( $instance )
{
$text = isset ( $instance['text'] )
? esc_textarea( $instance['text'] ) : '';
printf(
'<textarea class="widefat" rows="7" cols="20" id="%1$s" name="%2$s">%3$s</textarea>',
$this->get_field_id( 'text' ),
$this->get_field_name( 'text' ),
$text
);
}
}
Tenga en cuenta que el constructor: 't5_demo_widget'
es $id_base
el identificador de este widget. Como puede ver en la captura de pantalla, sus argumentos se almacenan en la opción widget_t5_demo_widget
. Todos sus widgets personalizados serán tratados de esta manera. No tienes que adivinar el nombre. Y puesto que ha escrito sus widgets (probablemente) que conoce todos los argumentos de su clase de $instance
parámetros.
Conceptos básicos
Primero debes registrar algunas barras laterales y el widget personalizado. La acción apropiada para esto es fácil de recordar: 'widgets_init'
. Ponga todo en un contenedor: una clase o una función. Para simplificar, usaré una función llamada t5_default_widget_demo()
.
Todo el siguiente código va al functions.php
. La clase ya T5_Demo_Widget
debería estar cargada. Solo lo puse en el mismo archivo ...
add_action( 'widgets_init', 't5_default_widget_demo' );
function t5_default_widget_demo()
{
// Register our own widget.
register_widget( 'T5_Demo_Widget' );
// Register two sidebars.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
register_sidebar(
array (
'name' => $sidebar,
'id' => $sidebar,
'before_widget' => '',
'after_widget' => ''
)
);
}
Hasta ahora, muy simple. Nuestro tema ahora está listo para widgets, se conoce el widget de demostración. Ahora la diversion.
$active_widgets = get_option( 'sidebars_widgets' );
if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
or ! empty ( $active_widgets[ $sidebars['b'] ] )
)
{ // Okay, no fun anymore. There is already some content.
return;
}
Realmente no quieres destruir la configuración del usuario. Si ya hay contenido en las barras laterales, su código no debería pasar por encima. Por eso nos detenemos en este caso.
De acuerdo, asumí que las barras laterales están vacías ... necesitamos un contador:
$counter = 1;
Los widgets están numerados . Estos números son segundos identificadores para WordPress.
Hagamos que la matriz lo cambie:
$active_widgets = get_option( 'sidebars_widgets' );
También necesitamos un contador (más sobre eso más adelante):
$counter = 1;
Y así es como usamos el contador, los nombres de la barra lateral y los argumentos del widget (bueno, solo tenemos un argumento:) text
.
// Add a 'demo' widget to the top sidebar …
$active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
// … and write some text into it:
$demo_widget_content[ $counter ] = array ( 'text' => "This works!\n\nAmazing!" );
$counter++;
Observe cómo se crea el identificador del widget: el id_base
, un signo menos -
y el contador. El contenido del widget se almacena en otra variable $demo_widget_content
. Aquí está el contador de la clave y los argumentos del widget se almacenan en una matriz.
Incrementamos el contador en uno cuando hayamos terminado para evitar colisiones.
Eso fue fácil. Ahora un widget RSS. ¡Más campos, más diversión!
$active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
// The latest 15 questions from WordPress Stack Exchange.
$rss_content[ $counter ] = array (
'title' => 'WordPress Stack Exchange',
'url' => 'http://wordpress.stackexchange.com/feeds',
'link' => 'http://wordpress.stackexchange.com/questions',
'items' => 15,
'show_summary' => 0,
'show_author' => 1,
'show_date' => 1,
);
update_option( 'widget_rss', $rss_content );
$counter++;
Aquí hay algo nuevo: update_option()
esto almacenará el argumento del widget RSS en una opción separada. WordPress los encontrará automáticamente más tarde.
No guardamos los argumentos del widget de demostración porque ahora agregamos una segunda instancia a nuestra segunda barra lateral ...
// Okay, now to our second sidebar. We make it short.
$active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
#$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
$demo_widget_content[ $counter ] = array ( 'text' => 'The second instance of our amazing demo widget.' );
update_option( 'widget_t5_demo_widget', $demo_widget_content );
... y guardar todos los argumentos para la t5_demo_widget
prisa. No es necesario actualizar la misma opción dos veces.
Bueno, suficientes widgets para hoy, guardemos sidebars_widgets
también:
update_option( 'sidebars_widgets', $active_widgets );
Ahora WordPress sabrá que hay algunos widgets registrados y dónde se almacenan los argumentos para cada widget. A var_export()
en el sidebar_widgets se verá así:
array (
'wp_inactive_widgets' =>
array (
),
'top-widget' =>
array (
0 => 't5_demo_widget-1',
1 => 'rss-2',
),
'bottom-widget' =>
array (
0 => 't5_demo_widget-3',
),
'array_version' => 3,
)
El código completo nuevamente:
add_action( 'widgets_init', 't5_default_widget_demo' );
function t5_default_widget_demo()
{
// Register our own widget.
register_widget( 'T5_Demo_Widget' );
// Register two sidebars.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
register_sidebar(
array (
'name' => $sidebar,
'id' => $sidebar,
'before_widget' => '',
'after_widget' => ''
)
);
}
// Okay, now the funny part.
// We don't want to undo user changes, so we look for changes first.
$active_widgets = get_option( 'sidebars_widgets' );
if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
or ! empty ( $active_widgets[ $sidebars['b'] ] )
)
{ // Okay, no fun anymore. There is already some content.
return;
}
// The sidebars are empty, let's put something into them.
// How about a RSS widget and two instances of our demo widget?
// Note that widgets are numbered. We need a counter:
$counter = 1;
// Add a 'demo' widget to the top sidebar …
$active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
// … and write some text into it:
$demo_widget_content[ $counter ] = array ( 'text' => "This works!\n\nAmazing!" );
#update_option( 'widget_t5_demo_widget', $demo_widget_content );
$counter++;
// That was easy. Now a RSS widget. More fields, more fun!
$active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
// The latest 15 questions from WordPress Stack Exchange.
$rss_content[ $counter ] = array (
'title' => 'WordPress Stack Exchange',
'url' => 'http://wordpress.stackexchange.com/feeds',
'link' => 'http://wordpress.stackexchange.com/questions',
'items' => 15,
'show_summary' => 0,
'show_author' => 1,
'show_date' => 1,
);
update_option( 'widget_rss', $rss_content );
$counter++;
// Okay, now to our second sidebar. We make it short.
$active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
#$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
$demo_widget_content[ $counter ] = array ( 'text' => 'The second instance of our amazing demo widget.' );
update_option( 'widget_t5_demo_widget', $demo_widget_content );
// Now save the $active_widgets array.
update_option( 'sidebars_widgets', $active_widgets );
}
Si va a ver wp-admin/widgets.php
ahora, verá tres widgets preestablecidos:
Y eso es. Utilizar …
dynamic_sidebar( 'top-widget' );
dynamic_sidebar( 'bottom-widget' );
... para imprimir los widgets.
Hay una pequeña falla: debe cargar el front-end dos veces para el registro inicial. Si alguien puede ayudarme aquí, estaré muy agradecido.