Widgets de WordPress: Refactorización, Parte 11
En la publicación anterior, analizamos muchas refactorizaciones que separaron las preocupaciones en sus propias clases.
En última instancia, esto ayuda a mostrar cómo podemos mantener un alto nivel de cohesión mientras no solo trabajamos con clases en WordPress, sino que lo hacemos junto con las API preexistentes.
Debido a que las últimas publicaciones sobre la refactorización de la base de código han sido tan largas, el conjunto actual de publicaciones se centra en cambios pequeños e incrementales y, por lo tanto, publicaciones más cortas y enfocadas.
Como se mencionó en el artículo anterior:
Pero si actualiza la página, es posible que observe que la desinfección y la serialización no parecen funcionar al recuperar los datos. Y eso es lo que vamos a ver en el siguiente post.
Así que ahí es donde vamos a retomar en este artículo.
El modelo de widget de WordPress: Refactorización Parte 11
Antes de escribir cualquier código, lo primero que debe notar es que si completa una de las áreas de contenido del widget (como el título) con algo como esto :
<script type="text/javascript">This is the Title</script>
Y luego haga clic en Guardar, el contenido real se desinfectará y se escribirá en la base de datos. Puede ver que esto es cierto mirando el valor del widget en la base de datos.
Además, los datos se ven bien a primera vista, pero si actualiza la página, aparece el contenido sin desinfectar. Si navega a otra página, como Menús, y luego regresa, el contenido del widget aparece pero se desinfecta correctamente.
¿Por qué, entonces, muestra una cosa en la base de datos y otra en el front-end del área de administración al realizar ciertos pasos?
Esto tiene que ver con el caché de widgets y, afortunadamente, podemos vaciar este caché a voluntad usando los ganchos que queramos (es decir, podemos suscribirnos a cualquier evento y luego hacer que vacíe el caché).
De la referencia del código :
Elimina el contenido de la memoria caché que coincide con la clave y el grupo.
Tenga en cuenta, sin embargo, que requiere que proporcionemos la clave y un grupo opcional. En Boilerplate, hemos estado usando el slug del widget como clave y el grupo es widget.
Limpiando el caché
Dado que la función se puede vincular a cualquier evento, podemos crear un suscriptor que podamos vincular a cualquier evento. Esto significa que podemos crear un suscriptor DeleteWidgetCache en nuestro espacio de nombres de suscriptor:
<?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;
}
}
Luego actualizaremos el arranque para agregar el suscriptor al registro y usaremos un gancho personalizado, flush_widget_cache, que usaremos momentáneamente.
<?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 los propósitos de Boilerplate, usaremos el evento personalizado cada vez que se llame al código de serialización del widget.
Primero, definiremos una llamada do_action, la identificaremos como flush_widget_cache y luego pasaremos los argumentos necesarios al evento para que el suscriptor pueda leerlos:
<?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;
}
}
Y luego, en el suscriptor, vaciaremos el caché en función de los argumentos entrantes:
<?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;
}
}
Y eso lo hace.
Listo para el front-end
En este punto, contamos con un mecanismo que puede vaciar la caché de widgets cuando queramos, no solo con un evento personalizado, sino también con cualquiera de los eventos que ofrece WordPress.
Esto puede ser útil si está utilizando Boilerplate para algo que utilizará una consulta en caché o cualquier otro mecanismo de almacenamiento en caché, y quiere asegurarse de que el contenido sea claro.
A continuación, veremos la representación de contenido en el front-end. Nos acercamos al final de la refactorización de Boilerplate, pero queda un poco más por hacer antes de que estemos listos para fusionarlo en la rama maestra de la base de código.