{"id":231485,"date":"2022-12-21T13:10:00","date_gmt":"2022-12-21T10:10:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231485"},"modified":"2022-12-07T10:29:42","modified_gmt":"2022-12-07T07:29:42","slug":"wordpress-widgetit-refaktorointi-osa-11","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fi\/wordpress-widgetit-refaktorointi-osa-11\/","title":{"rendered":"WordPress-widgetit: Refaktorointi, osa 11"},"content":{"rendered":"\n<p>Edellisess\u00e4 postauksessa k\u00e4vimme l\u00e4pi monia uudelleenj\u00e4rjestelyj\u00e4, jotka erottivat huolenaiheet omiin luokkiinsa.<\/p>\n<p>Viime k\u00e4dess\u00e4 t\u00e4m\u00e4 auttaa osoittamaan, kuinka voimme yll\u00e4pit\u00e4\u00e4 korkeaa koheesion tasoa ty\u00f6skennelless\u00e4mme WordPressin luokkien lis\u00e4ksi my\u00f6s olemassa olevien API:iden kanssa.<\/p>\n<p>Koska viimeiset viestit koodikannan uudelleenmuodostamisesta ovat olleet niin pitki\u00e4, nykyiset viestit keskittyv\u00e4t pieniin, asteittain tapahtuviin muutoksiin ja siten lyhyempiin, tarkempiin viesteihin.<\/p>\n<p>Kuten edellisess\u00e4 artikkelissa mainittiin:<\/p>\n<blockquote>\n<p>Mutta jos p\u00e4ivit\u00e4t sivun, saatat huomata, ett\u00e4 desinfiointi ja serialisointi eiv\u00e4t n\u00e4yt\u00e4 toimivan tietoja haettaessa. Ja sit\u00e4 aiomme tarkastella seuraavassa postauksessa.<\/p>\n<\/blockquote>\n<p>Joten t\u00e4ss\u00e4 artikkelissa poimimme sen.<\/p>\n<h2>WordPress Widget Boilerplate: Refactoring osa 11<\/h2>\n<p>Ennen kuin kirjoitat mit\u00e4\u00e4n koodia, huomaa ensin, ett\u00e4 jos t\u00e4yt\u00e4t yhden widgetin sis\u00e4lt\u00f6alueista (kuten otsikon) jollain <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-00-example-title-js\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">t\u00e4mm\u00f6isell\u00e4<\/a> :<\/p>\n<pre><code>&lt;script type=\"text\/javascript\"&gt;This is the Title&lt;\/script&gt;<\/code><\/pre>\n<p>Napsauta sitten Tallenna, todellinen sis\u00e4lt\u00f6 desinfioidaan ja kirjoitetaan tietokantaan. Voit n\u00e4hd\u00e4 t\u00e4m\u00e4n olevan totta katsomalla widgetin arvoa tietokannassa.<\/p>\n<p>Lis\u00e4ksi tiedot n\u00e4ytt\u00e4v\u00e4t ensi silm\u00e4yksell\u00e4 hyv\u00e4lt\u00e4, mutta jos p\u00e4ivit\u00e4t sivun, puhdistamaton sis\u00e4lt\u00f6 tulee n\u00e4kyviin. Jos siirryt toiselle sivulle, kuten valikot, ja palaat sitten takaisin, widgetin sis\u00e4lt\u00f6 n\u00e4kyy, mutta se on kunnolla desinfioitu.<\/p>\n<p>Miksi se sitten n\u00e4ytt\u00e4\u00e4 yht\u00e4 asiaa tietokannassa ja yht\u00e4 asiaa hallinta-alueen etuosassa tiettyj\u00e4 vaiheita suoritettaessa?<\/p>\n<p>T\u00e4m\u00e4 liittyy widget-v\u00e4limuistiin, ja onneksi voimme tyhjent\u00e4\u00e4 t\u00e4m\u00e4n v\u00e4limuistin haluamallamme tavalla k\u00e4ytt\u00e4m\u00e4ll\u00e4 mit\u00e4 tahansa haluamiasi koukkuja (eli voimme tilata mink\u00e4 tahansa tapahtuman ja pyyt\u00e4\u00e4 sen sitten tyhjent\u00e4m\u00e4\u00e4n v\u00e4limuistin).<\/p>\n<\/p>\n<p><a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_cache_delete\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Koodiviittauksesta<\/a>: _<\/p>\n<blockquote>\n<p>Poistaa v\u00e4limuistin sis\u00e4lt\u00f6\u00e4 vastaavan avaimen ja ryhm\u00e4n.<\/p>\n<\/blockquote>\n<p>Huomaa kuitenkin, ett\u00e4 se edellytt\u00e4\u00e4 avaimen ja valinnaisen ryhm\u00e4n toimittamista. Boilerplatessa olemme k\u00e4ytt\u00e4neet widgetin etanaa avaimena ja ryhm\u00e4 on widget.<\/p>\n<h3>V\u00e4limuistin tyhjent\u00e4minen<\/h3>\n<p>Koska toiminto voidaan kytke\u00e4 mihin tahansa tapahtumaan, voimme luoda tilaajan, jonka voimme liitt\u00e4\u00e4 mihin tahansa tapahtumaan. T\u00e4m\u00e4 tarkoittaa <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-01-delete-widget-cache-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">, ett\u00e4 voimme luoda DeleteWidgetCache-tilaajan Tilaajan nimiavaruuteen:<\/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>P\u00e4ivit\u00e4mme sitten <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-02-wordpress-widget-plugin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">bootstrapin<\/a> lis\u00e4t\u00e4ksemme tilaajan rekisteriin ja k\u00e4yt\u00e4mme mukautettua koukkua, flush_widget_cache, jota k\u00e4yt\u00e4mme hetkellisesti.<\/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>Boilerplatea varten k\u00e4yt\u00e4mme mukautettua tapahtumaa aina, kun widgetin serialisointikoodia kutsutaan.<\/p>\n<p>Ensin m\u00e4\u00e4rit\u00e4mme <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/do_action\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">do_action-<\/a> kutsun, tunnistamme sen flush_widget_cacheksi ja v\u00e4lit\u00e4mme sitten tapahtumalle <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-03-widget-serialization-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tarvittavat argumentit<\/a>, jotta tilaaja voi lukea ne:<\/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>Ja sitten tilaajassa <a href=\"https:\/\/gist.github.com\/tommcfarlin\/39038338730b7141a19c3d2f48801dac#file-04-delete-widget-cache-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tyhjenn\u00e4mme v\u00e4limuistin<\/a> saapuvien argumenttien perusteella:<\/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>Ja se tekee sen.<\/p>\n<h2>Valmiina etup\u00e4\u00e4h\u00e4n<\/h2>\n<p>T\u00e4ss\u00e4 vaiheessa meill\u00e4 on k\u00e4yt\u00f6ss\u00e4 mekanismi, joka voi tyhjent\u00e4\u00e4 widgetin v\u00e4limuistin milloin tahansa \u2013 ei vain mukautetun tapahtuman avulla \u2013 vaan my\u00f6s mink\u00e4 tahansa WordPressin tarjoaman tapahtuman kanssa.<\/p>\n<p>T\u00e4st\u00e4 voi olla hy\u00f6ty\u00e4, jos k\u00e4yt\u00e4t Boilerplatea johonkin, joka k\u00e4ytt\u00e4\u00e4 v\u00e4limuistissa olevaa kysely\u00e4 tai mit\u00e4 tahansa muuta v\u00e4limuistimekanismia, ja haluat varmistaa, ett\u00e4 sis\u00e4lt\u00f6 on selke\u00e4.<\/p>\n<p>Seuraavaksi aiomme tarkastella sis\u00e4ll\u00f6n render\u00f6imist\u00e4 k\u00e4ytt\u00f6liittym\u00e4ss\u00e4. Olemme l\u00e4hestym\u00e4ss\u00e4 Boilerplaten uudelleenmuodostuksen loppua, mutta viel\u00e4 on v\u00e4h\u00e4n teht\u00e4v\u00e4\u00e4 ennen kuin olemme valmiita yhdist\u00e4m\u00e4\u00e4n sen koodikannan p\u00e4\u00e4haaraan.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Miksi WordPress sitten n\u00e4ytt\u00e4\u00e4 yhden asian tietokannassa ja yht\u00e4 asian hallinta-alueella? T\u00e4m\u00e4 liittyy widgetin v\u00e4limuistiin.<\/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":[719,895,834],"tags":[1166],"class_list":["post-231485","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kehittaejae","category-koodi","category-opas-aloittelijoille","tag-affiai-fi"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/231485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/comments?post=231485"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/231485\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media\/235955"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media?parent=231485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/categories?post=231485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/tags?post=231485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}