{"id":230589,"date":"2022-12-15T11:23:00","date_gmt":"2022-12-15T08:23:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230589"},"modified":"2022-12-17T14:59:46","modified_gmt":"2022-12-17T11:59:46","slug":"widzety-wordpress-refaktoryzacja-czesc-4","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-4\/","title":{"rendered":"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 4"},"content":{"rendered":"\n<p>Wprowadzili\u015bmy znaczn\u0105 ilo\u015b\u0107 zmian w WordPress Widget Boilerplate. Je\u015bli nie nad\u0105\u017casz, polecam zacz\u0105\u0107 od pocz\u0105tku serii i nadrobi\u0107 zaleg\u0142o\u015bci.<\/p>\n<p>Je\u015bli jednak \u015bledzisz ten temat i korzystasz r\u00f3wnie\u017c z niekt\u00f3rych narz\u0119dzi jako\u015bci kodu, kt\u00f3re badaj\u0105 stan projektu, zauwa\u017cysz gar\u015b\u0107 b\u0142\u0119d\u00f3w w konsoli.<\/p>\n<p>Zwykle jest to punkt, w kt\u00f3rym zalecam zwr\u00f3cenie uwagi na to, co udost\u0119pnia, a nast\u0119pnie naprawienie tego, co zg\u0142asza, ale jeszcze do tego nie doszli\u015bmy.<\/p>\n<p>Na przyk\u0142ad niekt\u00f3re b\u0142\u0119dy, kt\u00f3re obecnie wy\u015bwietlaj\u0105 nasze narz\u0119dzia, wynikaj\u0105 z faktu, \u017ce mamy nieu\u017cywane zmienne. Oczywi\u015bcie tak jest, poniewa\u017c nie zacz\u0119li\u015bmy budowa\u0107 wid\u017cetu.<\/p>\n<p>Ale jest jeszcze kilka konkretnych klas, kt\u00f3re musimy zaimplementowa\u0107.<\/p>\n<h2>Szablon WordPress Widget Boilerplate: Refaktoryzacja, cz\u0119\u015b\u0107 4<\/h2>\n<p>Jednym z problem\u00f3w, kt\u00f3re wci\u0105\u017c istniej\u0105 w kodzie w obecnej postaci, jest to, \u017ce konstruktor wid\u017cetu rejestruje funkcje, a to nie jest dobre.<\/p>\n<p>Zadaniem konstruktora jest ustawienie warto\u015bci w\u0142a\u015bciwo\u015bci klasy, a nie implementacja jakiejkolwiek logiki. Dzieje si\u0119 tak z kilku powod\u00f3w:<\/p>\n<ul>\n<li>tworzy silne sprz\u0119\u017cenie lub zale\u017cno\u015bci mi\u0119dzy klasami w projekcie, gdy dana klasa jest instancja,<\/li>\n<li>wprowadza logik\u0119 biznesow\u0105 do funkcji, kt\u00f3ra nie ma zawiera\u0107 tej funkcjonalno\u015bci,<\/li>\n<li>utrudnia to testowanie klasy w izolacji.<\/li>\n<\/ul>\n<p>Spos\u00f3b radzenia sobie z tym jest dwojaki:<\/p>\n<ol>\n<li>doda\u0107 Rejestr, za pomoc\u0105 kt\u00f3rego b\u0119dziemy mogli rejestrowa\u0107 klasy w aplikacji (i przekazywa\u0107 je z jak najmniejsz\u0105 liczb\u0105 zale\u017cno\u015bci, co wyja\u015bni\u0119 p\u00f3\u017aniej),<\/li>\n<li>tworzy\u0107 subskrybent\u00f3w, kt\u00f3rzy mog\u0105 obs\u0142ugiwa\u0107 logik\u0119 biznesow\u0105 na podstawie konkretnego haka.<\/li>\n<\/ol>\n<p>W kolejnych trzech postach:<\/p>\n<ol>\n<li>przyjrzymy si\u0119 tworzeniu rejestru,<\/li>\n<li>jak mo\u017cemy wprowadzi\u0107 to do pliku bootstrap,<\/li>\n<li>a nast\u0119pnie sp\u00f3jrz na tworzenie subskrybent\u00f3w dla ka\u017cdej z naszych funkcji (co nie powinno by\u0107 zbyt trudne, bior\u0105c pod uwag\u0119 to, co zrobili\u015bmy w poprzednim po\u015bcie i co robimy w tym po\u015bcie).<\/li>\n<\/ol>\n<h3>Utw\u00f3rz rejestr<\/h3>\n<p>Przed napisaniem kodu dla Rejestru wa\u017cne jest, aby zwr\u00f3ci\u0107 uwag\u0119, jaki jest jego g\u0142\u00f3wny cel. M\u00f3wi\u0105c najpro\u015bciej, klasa ma zawiera\u0107 odniesienie do dowolnej klasy, kt\u00f3ra jest, hm, zarejestrowana w niej.<\/p>\n<p>Odbywa si\u0119 to poprzez przekazanie referencji do danego obiektu do funkcji, a tak\u017ce powi\u0105zanie go z kluczem, dzi\u0119ki czemu mo\u017cemy go p\u00f3\u017aniej \u0142atwo pobra\u0107.<\/p>\n<h4>Rozwa\u017cania wst\u0119pne<\/h4>\n<p>Ale jest kilka rzeczy do rozwa\u017cenia. Na przyk\u0142ad:<\/p>\n<p>je\u015bli obiekt ju\u017c istnieje w rejestrze dla danego klucza, to musimy zg\u0142osi\u0107 wyj\u0105tek \u2013 je\u015bli u\u017cytkownik pr\u00f3buje pobra\u0107 obiekt z rejestru z danym kluczem, powinien zg\u0142osi\u0107 wyj\u0105tek<\/p>\n<p>Oczywi\u015bcie nie musi koniecznie rzuca\u0107 wyj\u0105tk\u00f3w. Zamiast tego mo\u017ce r\u00f3wnie\u017c wy\u015bwietla\u0107 komunikaty o b\u0142\u0119dach, zwraca\u0107 warto\u015bci null lub puste lub cokolwiek wybierzesz.<\/p>\n<p>Po drugie, rejestr musi by\u0107 w stanie zwr\u00f3ci\u0107 list\u0119 wszystkich zawartych w nim subskrybent\u00f3w, aby mo\u017cna by\u0142o ich zarejestrowa\u0107 w WordPressie (o czym przekonamy si\u0119 w nast\u0119pnym po\u015bcie).<\/p>\n<p>Aby to zrobi\u0107, musimy jednak upewni\u0107 si\u0119, \u017ce obs\u0142uguje wszystkich subskrybent\u00f3w i tutaj w gr\u0119 wchodzi poj\u0119cie AbstractSubscriber z <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-3\/\" title=\"poprzedniego postu .\">poprzedniego postu .<\/a> Oznacza to, \u017ce dop\u00f3ki klasa jest klas\u0105 potomn\u0105 tej klasy, wszystko jest w porz\u0105dku.<\/p>\n<h4>Tworzenie rejestru<\/h4>\n<p>Powiedziawszy to, zaplanujmy nast\u0119puj\u0105ce rzeczy:<\/p>\n<ul>\n<li>Stworzymy klas\u0119 Registry i umie\u015bcimy j\u0105 w przestrzeni nazw Utilities (a tym samym w katalogu), je\u015bli jeszcze nie istnieje w Twojej pracy.<\/li>\n<li>Rejestr b\u0119dzie utrzymywa\u0142 odniesienie do wszystkich swoich obiekt\u00f3w w tablicy asocjacyjnej.<\/li>\n<li>Potrzebujemy metod <strong>dodawania<\/strong> i <strong>pozyskiwania<\/strong> pojedynczego subskrybenta, a nast\u0119pnie jednej do pobrania listy ca\u0142ych subskrybent\u00f3w.<\/li>\n<\/ul>\n<p>Kod klasy b\u0119dzie wygl\u0105da\u0142 mniej wi\u0119cej <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-00-registry-stub-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tak:<\/a><\/p>\n<pre><code>&lt;?php\n\nclass Registry extends AbstractSubscriber\n{\n    public function __construct()\n    {\n    }\n\n    public function add($id, $obj)\n    {\n    }\n\n    public function get($id)\n    {\n    }\n\n    public function getRegisteredSubscribers()\n    {\n    }\n}\n<\/code><\/pre>\n<p>Nast\u0119pnie <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-01-registry-constructor-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">mo\u017cemy zdefiniowa\u0107 podstawow\u0105 w\u0142a\u015bciwo\u015b\u0107<\/a>, tablic\u0119 i zainicjalizowa\u0107 j\u0105 w konstruktorze:<\/p>\n<pre><code>&lt;?php\n\nclass Registry\n{\n    private $registry;\n\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/\/ ...\n\n}<\/code><\/pre>\n<p>Nast\u0119pnie <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-02-registry-add-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">mo\u017cemy stworzy\u0107 metod\u0119 add<\/a>. Pami\u0119taj, \u017ce w mojej implementacji decyduj\u0119 si\u0119 na zg\u0142oszenie wyj\u0105tku, je\u015bli klucz jest ju\u017c zdefiniowany, ale nie musisz tego robi\u0107.<\/p>\n<pre><code>&lt;?php\n\npublic function add($id, $obj)\n{\n    if (isset($this-&gt;registry[$id])) {\n        throw new Exception('An object already exists for this given key.');\n    }\n    $this-&gt;registry[$id] = $obj;\n}<\/code><\/pre>\n<p>Podobnie <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-03-registry-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">metoda get<\/a> zwr\u00f3ci odwo\u0142anie do instancji obiektu zidentyfikowanego za pomoc\u0105 tego klucza. Je\u015bli klucz nie zostanie ustawiony, zg\u0142osi wyj\u0105tek. Je\u015bli jest ustawiony, ale nie istnieje \u017caden obiekt, zwr\u00f3cimy null.<\/p>\n<pre><code>&lt;?php\n\npublic function get($id)\n{\n    if (!isset($this-&gt;registry[$id])) {\n        throw new Exception('No object exists for the specified key.');\n    }\n\n    return $this-&gt;registry[$id] ?? null;\n}<\/code><\/pre>\n<p>Na koniec potrzebujemy metody, aby zwr\u00f3ci\u0107 wszystkich zarejestrowanych subskrybent\u00f3w. W przysz\u0142ym po\u015bcie u\u017cycie tego stanie si\u0119 znacznie bardziej widoczne, ale na razie zauwa\u017c, \u017ce utworzymy tablic\u0119 dowolnej klasy, kt\u00f3ra jest instancj\u0105 klasy <strong>AbstractSubscriber, a<\/strong> <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-04-registry-get-subscribers-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">nast\u0119pnie zwr\u00f3cimy przefiltrowan\u0105 tablic\u0119.<\/a><\/p>\n<pre><code>&lt;?php\n\npublic function getRegisteredSubscribers()\n{\n    $subscribers = [];\n    foreach ($this-&gt;registry as $object) {\n        if ($object instanceof AbstractSubscriber) {\n            $subscribers[] = $object;\n        }\n    }\n\n    return array_filter($subscribers);\n}<\/code><\/pre>\n<p>W tym momencie <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-05-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">mamy pe\u0142n\u0105 klas\u0119<\/a> (wraz z dokumentacj\u0105):<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of the WordPress Widget Boilerplate\n *\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 WordPressWidgetBoilerplateUtilities;\n\nuse Exception;\nuse WordPressWidgetBoilerplateSubscriberAbstractSubscriber;\n\n\/**\n * This class services as a simple container that can be used to pass objects\n * around the plugin.\n *\n * To use this class you'd make a call to the registry by saying Registry-&gt;get(),\n * then making a class to `register()` and `retrieve()` on an instance of the object.\n *\/\nclass Registry\n{\n    \/**\n     * @var array an array used to maintain the objects registered with the plugin\n     *\/\n    private $registry;\n\n    \/**\n     * Initializes the class by setting up the registry.\n     *\/\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/**\n     * Registers an object with the registry with the specified ID; however, will throw an\n     * exception if the ID is already referencing an object.\n     *\n     * @param string $id  an ID by which the specified object will be referenced\n     * @param mixed  $obj an instance of an object to store in the registry\n     *\n     * @throws Exception if an object already exists for the specified key\n     *\/\n    public function add($id, $obj)\n    {\n        if (isset($this-&gt;registry[$id])) {\n            throw new Exception('An object already exists for this given key.');\n        }\n        $this-&gt;registry[$id] = $obj;\n    }\n\n    \/**\n     * @param string $id the ID for the object that we wish to retrieve\n     *\n     * @throws Exception if no object exists for the specified key\n     *\n     * @return mixed a reference to the object or null\n     *\/\n    public function get($id)\n    {\n        if (!isset($this-&gt;registry[$id])) {\n            throw new Exception('No object exists for the specified key.');\n        }\n\n        return $this-&gt;registry[$id] ?? null;\n    }\n\n    \/**\n     * @return array all of the the Subscribers that should be registered with WordPress\n     *\/\n    public function getRegisteredSubscribers()\n    {\n        $subscribers = [];\n        foreach ($this-&gt;registry as $object) {\n            if ($object instanceof AbstractSubscriber) {\n                $subscribers[] = $object;\n            }\n        }\n\n        return array_filter($subscribers);\n    }\n}\n<\/code><\/pre>\n<p>Teraz musimy doda\u0107 go do programu startowego naszej wtyczki.<\/p>\n<h2>Chocia\u017c przed Bootstrapem<\/h2>\n<p>Jak wspomniano wcze\u015bniej w po\u015bcie, musimy doda\u0107 to do \u0142adowania pocz\u0105tkowego wtyczki. Aby to zrobi\u0107, musimy jednak zdefiniowa\u0107 w\u0142asny filtr, dzi\u0119ki czemu b\u0119dziemy mogli \u0142atwo omin\u0105\u0107 rejestr z reszt\u0105 wtyczki (gdy nadejdzie na to czas).<\/p>\n<p>Jednak zanim to zrobimy, wa\u017cne jest, aby upewni\u0107 si\u0119, \u017ce dobrze radzisz sobie z utworzonym w\u0142a\u015bnie Rejestrem, \u017ce pasuje on do wtyczki i \u017ce \u015bledzisz za pomoc\u0105 <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ga\u0142\u0119zi<\/a> deweloperskiej, kt\u00f3r\u0105 mamy do tej pory.<\/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>Jednym z problem\u00f3w, kt\u00f3ry wci\u0105\u017c istnieje w kodzie w obecnej postaci, jest to, \u017ce konstruktor widgetu WordPress rejestruje funkcje, a to nie jest dobre.<\/p>\n","protected":false},"author":1,"featured_media":223984,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721,897,866],"tags":[1169],"class_list":["post-230589","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","category-kod","category-wordpress-7","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230589","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=230589"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230589\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/223984"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230589"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230589"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230589"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}