Quando comecei esta resposta, deveria ser apenas uma pequena nota. Bem, eu falhei. Desculpa! Fique comigo, há um broche escondido no fundo…
Como os widgets do WordPress são armazenados
A lista de widget é armazenado em uma opção chamada 'sidebars_widgets'
. A var_export()
pode fornecer algo como o seguinte:
array (
'wp_inactive_widgets' =>
array (
),
'top-widget' =>
array (
),
'bottom-widget' =>
array (
),
'array_version' => 3,
)
Ignore 'wp_inactive_widgets'
e 'array_version'
. Não precisamos nos preocupar com isso.
As outras chaves são identificadoras de barras laterais registradas. Nesse caso, as barras laterais podem ter sido registradas com 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 padrão, as barras laterais estão vazias após o registro. Claro.
Para cada classe de widget registrada, uma opção separada é criada, contendo todas as opções necessárias. A opção é prefixada pela sequência widget_
. Para obter as opções para todos os widgets RSS ativos, precisamos analisar…
get_option( 'widget_rss' );
Saída possível:
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,
),
)
Anote o número 2 . Os argumentos para várias instâncias são todos armazenados nessa opção, ordenada por números.
Para ver quais classes de widgets já são conhecidas pelo WordPress, vá wp-admin/options.php
e role para baixo até ver algo assim:
Sim, dados serializados. Não, você não pode ler esses aqui. Não se preocupe, você não precisa.
Um widget de demonstração
Para ilustrar melhor o funcionamento interno, escrevi um widget de demonstração muito simples:
/**
* 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
);
}
}
Observe o construtor: 't5_demo_widget'
é $id_base
o identificador para este widget. Como você pode ver na captura de tela seus argumentos são armazenados na opção widget_t5_demo_widget
. Todos os seus widgets personalizados serão tratados assim. Você não precisa adivinhar o nome. E desde que você escreveu seus widgets (provavelmente), você conhece todos os argumentos dos parâmetros da sua classe $instance
.
Noções básicas de tema
Primeiro, você precisa registrar algumas barras laterais e o widget personalizado. A ação adequada para isso é fácil de lembrar: 'widgets_init'
. Coloque tudo em um contêiner - uma classe ou uma função. Para simplificar eu vou usar uma função chamada t5_default_widget_demo()
.
Todo o código a seguir entra no functions.php
. A classe T5_Demo_Widget
já deve estar carregada. Eu apenas coloquei no mesmo arquivo ...
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' => ''
)
);
}
Até agora, tão simples. Nosso tema agora está pronto para o widget, o widget de demonstração é conhecido. Agora a diversão.
$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;
}
Você realmente não quer destruir as configurações do usuário. Se já houver algum conteúdo nas barras laterais, seu código não deve ser executado sobre ele. É por isso que paramos neste caso.
Ok, assumimos que as barras laterais estão vazias ... precisamos de um contador:
$counter = 1;
Os widgets são numerados . Esses números são segundos identificadores para o WordPress.
Vamos fazer com que o array mude:
$active_widgets = get_option( 'sidebars_widgets' );
Também precisamos de um contador (mais sobre isso mais tarde):
$counter = 1;
E aqui está como usamos o contador, os nomes da barra lateral e os argumentos do widget (bem, temos apenas um 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 como o identificador do widget é criado: o id_base
, um menos -
e o contador. O conteúdo do widget é armazenado em outra variável $demo_widget_content
. Aqui está o contador da chave e os argumentos do widget são armazenados em uma matriz.
Aumentamos o contador em um quando terminamos para evitar colisões.
Essa foi fácil. Agora um widget de RSS. Mais campos, mais diversão!
$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++;
Aqui está algo novo: update_option()
isso armazenará o argumento do widget RSS em uma opção separada. O WordPress os encontrará automaticamente mais tarde.
Não salvamos os argumentos do widget de demonstração porque agora adicionamos uma segunda instância à nossa 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 );
… E salve todos os argumentos para t5_demo_widget
uma corrida. Não há necessidade de atualizar a mesma opção duas vezes.
Bem, widgets suficientes para hoje, vamos salvar sidebars_widgets
também:
update_option( 'sidebars_widgets', $active_widgets );
Agora, o WordPress saberá que existem alguns widgets registrados e onde os argumentos para cada widget são armazenados. Um var_export()
na sidebar_widgets ficará assim:
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,
)
O código completo novamente:
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 );
}
Se você for wp-admin/widgets.php
agora, verá três widgets predefinidos:
E é isso. Usar …
dynamic_sidebar( 'top-widget' );
dynamic_sidebar( 'bottom-widget' );
… Para imprimir os widgets.
Há uma pequena falha: você precisa carregar o front-end duas vezes para o registro inicial. Se alguém puder ajudar aqui, ficarei muito grato.