Widgets de WordPress: Refactorización, Parte 10
En lo que respecta a la refactorización de WordPress Widget Boilerplate, estamos en un buen lugar. Se ha trabajado mucho para que la introducción de nuevas clases, características y funcionalidades sea mucho más fácil.
Y no solo eso: debería ser más fácil de seguir.
Gracias por el trabajo en la última publicación, tenemos mucho trabajo para desarrollar, es decir, una interfaz administrativa básica.
Finalmente, la última publicación decía:
En los próximos artículos, esto continuará evolucionando pero, como puede ver, nos estamos asegurando de tener una única clase básica de funcionalidad para hablar con WordPress y una clase específica para representar el formulario administrativo.
Y ahí es donde vamos a retomar en este artículo. Específicamente, veremos cómo desinfectar y serializar los datos, así como recuperar los datos guardados en el widget.
El modelo de widget de WordPress: Refactorización Parte 10
Refactorización de la interfaz de usuario
Antes de entrar en serialización, hay un trabajo menor que necesitaremos hacer en nuestra vista administrativa. Recuerde de las publicaciones anteriores de la serie que hemos creado un formulario que acepta:
- un título,
- algo de contenido,
- y una casilla de verificación.
Esto se muestra bien, pero excluye algunas funciones clave de la API de Widgets. Es decir, debemos asegurarnos de que estamos nombrando correctamente nuestros elementos usando las siguientes funciones:
Y luego escribiremos nuestra función simplemente llamada get, que explicaré en un momento.
Las funciones anteriores son necesarias porque ayudan a WordPress a realizar un seguimiento de cuántas instancias del widget se están utilizando y cuál está editando el usuario. En otras palabras, obtenemos una gran cantidad de funciones de forma gratuita.
Antes de mostrarle el código, quiero discutir brevemente el propósito de la función get que vamos a presentar. En resumen, es una forma de pasar una clave (como en la clave en un par clave/valor) a una función y luego hacer que recupere fácilmente un valor para nosotros para que mantenga nuestra interfaz lo más limpia posible.
Entonces, primero, el 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];
}
Lo importante a tener en cuenta es que este método acepta no solo la clave para el valor que estamos leyendo, sino también una matriz que se refiere a la instancia de la matriz.
Y ahora, la interfaz de usuario refactorizada :
<?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 -->
Pero esto todavía deja una falta de funcionalidad y nos deja trabajo por hacer. Es decir, necesitamos desinfectar los datos y devolverlos a WordPress, para que guarde los datos.
Desinfección y serialización
A los efectos de nuestro ejemplo, vamos a ser muy estrictos en lo que permitimos. Es decir, solo admitiremos texto básico y eliminaremos todo de manera agresiva.
Esto significa que no vamos a permitir marcas ni nada por el estilo. En su lugar, vamos a eliminar todo lo que no sea texto básico. Podemos decorarlo un poco cuando llegue el momento de mostrarlo en el front-end, pero eso lo dejaremos para la publicación correspondiente.
Para hacer esto, vamos a usar las siguientes funciones:
Recuerde que tenemos dos campos en nuestro widget: el campo de título y el campo de contenido. Según el tipo de widget que esté creando, es posible que solo necesite una sola clase o función para desinfectar los datos. En otras situaciones, es posible que necesite algo más complejo.
Tenga esto en cuenta a medida que avancemos en este código, ya que esta no será una solución única para todos. En cambio, será específicamente para esto.
De todos modos, para desinfectar los datos, vamos a escribir una clase específicamente para este propósito y luego la pondremos a disposición de nuestra clase WidgetAdmin.
Aquí está la clase en su totalidad con una descripción a continuación:
<?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;
}
}
La clase debe ser directa. Toma los valores entrantes del widget, los desinfecta y luego devuelve una nueva matriz para devolverla a WordPress.
Sin embargo, hay una trampa. Esta clase debe ser una propiedad de la clase Widget principal que se mostró en la última publicación.
En segundo lugar, el método de actualización que forma parte de la API de Widgets es lo que llamará a esta clase. No es necesario pasar la variable $oldInstance al serializador, pero es necesario para el método de actualización.
Aquí está la clase Widget tal como está construida actualmente :
<?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];
}
}
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.
Recuperando datos
Tenga en cuenta que aunque la funcionalidad parece incompleta para esto (ya que los datos sin desinfectar aún se muestran), nos enfocamos en asegurarnos de que estamos escribiendo clases con cohesión, responsabilidad y que no estén estrechamente acopladas.
Vamos a iterar un poco más sobre esto en la próxima publicación. Así que estudie el código anterior, impleméntelo si eso es lo que ha estado haciendo, y partiremos de ahí en la próxima publicación.