{"id":230890,"date":"2022-12-21T13:03:00","date_gmt":"2022-12-21T10:03:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230890"},"modified":"2022-12-07T10:29:50","modified_gmt":"2022-12-07T07:29:50","slug":"wordpress-widgets-refactoring-del-11","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/sv\/wordpress-widgets-refactoring-del-11\/","title":{"rendered":"WordPress-widgets: Refactoring, del 11"},"content":{"rendered":"\n<p>I f\u00f6rra inl\u00e4gget gick vi igenom en hel del refaktorering som separerade bekymmer i sina egna klasser.<\/p>\n<p>I slut\u00e4ndan hj\u00e4lper detta att visa hur vi kan bibeh\u00e5lla en h\u00f6g niv\u00e5 av sammanh\u00e5llning samtidigt som vi inte bara arbetar med klasser i WordPress utan g\u00f6r det tillsammans med redan existerande API:er.<\/p>\n<p>Eftersom de senaste inl\u00e4ggen om omstrukturering av kodbasen har varit s\u00e5 l\u00e5nga, \u00e4r den nuvarande upps\u00e4ttningen av inl\u00e4gg fokuserad p\u00e5 sm\u00e5, inkrementella f\u00f6r\u00e4ndringar och d\u00e4rmed kortare, mer fokuserade inl\u00e4gg.<\/p>\n<p>Som n\u00e4mndes i f\u00f6reg\u00e5ende artikel:<\/p>\n<blockquote>\n<p>Men om du uppdaterar sidan kanske du m\u00e4rker att saneringen och serialiseringen inte verkar fungera n\u00e4r du h\u00e4mtar data. Och det \u00e4r vad vi ska titta p\u00e5 i n\u00e4sta inl\u00e4gg.<\/p>\n<\/blockquote>\n<p>S\u00e5 det \u00e4r d\u00e4r vi ska ta upp i den h\u00e4r artikeln.<\/p>\n<h2>WordPress Widget Boilerplate: Refactoring del 11<\/h2>\n<p>Innan du skriver n\u00e5gon kod \u00e4r det f\u00f6rsta att l\u00e4gga m\u00e4rke till att om du fyller i ett av inneh\u00e5llsomr\u00e5dena i widgeten (som titeln) med n\u00e5got <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-00-example-title-js\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">s\u00e5 h\u00e4r<\/a> :<\/p>\n<pre><code>&lt;script type=\"text\/javascript\"&gt;This is the Title&lt;\/script&gt;<\/code><\/pre>\n<p>Och klicka sedan p\u00e5 Spara, det faktiska inneh\u00e5llet saneras och skrivs till databasen. Du kan se att detta \u00e4r sant genom att titta p\u00e5 widgetens v\u00e4rde i databasen.<\/p>\n<p>Vidare ser data bra ut vid f\u00f6rsta anblicken, men om du uppdaterar sidan visas det osaniserade inneh\u00e5llet. Om du navigerar till en annan sida, som Menyer, och sedan kommer tillbaka, visas widgetinneh\u00e5llet men ordentligt sanerat.<\/p>\n<p>Varf\u00f6r visar det d\u00e5 en sak i databasen och en sak p\u00e5 administrationsomr\u00e5dets front-end n\u00e4r man utf\u00f6r vissa steg?<\/p>\n<p>Detta har att g\u00f6ra med widget-cachen och lyckligtvis kan vi spola denna cache efter behag med hj\u00e4lp av vilka krokar vi vill (det vill s\u00e4ga vi kan prenumerera p\u00e5 vilken h\u00e4ndelse som helst och sedan f\u00e5 den att spola cachen).<\/p>\n<\/p>\n<p>Fr\u00e5n <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_cache_delete\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">kodreferensen<\/a> :<\/p>\n<blockquote>\n<p>Tar bort cacheminneh\u00e5llet som matchar nyckel och grupp.<\/p>\n<\/blockquote>\n<p>Observera dock att det kr\u00e4ver att vi tillhandah\u00e5ller nyckeln och en valfri grupp. I Boilerplate har vi anv\u00e4nt widgetens slug som nyckeln och gruppen \u00e4r widget.<\/p>\n<h3>Rensa cachen<\/h3>\n<p>Eftersom funktionen kan kopplas till vilket event som helst kan vi skapa en prenumerant som vi kan koppla till vilket event som helst. Det betyder att <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-01-delete-widget-cache-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vi kan skapa DeleteWidgetCache-prenumeranter i v\u00e5rt namnomr\u00e5de f\u00f6r prenumeranter:<\/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>Vi kommer sedan att <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-02-wordpress-widget-plugin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">uppdatera bootstrap<\/a> f\u00f6r att l\u00e4gga till prenumeranten i registret och vi kommer att anv\u00e4nda en anpassad hook, flush_widget_cache, som vi kommer att anv\u00e4nda tillf\u00e4lligt.<\/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>F\u00f6r syftet med Boilerplate kommer vi att anv\u00e4nda den anpassade h\u00e4ndelsen n\u00e4rhelst widgetens serialiseringskod anropas.<\/p>\n<p>F\u00f6rst definierar vi ett <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/do_action\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">do_action<\/a> -anrop, identifierar det som flush_widget_cache, och sedan skickar <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-03-widget-serialization-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vi de n\u00f6dv\u00e4ndiga argumenten<\/a> till h\u00e4ndelsen s\u00e5 att abonnenten kan l\u00e4sa dem:<\/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>Och sedan i abonnenten <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-04-delete-widget-cache-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">spolar vi cachen<\/a> baserat p\u00e5 de inkommande argumenten:<\/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>Och det g\u00f6r det.<\/p>\n<h2>Redo f\u00f6r front-end<\/h2>\n<p>Vid det h\u00e4r laget har vi en mekanism p\u00e5 plats som kan spola widgetcachen n\u00e4r vi vill \u2013 inte bara med en anpassad h\u00e4ndelse \u2013 utan med alla h\u00e4ndelser som erbjuds av WordPress ocks\u00e5.<\/p>\n<p>Detta kan vara praktiskt om du anv\u00e4nder Boilerplate f\u00f6r n\u00e5got som kommer att anv\u00e4nda en cachad fr\u00e5ga eller n\u00e5gon annan cachningsmekanism, f\u00f6r den delen, och vill se till att inneh\u00e5llet \u00e4r klart.<\/p>\n<p>D\u00e4refter ska vi titta p\u00e5 rendering av inneh\u00e5ll p\u00e5 front-end. Vi n\u00e4rmar oss slutet, av omstruktureringen av Boilerplate, men det finns bara lite mer att g\u00f6ra innan vi \u00e4r redo att sl\u00e5 samman den i kodbasens huvudgren.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Inspelningsk\u00e4lla:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Varf\u00f6r visar d\u00e5 WordPress en sak i databasen och en sak i administrationsomr\u00e5det? Detta har att g\u00f6ra med widgetcachen.<\/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":[838,901,724],"tags":[1173],"class_list":["post-230890","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guide-foer-nyboerjare","category-koda","category-utvecklaren","tag-affiai-sv"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/230890","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/comments?post=230890"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/230890\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media\/235955"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media?parent=230890"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/categories?post=230890"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/tags?post=230890"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}