{"id":230716,"date":"2022-12-18T19:40:00","date_gmt":"2022-12-18T16:40:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230716"},"modified":"2022-12-18T19:40:43","modified_gmt":"2022-12-18T16:40:43","slug":"widzety-wordpress-refaktoryzacja-czesc-7","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-7\/","title":{"rendered":"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 7"},"content":{"rendered":"\n<p>W ostatnich kilku postach wykonali\u015bmy du\u017co pracy, aby doprowadzi\u0107 kod do punktu refaktoryzacji, kt\u00f3ry zostanie om\u00f3wiony w tym artykule.<\/p>\n<p>W szczeg\u00f3lno\u015bci om\u00f3wili\u015bmy:<\/p>\n<ul>\n<li>haczyki,<\/li>\n<li><a href=\"https:\/\/tommcfarlin.com\/wordpress-widgets-part-4\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Rejestr<\/a>, _<\/li>\n<li>i <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-3\/\" title=\"abonenci\">abonenci<\/a>.<\/li>\n<\/ul>\n<p>Wszystko to odegra pewn\u0105 rol\u0119 w tym, co zrobimy dzisiaj.<\/p>\n<h2>WordPress Widget Boilerplate: Refaktoryzacja, cz\u0119\u015b\u0107 7<\/h2>\n<p>Ci, kt\u00f3rzy s\u0105 zaznajomieni z <a href=\"https:\/\/codex.wordpress.org\/Widgets_API\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">API WordPress Widgets<\/a>, prawdopodobnie wiedz\u0105, \u017ce nie zmieni\u0142 si\u0119 on zbytnio w ci\u0105gu ostatnich kilku lat.<\/p>\n<p>Co wi\u0119cej, tak naprawd\u0119 sk\u0142ada si\u0119 tylko z czterech funkcji (z kt\u00f3rych jedn\u0105 jest konstruktor):<\/p>\n<ol>\n<li>Konstruktor odpowiada za ustawienie kilku w\u0142a\u015bciwo\u015bci wid\u017cetu, najcz\u0119\u015bciej jego nazwy i opisu.<\/li>\n<li>Funkcja wid\u017cetu odpowiada za renderowanie zawarto\u015bci wid\u017cetu.<\/li>\n<li>Funkcja formularza odpowiada za wy\u015bwietlanie formularza w obszarze administracyjnym WordPressa podczas pracy z wid\u017cetem.<\/li>\n<li>Funkcja aktualizacji odpowiada za aktualizacj\u0119 opcji, kt\u00f3re s\u0105 zapisane w bazie danych (lub zainicjowane, a nast\u0119pnie zapisanie opcji, kt\u00f3re mog\u0105 jeszcze nie istnie\u0107 w bazie danych).<\/li>\n<\/ol>\n<p>Mi\u0142\u0105 rzecz\u0105 jest to, \u017ce to szczeg\u00f3lne podej\u015bcie jest osi\u0105gane poprzez dziedziczenie funkcjonalno\u015bci klasy <a href=\"https:\/\/developer.wordpress.org\/reference\/classes\/wp_widget\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">WP_Widget<\/a>.<\/p>\n<p>Problem polega jednak na tym, \u017ce jedna klasa to du\u017co pracy.<\/p>\n<p>Zamiast tego powinni\u015bmy rozdzieli\u0107 ka\u017cd\u0105 z funkcji na jej w\u0142asny obszar funkcjonalno\u015bci.<\/p>\n<p>Podobnie jak w przypadku wszystkiego w programowaniu, b\u0119d\u0105 sposoby, w kt\u00f3rych pewne rzeczy b\u0119d\u0105 jasne, jak mo\u017cna je wykona\u0107, a tak\u017ce b\u0119d\u0105 pewne rzeczy, kt\u00f3re mo\u017cna zrobi\u0107 na wiele sposob\u00f3w.<\/p>\n<p>Zaprezentuj\u0119, jak do tego podchodz\u0119 na razie. Mo\u017ce si\u0119 to zmieni\u0107 w przysz\u0142o\u015bci, a mo\u017ce nie, a inni mog\u0105 mie\u0107 na to inne podej\u015bcie.<\/p>\n<p>Niezale\u017cnie od tego implementacja b\u0119dzie znacznie bardziej zorientowana obiektowo i da ka\u017cdej klasie w\u0142asny zestaw obowi\u0105zk\u00f3w.<\/p>\n<p>Pierwsze pytanie brzmi jednak, jak podzieli\u0107 klas\u0119 z czterema funkcjami, kt\u00f3ra dziedziczy po klasie nadrz\u0119dnej?<\/p>\n<h3>Aktualizacja Bootstrapa<\/h3>\n<p>Po pierwsze, jest kilka rzeczy, kt\u00f3re musimy dostosowa\u0107 w programie startowym wtyczki. Mianowicie musimy wykona\u0107 nast\u0119puj\u0105ce czynno\u015bci:<\/p>\n<ol>\n<li>utworzy\u0107 instancj\u0119 Rejestru i udost\u0119pni\u0107 go poprzez projekt,<\/li>\n<li>zaktualizowa\u0107 klas\u0119 Plugin tak, aby akceptowa\u0142a rejestr i \u0142adowa\u0142a subskrybent\u00f3w,<\/li>\n<li>przejrzyj bootstrap<\/li>\n<\/ol>\n<p>Oto spojrzenie na wszystkie trzy z powy\u017cszych.<\/p>\n<h3>1 Utw\u00f3rz instancj\u0119 rejestru<\/h3>\n<p>Poniewa\u017c om\u00f3wili\u015bmy to ju\u017c wcze\u015bniej w serii, powinno by\u0107 jasne, jak to zrobi\u0107.<\/p>\n<p>Najpierw <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9c39ba3635c823f85447d0378c8976d2#file-00-instantiate-the-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">zobacz nast\u0119puj\u0105cy kod<\/a> :<\/p>\n<pre><code>&lt;?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});<\/code><\/pre>\n<p>Nast\u0119pnie zauwa\u017c, \u017ce tworzymy instancj\u0119 Rejestru (za chwil\u0119 porozmawiamy o jego przestrzeni nazw), a nast\u0119pnie pod\u0142\u0105czamy go do niestandardowego filtra, kt\u00f3ry umo\u017cliwia nam dost\u0119p do niego przez ca\u0142\u0105 wtyczk\u0119, kiedy tylko chcemy.<\/p>\n<h3>2 Zaktualizuj klas\u0119 wtyczki<\/h3>\n<p>Nast\u0119pnie musimy zaktualizowa\u0107 podstawow\u0105 klas\u0119 wtyczki (znajduj\u0105c\u0105 si\u0119 w\u00a0 katalogu <strong>src<\/strong> ), aby odwo\u0142ywa\u0142a si\u0119 do rejestru i \u0142adowa\u0142a <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9c39ba3635c823f85447d0378c8976d2#file-01-update-the-plugin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wszystkich zarejestrowanych subskrybent\u00f3w<\/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 WordPressWidgetBoilerplate;\n\nuse WordPressWidgetBoilerplateUtilitiesRegistry;\n\n\/**\n * The base class for this plugin. Maintains a copy of the registry and starts\n * all of the objects that should hook into WordPress.\n *\/\nclass Plugin\n{\n    \/**\n     * @var Registry a reference to the simple container used to maintain plugin objects\n     *\/\n    private $registry;\n\n    \/**\n     * @param Registry $registry a reference to the simple container used to maintain plugin objects\n     *\/\n    public function __construct(Registry $registry)\n    {\n        $this-&gt;registry = $registry;\n    }\n\n    \/**\n     * Iterates through each of the subscribers maintained in the registry and registers them\n     * to the proper WordPress hook.\n     *\/\n    public function start()\n    {\n        array_map(function ($subscriber) {\n            add_action($subscriber-&gt;getHook(), [$subscriber, 'load']);\n        }, $this-&gt;registry-&gt;getRegisteredSubscribers());\n    }\n}<\/code><\/pre>\n<p>Pami\u0119taj jednak, \u017ce tak naprawd\u0119 nie skonfigurowali\u015bmy jeszcze \u017cadnych subskrybent\u00f3w. Zacz\u0119li\u015bmy to wcze\u015bniej w serii i teraz nadszed\u0142 czas, aby do tego wr\u00f3ci\u0107, ale zrobimy to p\u00f3\u017aniej.<\/p>\n<p>Musimy jednak <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9c39ba3635c823f85447d0378c8976d2#file-03-new-registry-function-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">doda\u0107 funkcj\u0119<\/a> \u2013 nawet tymczasow\u0105 \u2013 aby\u015bmy mogli doda\u0107 klasy, kt\u00f3re nie s\u0105 jawnymi subskrybentami zdarze\u0144:<\/p>\n<pre><code>&lt;?php\n\/**\n * @return array all of the the objects that aren't subscribers registered with WordPress\n *\/\npublic function getRegisteredObjects()\n{\n    $objects = [];\n    foreach ($this-&gt;registry as $object) {\n        if (!$object instanceof AbstractSubscriber) {\n            $objects[] = $object;\n        }\n    }\n\n    return array_filter($objects);\n}<\/code><\/pre>\n<p>Zostanie to przerobione p\u00f3\u017aniej, poniewa\u017c p\u00f3\u017aniej b\u0119dziemy przekszta\u0142ca\u0107 podstawowe klasy w subskrybent\u00f3w.<\/p>\n<h3>3 Przejrzyj Bootstrap<\/h3>\n<p>Zanim przejdziemy dalej, my\u015bl\u0119, \u017ce wa\u017cne jest, aby przejrze\u0107 bootstrap. Chocia\u017c Tw\u00f3j nag\u0142\u00f3wek i dokumentacja mog\u0105 si\u0119 r\u00f3\u017cni\u0107, wa\u017cne jest, aby pami\u0119ta\u0107, \u017ce wykonujemy nast\u0119puj\u0105ce czynno\u015bci:<\/p>\n<ul>\n<li>nazwanie bootstrapu,<\/li>\n<li>uniemo\u017cliwienie dost\u0119pu do pliku,<\/li>\n<li>wywo\u0142anie autoloadera,<\/li>\n<li>za\u0142o\u017cenie rejestru,<\/li>\n<li>i uruchomienie wtyczki.<\/li>\n<\/ul>\n<p>Brzmi to du\u017co, ale <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9c39ba3635c823f85447d0378c8976d2#file-02-the-current-bootstrap-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">kod jest do\u015b\u0107 kr\u00f3tki<\/a> :<\/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;\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\/\/ Start the machine.\n(new Plugin($registry))-&gt;start();\n<\/code><\/pre>\n<p>W tym momencie jednak nadszed\u0142 czas, aby przyjrze\u0107 si\u0119, jak to jest podzieli\u0107 klas\u0119 potomn\u0105 ze standardowego <a href=\"https:\/\/codex.wordpress.org\/Widgets_API\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">interfejsu API wid\u017cet\u00f3w<\/a> na co\u015b, co pasuje do modelu kodu, z kt\u00f3rym pracujemy.<\/p>\n<h2>Dzielenie klasy dziecka<\/h2>\n<p>Ta cz\u0119\u015b\u0107 prawdopodobnie obejmie kilka post\u00f3w, poniewa\u017c jest troch\u0119 pracy do wykonania, ale zaczniemy od stworzenia w\u0142asnej klasy wid\u017cet\u00f3w, kt\u00f3ra b\u0119dzie dziedziczy\u0107 po podstawowej klasie wid\u017cet\u00f3w.<\/p>\n<p>Najpierw stw\u00f3rz\u00a0 katalog <strong>API<\/strong> w katalogu <strong>src<\/strong> i dodaj plik o nazwie <strong>Widget.php<\/strong>. Tutaj b\u0119d\u0105 znajdowa\u0107 si\u0119 podstawy wid\u017cetu. W nast\u0119pnym po\u015bcie zajmiemy si\u0119 administracyjnymi i publicznymi arkuszami styl\u00f3w oraz plikami JavaScript.<\/p>\n<p>W tym momencie podstawy pliku powinny <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9c39ba3635c823f85447d0378c8976d2#file-04-widget-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wygl\u0105da\u0107 tak<\/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 WordPressWidgetBoilerplateAPI;\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 mixed $widgetSlug\n     *\/\n    public function __construct($widgetSlug)\n    {\n        $this-&gt;widgetSlug = $widgetSlug;\n\n        \/\/ TODO: update description\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     * TODO: This is a temporary message to show that the Boilerplate has loaded.\n     *\/\n    public function load()\n    {\n        $html = '&lt;p style=\"text-align:center; background: #fff; padding: 1em; border: 1px dotted gray; margin: 2em 2em 2em 14em;\"&gt;';\n        $html .= 'The Widget Boilerplate is loaded.';\n        $html .= '&lt;\/p&gt;';\n        echo $html;\n    }\n}\n<\/code><\/pre>\n<p>Zauwa\u017c, \u017ce zajmuje jeden argument. U\u017cy\u0142em nazwy wid\u017cetu, ale mo\u017cesz u\u017cy\u0107 tego, co chcesz, o ile reprezentuje tw\u00f3j wid\u017cet.<\/p>\n<p>Ma to na celu pokazanie, \u017ce klasa jest poprawnie tworzona i \u0142adowana, gdy wtyczka jest aktywowana. Je\u015bli tego nie widzisz, oznacza to, \u017ce co\u015b jest nie tak (co za chwil\u0119 sprawdzimy).<\/p>\n<p>Nast\u0119pnie wa\u017cne jest, aby upewni\u0107 si\u0119, \u017ce ta klasa zosta\u0142a dodana do Rejestru. Dodaj wi\u0119c nast\u0119puj\u0105ce wiersze kodu <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9c39ba3635c823f85447d0378c8976d2#file-05-add-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">w bootstrapie:<\/a><\/p>\n<pre><code>&lt;?php\n\n\/\/ Add the Widget base class to the Registry.\n$registry-&gt;add('widget', new Widget('widget-name'));<\/code><\/pre>\n<p>A teraz, kiedy aktywujesz wtyczk\u0119, powiniene\u015b zobaczy\u0107:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-160983-61e7189c9c671.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-160983-61e7189c9c671.png\" alt=\"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 7\"><\/a><\/p>\n<p>Je\u015bli nie, sprawd\u017a kod w <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ga\u0142\u0119zi deweloperskiej<\/a>, aby upewni\u0107 si\u0119, \u017ce masz wszystko, co jest opisane w tym po\u015bcie.<\/p>\n<h2>Wdra\u017canie subskrybent\u00f3w<\/h2>\n<p>W nadchodz\u0105cych postach przyjrzymy si\u0119, jak mo\u017cemy zaimplementowa\u0107 subskrybent\u00f3w dla publicznej strony witryny (czyli tam, gdzie wy\u015bwietlana jest tre\u015b\u0107 wid\u017cetu). I zrobimy to samo dla obszaru administracyjnego witryny.<\/p>\n<p>Na koniec zwr\u00f3cimy uwag\u0119 na kod odpowiedzialny za zabezpieczenie i serializacj\u0119 danych (czytaj: aktualizacja naszego wid\u017cetu), a nast\u0119pnie zobaczymy, jak wygl\u0105da finalna wersja zaktualizowanego boilerplate&#8217;u.<\/p>\n<p>Jednak w tym po\u015bcie podstawow\u0105 strategi\u0105, kt\u00f3r\u0105 stosujemy, jest podzielenie klasy potomnej tak, aby nadal mog\u0142a by\u0107 u\u017cywana z innymi klasami przy u\u017cyciu interfejs\u00f3w i klas bazowych, kt\u00f3re s\u0105 ju\u017c zdefiniowane w kodzie bazowym.<\/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>Problem z WP_Widget polega na tym, \u017ce jedna klasa to du\u017co pracy. Wi\u0119c teraz zaczniemy refaktoryzacj\u0119.<\/p>\n","protected":false},"author":1,"featured_media":236064,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721],"tags":[1169],"class_list":["post-230716","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230716","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=230716"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230716\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/236064"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}