{"id":231483,"date":"2022-12-21T12:54:00","date_gmt":"2022-12-21T09:54:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231483"},"modified":"2022-12-07T10:29:49","modified_gmt":"2022-12-07T07:29:49","slug":"widgets-do-wordpress-refatoracao-parte-11","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/widgets-do-wordpress-refatoracao-parte-11\/","title":{"rendered":"Widgets do WordPress: Refatora\u00e7\u00e3o, Parte 11"},"content":{"rendered":"\n<p>No post anterior, passamos por muitas refatora\u00e7\u00f5es que separavam as preocupa\u00e7\u00f5es em suas pr\u00f3prias classes.<\/p>\n<p>Em \u00faltima an\u00e1lise, isso ajuda a mostrar como podemos manter um alto n\u00edvel de coes\u00e3o enquanto n\u00e3o apenas trabalhamos com classes no WordPress, mas tamb\u00e9m com APIs pr\u00e9-existentes.<\/p>\n<p>Como as \u00faltimas postagens sobre refatora\u00e7\u00e3o da base de c\u00f3digo foram t\u00e3o longas, o conjunto atual de postagens est\u00e1 focado em pequenas altera\u00e7\u00f5es incrementais e, portanto, em postagens mais curtas e mais focadas.<\/p>\n<p>Conforme mencionado no artigo anterior:<\/p>\n<blockquote>\n<p>Mas se voc\u00ea atualizar a p\u00e1gina, poder\u00e1 notar que a sanitiza\u00e7\u00e3o e a serializa\u00e7\u00e3o parecem n\u00e3o funcionar ao recuperar os dados. E \u00e9 isso que veremos no pr\u00f3ximo post.<\/p>\n<\/blockquote>\n<p>Ent\u00e3o \u00e9 a\u00ed que vamos pegar neste artigo.<\/p>\n<h2>The WordPress Widget Boilerplate: Refatorando Parte 11<\/h2>\n<p>Antes de escrever qualquer c\u00f3digo, a primeira coisa a notar \u00e9 que se voc\u00ea preencher uma das \u00e1reas de conte\u00fado do widget (como o t\u00edtulo) com algo <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-00-example-title-js\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">assim<\/a> :<\/p>\n<pre><code>&lt;script type=\"text\/javascript\"&gt;This is the Title&lt;\/script&gt;<\/code><\/pre>\n<p>E, em seguida, clique em Salvar, o conte\u00fado real ser\u00e1 higienizado e gravado no banco de dados. Voc\u00ea pode ver que isso \u00e9 verdade observando o valor do widget no banco de dados.<\/p>\n<p>Al\u00e9m disso, os dados parecem bons \u00e0 primeira vista, mas se voc\u00ea atualizar a p\u00e1gina, o conte\u00fado n\u00e3o limpo aparecer\u00e1. Se voc\u00ea navegar para outra p\u00e1gina, como Menus, e depois voltar, o conte\u00fado do widget aparecer\u00e1, mas devidamente higienizado.<\/p>\n<p>Por que, ent\u00e3o, ele mostra uma coisa no banco de dados e uma coisa no front-end da \u00e1rea de administra\u00e7\u00e3o ao executar determinadas etapas?<\/p>\n<p>Isso tem a ver com o cache do widget e, felizmente, podemos liberar esse cache \u00e0 vontade usando os ganchos que quisermos (ou seja, podemos assinar qualquer evento e fazer com que ele libere o cache).<\/p>\n<\/p>\n<p>Da <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_cache_delete\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">refer\u00eancia de c\u00f3digo<\/a> :<\/p>\n<blockquote>\n<p>Remove a chave e o grupo correspondentes ao conte\u00fado do cache.<\/p>\n<\/blockquote>\n<p>Observe, no entanto, que isso requer que forne\u00e7amos a chave e um grupo opcional. No Boilerplate, usamos o slug do widget como a chave e o grupo \u00e9 widget.<\/p>\n<h3>Limpando o Cache<\/h3>\n<p>Como a fun\u00e7\u00e3o pode ser vinculada a qualquer evento, podemos criar um assinante que podemos vincular a qualquer evento. Isso significa <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-01-delete-widget-cache-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">que podemos criar um assinante DeleteWidgetCache em nosso namespace Subscriber:<\/a><\/p>\n<pre><code>&lt;?php\n\n&lt;?php\n\n\/*\n * This file is part of WordPress Widget Boilerplate\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * Deletes the cached contents of the widget.\n *\/\nclass DeleteWidgetCacheSubscriber extends AbstractSubscriber\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    \/**\n     * Flushes the widget's cache based on the key that's specified in the function arguments.\n     *\/\n    public function load()\n    {\n        \/* Because we're implementing an abstract class, we'll parse arguments from the\n         * func_get_args().\n         *\/\n        $args = func_get_args();\n        if (!$this-&gt;hasValidArguments($args)) {\n            return;\n        }\n\n        \/\/ TODO: More to come...\n    }\n\n    \/**\n     * Verifies that we have valid arguments with which to work.\n     *\n     * @param array $args the array of arguments we are validating\n     *\n     * @return bool true if the arguments are valid; otherwise, false\n     *\/\n    private function hasValidArguments(array $args): bool\n    {\n        \/\/ First, check the initial index of the arguments.\n        if (!isset($args[0])) {\n            return false;\n        }\n\n        \/\/ Next, check the values of the arguments for the widget key and group.\n        $args = $args[0];\n        if (!isset($args[0]) &amp;&amp; !isset($args[1])) {\n            return false;\n        }\n\n        return true;\n    }\n}\n<\/code><\/pre>\n<p>Em seguida, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-02-wordpress-widget-plugin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">atualizaremos o bootstrap<\/a> para adicionar o assinante ao registro e usaremos um gancho personalizado, flush_widget_cache, que usaremos momentaneamente.<\/p>\n<pre><code>&lt;?php\n\/**\n * WordPress Widget Boilerplate\n *\n * The WordPress Widget Boilerplate is an organized, maintainable boilerplate for building\n * widgets using WordPress best practices.\n *\n * @package   WordPressWidgetBoilerplate\n * @author    Your Name &lt;email@example.com&gt;\n * @license   GPL-3.0+\n * @link      http:\/\/example.com\n * @copyright 2018 - 2019 Your Name or Company Name\n *\n * @wordpress-plugin\n * Plugin Name:       WordPress Widget Boilerplate\n * Plugin URI:        https:\/\/github.com\/tommcfarlin\/wordpress-widget-boilerplate\n * Description:       An object-oriented foundation for building WordPress Widgets.\n * Version:           1.0.0\n * Author:            Tom McFarlin\n * Author URI:        https:\/\/tommcfarlin.com\n * Text Domain:       widget-name\n * License:           GPL-3.0+\n * License URI:       http:\/\/www.gnu.org\/licenses\/gpl-3.0.txt\n * Domain Path:       \/lang\n *\/\n\nnamespace WordPressWidgetBoilerplate;\n\nuse WordPressWidgetBoilerplateUtilitiesRegistry;\nuse WordPressWidgetBoilerplatePlugin;\nuse WordPressWidgetBoilerplateSubscriberWidgetSubscriber;\nuse WordPressWidgetBoilerplateSubscriberDeleteWidgetCacheSubscriber;\n\n\/\/ Prevent this file from being called directly.\ndefined('WPINC') || die;\n\n\/\/ Include the autoloader.\nrequire_once __DIR__. '\/vendor\/autoload.php';\n\n\/\/ Setup a filter so we can retrieve the registry throughout the plugin.\n$registry = new Registry();\nadd_filter('wpwBoilerplateRegistry', function() use ($registry) {\n    return $registry;\n});\n\n\/\/ Add subscribers.\n$registry-&gt;add('deleteWidgetCacheSubscriber', new DeleteWidgetCacheSubscriber('flush_widget_cache'));\n\n\/\/ Add the Widget base class to the Registry.\n$registry-&gt;add('widgetSubscriber', new WidgetSubscriber('widgets_init'));\n\n\/\/ Start the machine.\n(new Plugin($registry))-&gt;start();\n<\/code><\/pre>\n<p>Para os prop\u00f3sitos do Boilerplate, usaremos o evento customizado sempre que o c\u00f3digo de serializa\u00e7\u00e3o do widget for chamado.<\/p>\n<p>Primeiro, vamos definir uma\u00a0 chamada <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/do_action\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">do_action<\/a>, identific\u00e1-la como flush_widget_cache e, em seguida <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-03-widget-serialization-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">, passar os argumentos necess\u00e1rios<\/a> para o evento para que o assinante possa l\u00ea-los:<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of WordPress Widget Boilerplate\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace WordPressWidgetBoilerplateWordPress;\n\n\/**\n * Santiizes and saves the data for the widget.\n *\/\nclass WidgetSerializer\n{\n    \/**\n     * @var string a reference to the slug of the widget to which the serialier is associated\n     *\/\n    private $widgetSlug;\n\n    \/**\n     * Initializes the class.\n     *\n     * @param string a reference to the slug of the widget to which the serialier is associated\n     *\/\n    public function __construct(string $widgetSlug)\n    {\n        $this-&gt;widgetSlug = $widgetSlug;\n    }\n\n    \/**\n     * Updates the values of the widget. Sanitizes the information before saving it.\n     *\n     * @param array $newInstance the array of new options to save\n     *\/\n    public function update($newInstance)\n    {\n        $instance = [];\n        foreach ($newInstance as $key =&gt; $value) {\n            $instance[$key] = strip_tags(\n                stripslashes($value)\n            );\n        }\n\n        do_action('flush_widget_cache', [$this-&gt;widgetSlug, 'widget']);\n\n        return $instance;\n    }\n}\n<\/code><\/pre>\n<p>E, em seguida, no assinante, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-04-delete-widget-cache-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">liberaremos o cache<\/a> com base nos argumentos recebidos:<\/p>\n<pre><code>&lt;?php\n\n&lt;?php\n\n\/*\n * This file is part of WordPress Widget Boilerplate\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * Deletes the cached contents of the widget.\n *\/\nclass DeleteWidgetCacheSubscriber extends AbstractSubscriber\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    \/**\n     * Flushes the widget's cache based on the key that's specified in the function arguments.\n     *\/\n    public function load()\n    {\n        \/* Because we're implementing an abstract class, we'll parse arguments from the\n         * func_get_args().\n         *\/\n        $args = func_get_args();\n        if (!$this-&gt;hasValidArguments($args)) {\n            return;\n        }\n\n        $args = $args[0];\n        wp_cache_delete($args[0], $args[1]);\n    }\n\n    \/**\n     * Verifies that we have valid arguments with which to work.\n     *\n     * @param array $args the array of arguments we are validating\n     *\n     * @return bool true if the arguments are valid; otherwise, false\n     *\/\n    private function hasValidArguments(array $args): bool\n    {\n        \/\/ First, check the initial index of the arguments.\n        if (!isset($args[0])) {\n            return false;\n        }\n\n        \/\/ Next, check the values of the arguments for the widget key and group.\n        $args = $args[0];\n        if (!isset($args[0]) &amp;&amp; !isset($args[1])) {\n            return false;\n        }\n\n        return true;\n    }\n}\n<\/code><\/pre>\n<p>E isso faz isso.<\/p>\n<h2>Pronto para o Front-End<\/h2>\n<p>Neste ponto, temos um mecanismo que pode liberar o cache do widget sempre que quisermos \u2013 n\u00e3o apenas com um evento personalizado \u2013 mas tamb\u00e9m com qualquer um dos eventos oferecidos pelo WordPress.<\/p>\n<p>Isso pode ser \u00fatil se voc\u00ea estiver usando o Boilerplate para algo que usar\u00e1 uma consulta em cache ou qualquer outro mecanismo de cache, para esse assunto, e quiser ter certeza de que o conte\u00fado est\u00e1 claro.<\/p>\n<p>Em seguida, veremos a renderiza\u00e7\u00e3o de conte\u00fado no front-end. Estamos chegando ao fim da refatora\u00e7\u00e3o do Boilerplate, mas h\u00e1 um pouco mais a fazer antes de estarmos prontos para merge-lo no branch master da base de c\u00f3digo.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Por que, ent\u00e3o, o WordPress mostra uma coisa no banco de dados e outra na \u00e1rea de administra\u00e7\u00e3o? Isso tem a ver com o cache do widget.<\/p>\n","protected":false},"author":1,"featured_media":235955,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,722,837],"tags":[1170],"class_list":["post-231483","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-guia-para-iniciantes","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/231483","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=231483"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/231483\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/235955"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=231483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=231483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=231483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}