{"id":231018,"date":"2022-12-20T12:11:00","date_gmt":"2022-12-20T09:11:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231018"},"modified":"2022-12-20T12:15:09","modified_gmt":"2022-12-20T09:15:09","slug":"widgets-de-wordpress-refactorizacion-parte-10","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/widgets-de-wordpress-refactorizacion-parte-10\/","title":{"rendered":"Widgets de WordPress: Refactorizaci\u00f3n, Parte 10"},"content":{"rendered":"\n<p>En lo que respecta a la refactorizaci\u00f3n de WordPress Widget Boilerplate, estamos en un buen lugar. Se ha trabajado mucho para que la introducci\u00f3n de nuevas clases, caracter\u00edsticas y funcionalidades sea mucho m\u00e1s f\u00e1cil.<\/p>\n<p>Y no solo eso: deber\u00eda ser m\u00e1s f\u00e1cil de seguir.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/es\/widgets-de-wordpress-refactorizacion-parte-9\/\" title=\"Gracias por el trabajo en la \u00faltima publicaci\u00f3n\">Gracias por el trabajo en la \u00faltima publicaci\u00f3n<\/a>, tenemos mucho trabajo para desarrollar, es decir, una interfaz administrativa b\u00e1sica.<\/p>\n<p>Finalmente, la \u00faltima publicaci\u00f3n dec\u00eda:<\/p>\n<blockquote>\n<p>En los pr\u00f3ximos art\u00edculos, esto continuar\u00e1 evolucionando pero, como puede ver, nos estamos asegurando de tener una \u00fanica clase b\u00e1sica de funcionalidad para hablar con WordPress y una clase espec\u00edfica para representar el formulario administrativo.<\/p>\n<\/blockquote>\n<p>Y ah\u00ed es donde vamos a retomar en este art\u00edculo. Espec\u00edficamente, veremos c\u00f3mo desinfectar y serializar los datos, as\u00ed como recuperar los datos guardados en el widget.<\/p>\n<h2>El modelo de widget de WordPress: Refactorizaci\u00f3n Parte 10<\/h2>\n<h3>Refactorizaci\u00f3n de la interfaz de usuario<\/h3>\n<p>Antes de entrar en serializaci\u00f3n, 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:<\/p>\n<ul>\n<li>un t\u00edtulo,<\/li>\n<li>algo de contenido,<\/li>\n<li>y una casilla de verificaci\u00f3n.<\/li>\n<\/ul>\n<p>Esto se muestra bien, pero excluye algunas funciones clave de la <a href=\"https:\/\/codex.wordpress.org\/Widgets_API#Widgets_API\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">API de Widgets<\/a>. Es decir, debemos asegurarnos de que estamos nombrando correctamente nuestros elementos usando las siguientes funciones:<\/p>\n<ul>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/classes\/wp_widget\/get_field_id\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get_field_id<\/a><\/li>\n<li><a href=\"https:\/\/developer.wordpress.org\/reference\/classes\/wp_widget\/get_field_name\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get_field_name<\/a><\/li>\n<\/ul>\n<p>Y luego escribiremos nuestra funci\u00f3n simplemente llamada <a href=\"https:\/\/codex.wordpress.org\/Widgets_API#Widgets_API\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get<\/a>, que explicar\u00e9 en un momento.<\/p>\n<p>Las funciones anteriores son necesarias porque ayudan a WordPress a realizar un seguimiento de cu\u00e1ntas instancias del widget se est\u00e1n utilizando y cu\u00e1l est\u00e1 editando el usuario. En otras palabras, obtenemos una gran cantidad de funciones de forma gratuita.<\/p>\n<p>Antes de mostrarle el c\u00f3digo, quiero discutir brevemente el prop\u00f3sito de la\u00a0 funci\u00f3n <strong>get<\/strong> 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\u00f3n y luego hacer que recupere f\u00e1cilmente un valor para nosotros para que mantenga nuestra interfaz lo m\u00e1s limpia posible.<\/p>\n<p>Entonces, primero, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-00-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">el m\u00e9todo get<\/a> :<\/p>\n<pre><code>&lt;?php\n\n\/**\n * If the value for the key exists in the current instance of the widget, then it will\n * retrieve it. Otherwise, it will return an empty value.\n *\n * @param string $key the used to identify the value of the widget.\n * @param array $instance the options for the instance of this widget\n *\/\nprotected function get($key, $instance)\n{\n    return empty($instance[$key])? '': $instance[$key];\n}<\/code><\/pre>\n<p>Lo importante a tener en cuenta es que este m\u00e9todo acepta no solo la clave para el valor que estamos leyendo, sino tambi\u00e9n una matriz que se refiere a la instancia de la matriz.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-01-admin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Y ahora, la interfaz de usuario refactorizada<\/a> :<\/p>\n<pre><code>&lt;?php\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?&gt;\n\n&lt;div class=\"widget-content\"&gt;\n    &lt;p&gt;\n        &lt;input\n            type=\"text\"\n            id=\"&lt;?php echo esc_attr($this-&gt;get_field_id('title')); ?&gt;\"\n            name=\"&lt;?php echo esc_attr($this-&gt;get_field_name('title')); ?&gt;\"\n            value=\"&lt;?php echo $this-&gt;get('title', $instance) ?&gt;\"\n            placeholder=\"Widget Title\"\n            class=\"widefat\"\n        \/&gt;\n    &lt;\/p&gt;\n\n    &lt;p&gt;\n        &lt;textarea\n            id=\"&lt;?php echo esc_attr($this-&gt;get_field_id('content')); ?&gt;\"\n            name=\"&lt;?php echo esc_attr($this-&gt;get_field_name('content')); ?&gt;\"\n            placeholder=\"Widget Content\"\n            style=\"width:100%;\"&gt;&lt;?php echo $this-&gt;get('content', $instance) ?&gt;&lt;\/textarea&gt;\n    &lt;\/p&gt;\n\n    &lt;p&gt;\n        &lt;input\n            type=\"checkbox\"\n            value=\"on\"\n            name=\"&lt;?php echo esc_attr($this-&gt;get_field_name('display-title')); ?&gt;\"\n            id=\"&lt;?php echo esc_attr($this-&gt;get_field_id('display-title')); ?&gt;\"\n            &lt;?php checked('on', $this-&gt;get('display-title', $instance), true); ?&gt;\n            class=\"checkbox\"\n        \/&gt;\n        &lt;label for=\"&lt;?php echo esc_attr($this-&gt;get_field_id('display-title')); ?&gt;\"&gt;Display Title?&lt;\/label&gt;\n    &lt;\/p&gt;\n&lt;\/div&gt;&lt;!-- .widget-content --&gt;\n<\/code><\/pre>\n<p>Pero esto todav\u00eda 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.<\/p>\n<h3>Desinfecci\u00f3n y serializaci\u00f3n<\/h3>\n<p>A los efectos de nuestro ejemplo, vamos a ser muy estrictos en lo que permitimos. Es decir, solo admitiremos texto b\u00e1sico y eliminaremos todo de manera agresiva.<\/p>\n<p>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\u00e1sico. Podemos decorarlo un poco cuando llegue el momento de mostrarlo en el front-end, pero eso lo dejaremos para la publicaci\u00f3n correspondiente.<\/p>\n<p>Para hacer esto, vamos a usar las siguientes funciones:<\/p>\n<ul>\n<li><a href=\"https:\/\/php.net\/manual\/en\/function.strip-tags.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tira_etiquetas<\/a><\/li>\n<li><a href=\"https:\/\/php.net\/manual\/en\/function.stripslashes.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tiras<\/a><\/li>\n<\/ul>\n<p>Recuerde que tenemos dos campos en nuestro widget: el campo de t\u00edtulo y el campo de contenido. Seg\u00fan el tipo de widget que est\u00e9 creando, es posible que solo necesite una sola clase o funci\u00f3n para desinfectar los datos. En otras situaciones, es posible que necesite algo m\u00e1s complejo.<\/p>\n<p>Tenga esto en cuenta a medida que avancemos en este c\u00f3digo, ya que esta no ser\u00e1 una soluci\u00f3n \u00fanica para todos. En cambio, ser\u00e1 espec\u00edficamente para esto.<\/p>\n<p>De todos modos, para desinfectar los datos, vamos a escribir una clase espec\u00edficamente para este prop\u00f3sito y luego la pondremos a disposici\u00f3n de nuestra clase WidgetAdmin.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-02-widget-serializer-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Aqu\u00ed est\u00e1 la clase en su totalidad<\/a> con una descripci\u00f3n a continuaci\u00f3n:<\/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     * 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        return $instance;\n    }\n}\n<\/code><\/pre>\n<p>La clase debe ser directa. Toma los valores entrantes del widget, los desinfecta y luego devuelve una nueva matriz para devolverla a WordPress.<\/p>\n<p>Sin embargo, hay una trampa. Esta clase debe ser una propiedad de la\u00a0 clase <strong>Widget<\/strong> principal \u00a0que se mostr\u00f3 en la \u00faltima publicaci\u00f3n.<\/p>\n<p>En segundo lugar, el\u00a0 m\u00e9todo de <strong>actualizaci\u00f3n<\/strong> que forma parte de la API de Widgets es lo que llamar\u00e1 a esta clase. No es necesario pasar la variable <strong>$oldInstance<\/strong> al serializador, pero es necesario para el m\u00e9todo de actualizaci\u00f3n.<\/p>\n<p>Aqu\u00ed est\u00e1 la clase <strong>Widget<\/strong> <a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-03-widget-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tal como est\u00e1 construida actualmente<\/a> :<\/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\nuse WP_Widget;\n\nclass Widget extends WP_Widget\n{\n    \/**\n     * @var string unique identifier for your widget\n     *\/\n    protected $widgetSlug;\n\n    \/**\n     * Initializes the plugin by setting its properties and calling the parent class with the description.\n     *\n     * @param string           $widgetSlug       unique identifier for your widget\n     * @param WidgetSerializer $widgetSerializer the class responsible for saving widget options\n     *\/\n    public function __construct($widgetSlug)\n    {\n        $this-&gt;widgetSlug = $widgetSlug;\n\n        parent::__construct(\n            $this-&gt;getWidgetSlug(),\n            __('Widget Name', $this-&gt;getWidgetSlug()),\n            [\n                'classname' =&gt; $this-&gt;getWidgetSlug().'-class',\n                'description' =&gt; __('Short description of the widget goes here.', $this-&gt;getWidgetSlug()),\n            ]\n        );\n    }\n\n    \/**\n     * Return the widget slug.\n     *\n     * @return string slug variable\n     *\/\n    public function getWidgetSlug()\n    {\n        return $this-&gt;widgetSlug;\n    }\n\n    \/**\n     * Displays the administrative view of the form and includes the options\n     * for the instance of the widget as arguments passed into the function.\n     *\n     * @param array $instance the options for the instance of this widget\n     *\/\n    public function form($instance)\n    {\n        include plugin_dir_path(__FILE__).'Views\/Admin.php';\n    }\n\n    \/**\n     * Updates the values of the widget. Uses the serialization class to sanitize the\n     * information before saving it.\n     *\n     * @param array $newInstance the values to be sanitized and saved\n     * @param array $oldInstance the values that were originally saved\n     *\/\n    public function update($newInstance, $oldInstance)\n    {\n        return $this-&gt;widgetSerializer-&gt;update($newInstance, $oldInstance);\n    }\n\n    \/**\n     * If the value for the key exists in the current instance of the widget, then it will\n     * retrieve it. Otherwise, it will return an empty value.\n     *\n     * @param string $key      the used to identify the value of the widget\n     * @param array  $instance the options for the instance of this widget\n     *\/\n    protected function get($key, $instance)\n    {\n        return empty($instance[$key])? '': $instance[$key];\n    }\n}\n<\/code><\/pre>\n<p>Pero si actualiza la p\u00e1gina, es posible que observe que la desinfecci\u00f3n y la serializaci\u00f3n no parecen funcionar al recuperar los datos. Y eso es lo que vamos a ver en el siguiente post.<\/p>\n<h2>Recuperando datos<\/h2>\n<p>Tenga en cuenta que aunque la funcionalidad parece incompleta para esto (ya que los datos sin desinfectar a\u00fan se muestran), nos enfocamos en asegurarnos de que estamos escribiendo clases con cohesi\u00f3n, responsabilidad y que no est\u00e9n estrechamente acopladas.<\/p>\n<p>Vamos a iterar un poco m\u00e1s sobre esto en la pr\u00f3xima publicaci\u00f3n. As\u00ed que estudie el c\u00f3digo anterior, implem\u00e9ntelo si eso es lo que ha estado haciendo, y partiremos de ah\u00ed en la pr\u00f3xima publicaci\u00f3n.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Y ahora, comenzamos a agregar la funcionalidad de desinfecci\u00f3n y serializaci\u00f3n en WordPress Widget Boilerplate.<\/p>\n","protected":false},"author":1,"featured_media":234964,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[716,840],"tags":[1172],"class_list":["post-231018","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-desarrollador","category-tutoriales","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/231018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=231018"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/231018\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/234964"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=231018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=231018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=231018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}