Виджеты WordPress: рефакторинг, часть 11
В предыдущем посте мы прошли через множество рефакторингов, которые разделили задачи на их собственные классы.
В конечном счете, это помогает показать, как мы можем поддерживать высокий уровень согласованности, не только работая с классами в WordPress, но и параллельно с уже существующими API.
Поскольку последние несколько сообщений о рефакторинге базы кода были очень длинными, текущий набор сообщений сосредоточен на небольших, постепенных изменениях и, следовательно, более коротких и целенаправленных сообщениях.
Как упоминалось в предыдущей статье:
Но если вы обновите страницу, вы можете заметить, что очистка и сериализация не работают при извлечении данных. И это то, что мы собираемся изучить в следующем посте.
Так вот где мы собираемся подобрать в этой статье.
Шаблон виджета WordPress: рефакторинг, часть 11
Прежде чем писать какой-либо код, первое, на что следует обратить внимание, это то, что если вы заполните одну из областей содержимого виджета (например, заголовок) чем-то вроде этого :
<script type="text/javascript">This is the Title</script>
Затем нажмите «Сохранить», фактический контент будет очищен и записан в базу данных. Вы можете убедиться в этом, посмотрев на значение виджета в базе данных.
Кроме того, на первый взгляд данные выглядят нормально, но если вы обновите страницу, появится непроверенное содержимое. Если вы перейдете на другую страницу, например «Меню», а затем вернетесь, содержимое виджета появится, но должным образом очищено.
Почему же тогда он показывает одно в базе данных и одно во внешнем интерфейсе области администрирования при выполнении определенных шагов?
Это связано с кешем виджетов, и, к счастью, мы можем сбрасывать этот кеш по желанию, используя любые хуки, которые захотим (то есть мы можем подписаться на любое событие, а затем очистить кеш).
Из Справочника кода :
Удаляет содержимое кеша, соответствующее ключу и группе.
Обратите внимание, однако, что для этого требуется, чтобы мы предоставили ключ и необязательную группу. В Boilerplate мы использовали ярлык виджета, поскольку ключ и группа — это виджет.
Очистка кэша
Так как функцию можно подключить к любому событию, мы можем создать подписчика, которого можно подключить к любому событию. Это означает , что мы можем создать подписчика DeleteWidgetCache в нашем пространстве имен 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;
}
}
Затем мы обновим начальную загрузку, чтобы добавить подписчика в реестр, и воспользуемся пользовательским хуком, flush_widget_cache, который мы будем использовать на мгновение.
<?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();
Для целей Boilerplate мы будем использовать пользовательское событие всякий раз, когда вызывается код сериализации виджета.
Сначала мы определим вызов do_action, идентифицируем его как flush_widget_cache, а затем передадим в событие необходимые аргументы, чтобы подписчик мог их прочитать:
<?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;
}
}
А затем в подписчике мы будем очищать кеш на основе входящих аргументов:
<?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;
}
}
И это делает это.
Готов к интерфейсу
На данный момент у нас есть механизм, который может очищать кеш виджета в любое время — не только с помощью специального события, но и с любым из событий, предлагаемых WordPress.
Это может пригодиться, если вы используете Boilerplate для чего-то, что будет использовать кэшированный запрос или любой другой механизм кэширования, если на то пошло, и хотите убедиться, что содержимое понятно.
Далее мы рассмотрим рендеринг контента во внешнем интерфейсе. Мы приближаемся к концу рефакторинга Boilerplate, но осталось сделать еще немного, прежде чем мы будем готовы объединить его с основной веткой кодовой базы.