Widgets do WordPress: Refatoração, Parte 10
No que diz respeito à refatoração do WordPress Widget Boilerplate, estamos em um bom lugar. Muito trabalho foi feito de modo que a introdução de novas classes, recursos e funcionalidades deve ser muito mais fácil.
E não só isso: deveria ser mais fácil de seguir.
Obrigado pelo trabalho no último post, temos muito trabalho para construir – ou seja, uma interface administrativa básica.
Por fim, o último post dizia:
Nos próximos artigos, isso continuará a evoluir, mas, como você pode ver, estamos nos certificando de que temos uma única classe base de funcionalidade para conversar com o WordPress e uma classe específica para renderizar o formulário administrativo.
E é aí que vamos pegar neste artigo. Especificamente, veremos como limpar e serializar os dados, bem como recuperar os dados salvos no widget.
The WordPress Widget Boilerplate: Refatorando Parte 10
Refatorando a IU
Antes de entrarmos na serialização, há um pequeno trabalho que precisaremos fazer em nossa visão administrativa. Lembre-se de postagens anteriores da série que criamos um formulário que aceita:
- um título,
- algum conteúdo,
- e uma caixa de seleção.
Isso é exibido bem, mas exclui alguns recursos importantes da API de Widgets. Ou seja, precisamos ter certeza de que estamos nomeando corretamente nossos elementos usando as seguintes funções:
E então escreveremos nossa função simplesmente chamada get, que explicarei momentaneamente.
As funções acima são necessárias porque ajudam o WordPress a acompanhar quantas instâncias do widget estão sendo usadas e qual o usuário está editando. Em outras palavras, temos muitas funcionalidades de graça.
Antes de mostrar o código, quero discutir brevemente o propósito da função get que vamos apresentar. Resumindo, é uma maneira de passarmos uma chave (como na chave em um par chave/valor) para uma função e, em seguida, fazer com que ela recupere facilmente um valor para nós, de modo que mantenha nossa interface o mais limpa possível.
Então, primeiro, o método get :
<?php
/**
* If the value for the key exists in the current instance of the widget, then it will
* retrieve it. Otherwise, it will return an empty value.
*
* @param string $key the used to identify the value of the widget.
* @param array $instance the options for the instance of this widget
*/
protected function get($key, $instance)
{
return empty($instance[$key])? '': $instance[$key];
}
O importante a notar é que este método aceita não apenas a chave para o valor que estamos lendo, mas um array referente à instância do array.
E agora, a interface do usuário refatorada :
<?php
/*
* This file is part of WordPress Widget Boilerplate
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
?>
<div class="widget-content">
<p>
<input
type="text"
id="<?php echo esc_attr($this->get_field_id('title')); ?>"
name="<?php echo esc_attr($this->get_field_name('title')); ?>"
value="<?php echo $this->get('title', $instance) ?>"
placeholder="Widget Title"
class="widefat"
/>
</p>
<p>
<textarea
id="<?php echo esc_attr($this->get_field_id('content')); ?>"
name="<?php echo esc_attr($this->get_field_name('content')); ?>"
placeholder="Widget Content"
style="width:100%;"><?php echo $this->get('content', $instance) ?></textarea>
</p>
<p>
<input
type="checkbox"
value="on"
name="<?php echo esc_attr($this->get_field_name('display-title')); ?>"
id="<?php echo esc_attr($this->get_field_id('display-title')); ?>"
<?php checked('on', $this->get('display-title', $instance), true); ?>
class="checkbox"
/>
<label for="<?php echo esc_attr($this->get_field_id('display-title')); ?>">Display Title?</label>
</p>
</div><!-- .widget-content -->
Mas isso ainda deixa falta de funcionalidade e deixa trabalho para nós fazermos. Ou seja, precisamos higienizar os dados e passá-los de volta para o WordPress, para que ele salve os dados.
Sanitização e Serialização
Para os propósitos do nosso exemplo, seremos muito rigorosos no que permitimos. Ou seja, vamos suportar apenas o texto básico e vamos remover tudo de forma agressiva.
Isso significa que não vamos permitir marcação ou algo assim. Em vez disso, vamos remover tudo o que não é texto básico. Podemos decorá-lo um pouco quando chegar a hora de exibi-lo no front-end, mas deixaremos isso para o post apropriado.
Para isso, vamos usar as seguintes funções:
Lembre-se de que temos dois campos em nosso widget – o campo de título e o campo de conteúdo. Dependendo do tipo de widget que você está construindo, você pode precisar apenas de uma única classe ou função para limpar os dados. Em outras situações, você pode precisar de algo mais complexo.
Tenha isso em mente enquanto analisamos este código, pois essa não será uma solução de tamanho único. Em vez disso, será especificamente para isso.
De qualquer forma, para sanitizar os dados, vamos escrever uma classe específica para esse fim, e depois vamos disponibilizá-la para nossa classe WidgetAdmin.
Aqui está a classe na íntegra com uma descrição a seguir:
<?php
/*
* This file is part of WordPress Widget Boilerplate
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
namespace WordPressWidgetBoilerplateWordPress;
/**
* Santiizes and saves the data for the widget.
*/
class WidgetSerializer
{
/**
* Updates the values of the widget. Sanitizes the information before saving it.
*
* @param array $newInstance the array of new options to save
*/
public function update($newInstance)
{
$instance = [];
foreach ($newInstance as $key => $value) {
$instance[$key] = strip_tags(
stripslashes($value)
);
}
return $instance;
}
}
A aula deve ser direta. Ele recebe os valores recebidos do widget, limpa-os e retorna um novo array para ser devolvido ao WordPress.
Há um porém. Esta classe deve ser uma propriedade da classe Widget principal que foi mostrada no último post.
Em segundo lugar, o método de atualização que faz parte da API Widgets é o que chamará essa classe. Não é necessário passar a variável $oldInstance para o serializador, mas é necessário para o método de atualização.
Aqui está a classe Widget como está atualmente construída :
<?php
/*
* This file is part of WordPress Widget Boilerplate
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
namespace WordPressWidgetBoilerplateWordPress;
use WP_Widget;
class Widget extends WP_Widget
{
/**
* @var string unique identifier for your widget
*/
protected $widgetSlug;
/**
* Initializes the plugin by setting its properties and calling the parent class with the description.
*
* @param string $widgetSlug unique identifier for your widget
* @param WidgetSerializer $widgetSerializer the class responsible for saving widget options
*/
public function __construct($widgetSlug)
{
$this->widgetSlug = $widgetSlug;
parent::__construct(
$this->getWidgetSlug(),
__('Widget Name', $this->getWidgetSlug()),
[
'classname' => $this->getWidgetSlug().'-class',
'description' => __('Short description of the widget goes here.', $this->getWidgetSlug()),
]
);
}
/**
* Return the widget slug.
*
* @return string slug variable
*/
public function getWidgetSlug()
{
return $this->widgetSlug;
}
/**
* Displays the administrative view of the form and includes the options
* for the instance of the widget as arguments passed into the function.
*
* @param array $instance the options for the instance of this widget
*/
public function form($instance)
{
include plugin_dir_path(__FILE__).'Views/Admin.php';
}
/**
* Updates the values of the widget. Uses the serialization class to sanitize the
* information before saving it.
*
* @param array $newInstance the values to be sanitized and saved
* @param array $oldInstance the values that were originally saved
*/
public function update($newInstance, $oldInstance)
{
return $this->widgetSerializer->update($newInstance, $oldInstance);
}
/**
* If the value for the key exists in the current instance of the widget, then it will
* retrieve it. Otherwise, it will return an empty value.
*
* @param string $key the used to identify the value of the widget
* @param array $instance the options for the instance of this widget
*/
protected function get($key, $instance)
{
return empty($instance[$key])? '': $instance[$key];
}
}
Mas se você atualizar a página, poderá notar que a sanitização e a serialização parecem não funcionar ao recuperar os dados. E é isso que veremos no próximo post.
Recuperando dados
Observe que, embora a funcionalidade pareça incompleta para isso (já que os dados não higienizados ainda são exibidos), estamos focados em garantir que estamos escrevendo classes com coesão, responsabilidade e que não sejam fortemente acopladas.
Vamos iterar um pouco mais sobre isso no próximo post. Então estude o código acima, implemente-o se é isso que você está fazendo, e vamos a partir daí no próximo post.