Widgets do WordPress: Refatoração, Parte 11
No post anterior, passamos por muitas refatorações que separavam as preocupações em suas próprias classes.
Em última análise, isso ajuda a mostrar como podemos manter um alto nível de coesão enquanto não apenas trabalhamos com classes no WordPress, mas também com APIs pré-existentes.
Como as últimas postagens sobre refatoração da base de código foram tão longas, o conjunto atual de postagens está focado em pequenas alterações incrementais e, portanto, em postagens mais curtas e mais focadas.
Conforme mencionado no artigo anterior:
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.
Então é aí que vamos pegar neste artigo.
The WordPress Widget Boilerplate: Refatorando Parte 11
Antes de escrever qualquer código, a primeira coisa a notar é que se você preencher uma das áreas de conteúdo do widget (como o título) com algo assim :
<script type="text/javascript">This is the Title</script>
E, em seguida, clique em Salvar, o conteúdo real será higienizado e gravado no banco de dados. Você pode ver que isso é verdade observando o valor do widget no banco de dados.
Além disso, os dados parecem bons à primeira vista, mas se você atualizar a página, o conteúdo não limpo aparecerá. Se você navegar para outra página, como Menus, e depois voltar, o conteúdo do widget aparecerá, mas devidamente higienizado.
Por que, então, ele mostra uma coisa no banco de dados e uma coisa no front-end da área de administração ao executar determinadas etapas?
Isso tem a ver com o cache do widget e, felizmente, podemos liberar esse cache à vontade usando os ganchos que quisermos (ou seja, podemos assinar qualquer evento e fazer com que ele libere o cache).
Da referência de código :
Remove a chave e o grupo correspondentes ao conteúdo do cache.
Observe, no entanto, que isso requer que forneçamos a chave e um grupo opcional. No Boilerplate, usamos o slug do widget como a chave e o grupo é widget.
Limpando o Cache
Como a função pode ser vinculada a qualquer evento, podemos criar um assinante que podemos vincular a qualquer evento. Isso significa que podemos criar um assinante DeleteWidgetCache em nosso namespace Subscriber:
<?php
<?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 WordPressWidgetBoilerplateSubscriber;
/**
* Deletes the cached contents of the widget.
*/
class DeleteWidgetCacheSubscriber extends AbstractSubscriber
{
/**
* {@inheritdoc}
*/
public function __construct(string $hook)
{
parent::__construct($hook);
}
/**
* Flushes the widget's cache based on the key that's specified in the function arguments.
*/
public function load()
{
/* Because we're implementing an abstract class, we'll parse arguments from the
* func_get_args().
*/
$args = func_get_args();
if (!$this->hasValidArguments($args)) {
return;
}
// TODO: More to come...
}
/**
* Verifies that we have valid arguments with which to work.
*
* @param array $args the array of arguments we are validating
*
* @return bool true if the arguments are valid; otherwise, false
*/
private function hasValidArguments(array $args): bool
{
// First, check the initial index of the arguments.
if (!isset($args[0])) {
return false;
}
// Next, check the values of the arguments for the widget key and group.
$args = $args[0];
if (!isset($args[0]) && !isset($args[1])) {
return false;
}
return true;
}
}
Em seguida, atualizaremos o bootstrap para adicionar o assinante ao registro e usaremos um gancho personalizado, flush_widget_cache, que usaremos momentaneamente.
<?php
/**
* WordPress Widget Boilerplate
*
* The WordPress Widget Boilerplate is an organized, maintainable boilerplate for building
* widgets using WordPress best practices.
*
* @package WordPressWidgetBoilerplate
* @author Your Name <email@example.com>
* @license GPL-3.0+
* @link http://example.com
* @copyright 2018 - 2019 Your Name or Company Name
*
* @wordpress-plugin
* Plugin Name: WordPress Widget Boilerplate
* Plugin URI: https://github.com/tommcfarlin/wordpress-widget-boilerplate
* Description: An object-oriented foundation for building WordPress Widgets.
* Version: 1.0.0
* Author: Tom McFarlin
* Author URI: https://tommcfarlin.com
* Text Domain: widget-name
* License: GPL-3.0+
* License URI: http://www.gnu.org/licenses/gpl-3.0.txt
* Domain Path: /lang
*/
namespace WordPressWidgetBoilerplate;
use WordPressWidgetBoilerplateUtilitiesRegistry;
use WordPressWidgetBoilerplatePlugin;
use WordPressWidgetBoilerplateSubscriberWidgetSubscriber;
use WordPressWidgetBoilerplateSubscriberDeleteWidgetCacheSubscriber;
// Prevent this file from being called directly.
defined('WPINC') || die;
// Include the autoloader.
require_once __DIR__. '/vendor/autoload.php';
// Setup a filter so we can retrieve the registry throughout the plugin.
$registry = new Registry();
add_filter('wpwBoilerplateRegistry', function() use ($registry) {
return $registry;
});
// Add subscribers.
$registry->add('deleteWidgetCacheSubscriber', new DeleteWidgetCacheSubscriber('flush_widget_cache'));
// Add the Widget base class to the Registry.
$registry->add('widgetSubscriber', new WidgetSubscriber('widgets_init'));
// Start the machine.
(new Plugin($registry))->start();
Para os propósitos do Boilerplate, usaremos o evento customizado sempre que o código de serialização do widget for chamado.
Primeiro, vamos definir uma chamada do_action, identificá-la como flush_widget_cache e, em seguida , passar os argumentos necessários para o evento para que o assinante possa lê-los:
<?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
{
/**
* @var string a reference to the slug of the widget to which the serialier is associated
*/
private $widgetSlug;
/**
* Initializes the class.
*
* @param string a reference to the slug of the widget to which the serialier is associated
*/
public function __construct(string $widgetSlug)
{
$this->widgetSlug = $widgetSlug;
}
/**
* 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)
);
}
do_action('flush_widget_cache', [$this->widgetSlug, 'widget']);
return $instance;
}
}
E, em seguida, no assinante, liberaremos o cache com base nos argumentos recebidos:
<?php
<?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 WordPressWidgetBoilerplateSubscriber;
/**
* Deletes the cached contents of the widget.
*/
class DeleteWidgetCacheSubscriber extends AbstractSubscriber
{
/**
* {@inheritdoc}
*/
public function __construct(string $hook)
{
parent::__construct($hook);
}
/**
* Flushes the widget's cache based on the key that's specified in the function arguments.
*/
public function load()
{
/* Because we're implementing an abstract class, we'll parse arguments from the
* func_get_args().
*/
$args = func_get_args();
if (!$this->hasValidArguments($args)) {
return;
}
$args = $args[0];
wp_cache_delete($args[0], $args[1]);
}
/**
* Verifies that we have valid arguments with which to work.
*
* @param array $args the array of arguments we are validating
*
* @return bool true if the arguments are valid; otherwise, false
*/
private function hasValidArguments(array $args): bool
{
// First, check the initial index of the arguments.
if (!isset($args[0])) {
return false;
}
// Next, check the values of the arguments for the widget key and group.
$args = $args[0];
if (!isset($args[0]) && !isset($args[1])) {
return false;
}
return true;
}
}
E isso faz isso.
Pronto para o Front-End
Neste ponto, temos um mecanismo que pode liberar o cache do widget sempre que quisermos – não apenas com um evento personalizado – mas também com qualquer um dos eventos oferecidos pelo WordPress.
Isso pode ser útil se você estiver usando o Boilerplate para algo que usará uma consulta em cache ou qualquer outro mecanismo de cache, para esse assunto, e quiser ter certeza de que o conteúdo está claro.
Em seguida, veremos a renderização de conteúdo no front-end. Estamos chegando ao fim da refatoração do Boilerplate, mas há um pouco mais a fazer antes de estarmos prontos para merge-lo no branch master da base de código.