Widget WordPress: refactoring, parte 11
Nel post precedente, abbiamo esaminato molte operazioni di refactoring che hanno separato le preoccupazioni nelle rispettive classi.
In definitiva, questo aiuta a mostrare come possiamo mantenere un alto livello di coesione mentre non solo lavoriamo con le classi in WordPress, ma lo facciamo insieme alle API preesistenti.
Poiché gli ultimi post sul refactoring della base di codice sono stati così lunghi, l’attuale set di post si concentra su piccole modifiche incrementali e quindi post più brevi e più mirati.
Come accennato nell’articolo precedente:
Ma se aggiorni la pagina, potresti notare che la sanificazione e la serializzazione non sembrano funzionare durante il recupero dei dati. Ed è quello che esamineremo nel prossimo post.
Quindi è qui che riprenderemo in questo articolo.
The WordPress Widget Boilerplate: Refactoring Parte 11
Prima di scrivere qualsiasi codice, la prima cosa da notare è che se si popola una delle aree di contenuto del widget (come il titolo) con qualcosa del genere :
<script type="text/javascript">This is the Title</script>
E quindi fare clic su Salva, il contenuto effettivo verrà disinfettato e scritto nel database. Puoi vedere che questo è vero osservando il valore del widget nel database.
Inoltre, i dati sembrano a posto a prima vista, ma se aggiorni la pagina, viene visualizzato il contenuto non disinfettato. Se accedi a un’altra pagina, come Menu, e poi torni indietro, il contenuto del widget viene visualizzato ma correttamente disinfettato.
Perché, quindi, mostra una cosa nel database e una cosa sul front-end dell’area di amministrazione durante l’esecuzione di determinati passaggi?
Questo ha a che fare con la cache del widget e, fortunatamente, siamo in grado di svuotare questa cache a piacimento usando qualsiasi hook vogliamo (ovvero, possiamo iscriverci a qualsiasi evento e quindi svuotare la cache).
Dal codice di riferimento :
Rimuove il contenuto della cache che corrisponde alla chiave e al gruppo.
Si noti, tuttavia, che è necessario fornire la chiave e un gruppo opzionale. In Boilerplate, abbiamo utilizzato lo slug del widget come chiave e gruppo è widget.
Svuotare la cache
Poiché la funzione può essere agganciata a qualsiasi evento, possiamo creare un abbonato che possiamo agganciare a qualsiasi evento. Ciò significa che possiamo creare un abbonato DeleteWidgetCache nel nostro spazio dei nomi degli abbonati:
<?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;
}
}
Aggiorneremo quindi il bootstrap per aggiungere l’abbonato al registro e utilizzeremo un hook personalizzato, flush_widget_cache, che utilizzeremo 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();
Ai fini di Boilerplate, utilizzeremo l’evento personalizzato ogni volta che viene chiamato il codice di serializzazione del widget.
Innanzitutto, definiremo una chiamata do_action, la identificheremo come flush_widget_cache, quindi passeremo gli argomenti necessari all’evento in modo che l’abbonato possa leggerli:
<?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 poi nell’abbonato, svuoteremo la cache in base agli argomenti in arrivo:
<?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 questo lo fa.
Pronto per il front-end
A questo punto, abbiamo un meccanismo in atto che può svuotare la cache del widget ogni volta che vogliamo, non solo con un evento personalizzato, ma anche con qualsiasi evento offerto da WordPress.
Questo può tornare utile se stai usando Boilerplate per qualcosa che utilizzerà una query memorizzata nella cache o qualsiasi altro meccanismo di memorizzazione nella cache, se è per questo, e vuoi assicurarti che i contenuti siano chiari.
Successivamente, esamineremo il rendering dei contenuti sul front-end. Ci stiamo avvicinando alla fine, del refactoring di Boilerplate, ma c’è solo un po’ di più da fare prima di essere pronti per unirlo al ramo principale della codebase.