{"id":230771,"date":"2022-12-20T12:07:00","date_gmt":"2022-12-20T09:07:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230771"},"modified":"2022-12-20T12:10:12","modified_gmt":"2022-12-20T09:10:12","slug":"widzety-wordpress-refaktoryzacja-czesc-10","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-10\/","title":{"rendered":"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 10"},"content":{"rendered":"\n<p>Je\u015bli chodzi o refaktoryzacj\u0119 WordPress Widget Boilerplate, jeste\u015bmy w dobrym miejscu. Wykonano du\u017co pracy, aby wprowadzanie nowych klas, funkcji i funkcjonalno\u015bci by\u0142o znacznie prostsze.<\/p>\n<p>I nie tylko to: powinno by\u0107 \u0142atwiej \u015bledzi\u0107.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-9\/\" title=\"Dzi\u0119ki pracy w ostatnim po\u015bcie\">Dzi\u0119ki pracy w ostatnim po\u015bcie<\/a> mamy du\u017co pracy do zbudowania \u2013 mianowicie podstawowy interfejs administracyjny.<\/p>\n<p>Wreszcie ostatni post m\u00f3wi\u0142:<\/p>\n<blockquote>\n<p>W ci\u0105gu kilku nast\u0119pnych artyku\u0142\u00f3w b\u0119dzie to ewoluowa\u0107, ale jak wida\u0107, upewniamy si\u0119, \u017ce mamy jedn\u0105 podstawow\u0105 klas\u0119 funkcjonalno\u015bci do komunikacji z WordPressem i klas\u0119 specjalnie do renderowania formularza administracyjnego.<\/p>\n<\/blockquote>\n<p>I w\u0142a\u015bnie to zajmiemy si\u0119 w tym artykule. W szczeg\u00f3lno\u015bci przyjrzymy si\u0119 oczyszczaniu i serializacji danych, a tak\u017ce pobieraniu danych zapisanych w wid\u017cecie.<\/p>\n<h2>WordPress Widget Boilerplate: Refaktoryzacja Cz\u0119\u015b\u0107 10<\/h2>\n<h3>Refaktoryzacja interfejsu u\u017cytkownika<\/h3>\n<p>Zanim przejdziemy do serializacji, musimy wykona\u0107 niewielk\u0105 prac\u0119 w naszym widoku administracyjnym. Przypomnij sobie z poprzednich post\u00f3w z serii, \u017ce zbudowali\u015bmy formularz, kt\u00f3ry akceptuje:<\/p>\n<ul>\n<li>tytu\u0142,<\/li>\n<li>troch\u0119 tre\u015bci,<\/li>\n<li>i pole wyboru.<\/li>\n<\/ul>\n<p>Wy\u015bwietla si\u0119 to dobrze, ale wyklucza niekt\u00f3re kluczowe funkcje <a href=\"https:\/\/codex.wordpress.org\/Widgets_API#Widgets_API\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">interfejsu Widgets API<\/a>. Mianowicie musimy upewni\u0107 si\u0119, \u017ce poprawnie nazywamy nasze elementy za pomoc\u0105 nast\u0119puj\u0105cych funkcji:<\/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\">pobierz_nazwa_pola<\/a><\/li>\n<\/ul>\n<p>A potem napiszemy nasz\u0105 funkcj\u0119 o nazwie po prostu <a href=\"https:\/\/codex.wordpress.org\/Widgets_API#Widgets_API\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get<\/a>, kt\u00f3r\u0105 wyja\u015bni\u0119 za chwil\u0119.<\/p>\n<p>Powy\u017csze funkcje s\u0105 niezb\u0119dne, poniewa\u017c pomagaj\u0105 WordPressowi \u015bledzi\u0107, ile wyst\u0105pie\u0144 wid\u017cetu jest u\u017cywanych i kt\u00f3re z nich edytuje u\u017cytkownik. Innymi s\u0142owy, du\u017co funkcjonalno\u015bci dostajemy za darmo.<\/p>\n<p>Zanim poka\u017c\u0119 kod, chc\u0119 kr\u00f3tko om\u00f3wi\u0107 przeznaczenie\u00a0 funkcji <strong>get<\/strong>, kt\u00f3r\u0105 zamierzamy wprowadzi\u0107. Kr\u00f3tko m\u00f3wi\u0105c, jest to spos\u00f3b, w jaki mo\u017cemy przekaza\u0107 klucz (jak w kluczu w parze klucz\/warto\u015b\u0107) do funkcji, a nast\u0119pnie \u0142atwo pobra\u0107 dla nas warto\u015b\u0107, tak aby nasz interfejs by\u0142 tak czysty, jak to mo\u017cliwe.<\/p>\n<p>Tak wi\u0119c najpierw <a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-00-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">metoda 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>Nale\u017cy zauwa\u017cy\u0107, \u017ce ta metoda akceptuje nie tylko klucz dla odczytanej warto\u015bci, ale tak\u017ce tablic\u0119 odwo\u0142uj\u0105c\u0105 si\u0119 do instancji tablicy.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-01-admin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">A teraz zrefaktoryzowany interfejs u\u017cytkownika<\/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>Ale to wci\u0105\u017c powoduje brak funkcjonalno\u015bci i pozostawia nam prac\u0119 do wykonania. Mianowicie musimy oczy\u015bci\u0107 dane i przekaza\u0107 je z powrotem do WordPressa, aby zapisywa\u0142 dane.<\/p>\n<h3>Sanityzacja i serializacja<\/h3>\n<p>Na potrzeby naszego przyk\u0142adu b\u0119dziemy bardzo surowi w tym, na co pozwalamy. Mianowicie zamierzamy wspiera\u0107 tylko podstawowy tekst i zamierzamy agresywnie usuwa\u0107 wszystko.<\/p>\n<p>Oznacza to, \u017ce nie pozwolimy na znaczniki ani nic podobnego. Zamiast tego usuniemy wszystko, co nie jest tekstem podstawowym. Mo\u017cemy go troch\u0119 udekorowa\u0107, gdy przyjdzie czas na wy\u015bwietlenie go na froncie, ale zostawiamy to do odpowiedniego postu.<\/p>\n<p>W tym celu u\u017cyjemy nast\u0119puj\u0105cych funkcji:<\/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\">strip_tags<\/a><\/li>\n<li><a href=\"https:\/\/php.net\/manual\/en\/function.stripslashes.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">paski uko\u015bne<\/a><\/li>\n<\/ul>\n<p>Przypomnijmy, \u017ce w naszym widgecie mamy dwa pola \u2013 tytu\u0142 i tre\u015b\u0107. W zale\u017cno\u015bci od typu wid\u017cetu, kt\u00f3ry tworzysz, mo\u017cesz potrzebowa\u0107 tylko jednej klasy lub funkcji do oczyszczenia danych. W innych sytuacjach mo\u017cesz potrzebowa\u0107 czego\u015b bardziej z\u0142o\u017conego.<\/p>\n<p>Miej to na uwadze, przechodz\u0105c przez ten kod, poniewa\u017c nie b\u0119dzie to rozwi\u0105zanie uniwersalne. Zamiast tego b\u0119dzie specjalnie do tego.<\/p>\n<p>W ka\u017cdym razie, aby oczy\u015bci\u0107 dane, napiszemy klas\u0119 specjalnie do tego celu, a nast\u0119pnie udost\u0119pnimy j\u0105 naszej klasie 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\">Oto ca\u0142a klasa<\/a> wraz z opisem do na\u015bladowania:<\/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>Klasa powinna by\u0107 prosta. Pobiera przychodz\u0105ce warto\u015bci wid\u017cetu, oczyszcza je, a nast\u0119pnie zwraca now\u0105 tablic\u0119, kt\u00f3ra ma zosta\u0107 przekazana z powrotem do WordPressa.<\/p>\n<p>Jest jednak pewien haczyk. Ta klasa musi by\u0107 w\u0142a\u015bciwo\u015bci\u0105 g\u0142\u00f3wnej\u00a0 klasy <strong>Widget<\/strong>, kt\u00f3ra zosta\u0142a pokazana w ostatnim po\u015bcie.<\/p>\n<p>Po drugie,\u00a0 metoda <strong>aktualizacji<\/strong>, kt\u00f3ra jest cz\u0119\u015bci\u0105 API Widgets, b\u0119dzie wywo\u0142ywa\u0107 t\u0119 klas\u0119. Nie jest konieczne przekazywanie zmiennej <strong>$oldInstance<\/strong> do serializatora, ale jest to wymagane w przypadku metody aktualizacji.<\/p>\n<p>Oto klasa <strong>Widget<\/strong> <a href=\"https:\/\/gist.github.com\/tommcfarlin\/392a2eda9ebc0b0a59cd4b364e427445#file-03-widget-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">w obecnej formie<\/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>Ale je\u015bli od\u015bwie\u017cysz stron\u0119, mo\u017cesz zauwa\u017cy\u0107, \u017ce oczyszczanie i serializacja nie dzia\u0142aj\u0105 podczas pobierania danych. I tym zajmiemy si\u0119 w nast\u0119pnym po\u015bcie.<\/p>\n<h2>Pobieranie danych<\/h2>\n<p>Zauwa\u017c, \u017ce chocia\u017c funkcjonalno\u015b\u0107 wydaje si\u0119 niekompletna (poniewa\u017c nieoczyszczone dane s\u0105 nadal wy\u015bwietlane), skupiamy si\u0119 na upewnieniu si\u0119, \u017ce piszemy klasy ze sp\u00f3jno\u015bci\u0105, odpowiedzialno\u015bci\u0105 i nie s\u0105 \u015bci\u015ble powi\u0105zane.<\/p>\n<p>W nast\u0119pnym po\u015bcie zajmiemy si\u0119 tym nieco bardziej. Wi\u0119c przestudiuj powy\u017cszy kod, zaimplementuj go, je\u015bli to w\u0142a\u015bnie robi\u0142e\u015b, a od tego przejdziemy w nast\u0119pnym po\u015bcie.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A teraz zaczynamy dodawa\u0107 funkcje sanityzacji i serializacji do WordPress Widget Boilerplate.<\/p>\n","protected":false},"author":1,"featured_media":234962,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721,845],"tags":[1169],"class_list":["post-230771","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","category-samouczki","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230771","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/comments?post=230771"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230771\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/234962"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230771"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230771"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230771"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}