{"id":231220,"date":"2022-12-15T10:59:00","date_gmt":"2022-12-15T07:59:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231220"},"modified":"2022-12-17T15:01:50","modified_gmt":"2022-12-17T12:01:50","slug":"widgets-do-wordpress-refatoracao-parte-4","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/widgets-do-wordpress-refatoracao-parte-4\/","title":{"rendered":"Widgets do WordPress: Refatora\u00e7\u00e3o, Parte 4"},"content":{"rendered":"\n<p>Implementamos uma quantidade significativa de mudan\u00e7as no WordPress Widget Boilerplate. Se voc\u00ea n\u00e3o tem acompanhado, recomendo come\u00e7ar no in\u00edcio da s\u00e9rie e se atualizar.<\/p>\n<p>Se, no entanto, voc\u00ea estiver acompanhando e tamb\u00e9m estiver executando algumas das ferramentas de qualidade de c\u00f3digo que examinam o estado do projeto, notar\u00e1 alguns erros no console.<\/p>\n<p>Normalmente, este \u00e9 o ponto em que recomendo prestar aten\u00e7\u00e3o ao que ele compartilha e depois corrigir o que ele relata, mas ainda n\u00e3o chegamos l\u00e1.<\/p>\n<p>Por exemplo, alguns dos erros que nossas ferramentas est\u00e3o mostrando agora s\u00e3o baseados no fato de termos vari\u00e1veis \u200b\u200bn\u00e3o utilizadas. Claro, esse \u00e9 o caso, porque ainda n\u00e3o come\u00e7amos a construir um widget.<\/p>\n<p>Mas ainda existem algumas classes concretas que precisamos implementar.<\/p>\n<h2>The WordPress Widget Boilerplate: Refatora\u00e7\u00e3o, Parte 4<\/h2>\n<p>Um dos problemas que ainda existem no c\u00f3digo como est\u00e1 agora \u00e9 que o construtor do widget est\u00e1 registrando fun\u00e7\u00f5es e isso n\u00e3o \u00e9 uma coisa boa.<\/p>\n<p>O objetivo de um construtor \u00e9 definir os valores das propriedades da classe, n\u00e3o implementar nenhum tipo de l\u00f3gica. Isso ocorre por alguns motivos:<\/p>\n<ul>\n<li>cria forte acoplamento ou depend\u00eancias entre classes no projeto sempre que uma determinada classe \u00e9 instanciada,<\/li>\n<li>ele introduz a l\u00f3gica de neg\u00f3cios em uma fun\u00e7\u00e3o que n\u00e3o se destina a conter a referida funcionalidade,<\/li>\n<li>torna dif\u00edcil testar uma classe isoladamente.<\/li>\n<\/ul>\n<p>A maneira de lidar com isso \u00e9 dupla:<\/p>\n<ol>\n<li>adicione um Registro que possamos usar para registrar classes na aplica\u00e7\u00e3o (e pass\u00e1-las com o m\u00ednimo de depend\u00eancias poss\u00edvel que explicarei mais adiante),<\/li>\n<li>crie assinantes que possam manipular a l\u00f3gica de neg\u00f3cios em uma base espec\u00edfica de gancho.<\/li>\n<\/ol>\n<p>Nos pr\u00f3ximos tr\u00eas posts:<\/p>\n<ol>\n<li>veremos como criar um Registro,<\/li>\n<li>como podemos introduzi-lo no arquivo bootstrap,<\/li>\n<li>e, em seguida, veja como criar assinantes para cada uma de nossas fun\u00e7\u00f5es (o que n\u00e3o deve ser muito dif\u00edcil, considerando o que fizemos no post anterior e o que estamos fazendo neste post).<\/li>\n<\/ol>\n<h3>Criar o registro<\/h3>\n<p>Antes de escrever o c\u00f3digo para o Registro, \u00e9 importante observar qual \u00e9 seu objetivo principal. Simplificando, a classe deve conter uma refer\u00eancia a qualquer classe que esteja registrada com ela.<\/p>\n<p>Isso \u00e9 feito passando uma refer\u00eancia a um determinado objeto para uma fun\u00e7\u00e3o e tamb\u00e9m ligando-o a uma chave para que possamos recuper\u00e1-lo facilmente mais tarde.<\/p>\n<h4>Considera\u00e7\u00f5es iniciais<\/h4>\n<p>Mas h\u00e1 algumas coisas a considerar. Por exemplo:<\/p>\n<p>se um objeto j\u00e1 existe no registro para uma determinada chave, precisamos lan\u00e7ar uma exce\u00e7\u00e3o &#8211; se um usu\u00e1rio tentar pegar um objeto do registro com uma determinada chave, ele deve lan\u00e7ar uma exce\u00e7\u00e3o<\/p>\n<p>Claro, n\u00e3o necessariamente tem que lan\u00e7ar exce\u00e7\u00f5es. Em vez disso, ele tamb\u00e9m pode exibir mensagens de erro, retornar valores nulos ou vazios ou o que voc\u00ea escolher.<\/p>\n<p>Em segundo lugar, o registro precisa ser capaz de retornar uma lista de todos os assinantes que est\u00e3o contidos nele para que possam ser registrados no WordPress (que \u00e9 o que veremos no pr\u00f3ximo post).<\/p>\n<p>Para fazer isso, por\u00e9m, precisamos ter certeza de que ele suporta todos os assinantes e \u00e9 a\u00ed que a no\u00e7\u00e3o do AbstractSubscriber do <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/widgets-do-wordpress-refatoracao-parte-3\/\" title=\"post anterior\">post anterior<\/a> entra em jogo. Isto \u00e9, desde que uma classe seja uma classe filha daquela classe, ent\u00e3o tudo bem.<\/p>\n<h4>Criando o Registro<\/h4>\n<p>Dito isso, vamos planejar o seguinte:<\/p>\n<ul>\n<li>Criaremos uma classe Registry e a colocaremos em um namespace Utilities (e, portanto, em um diret\u00f3rio) se ela ainda n\u00e3o existir em seu trabalho.<\/li>\n<li>Faremos com que o registro mantenha uma refer\u00eancia a todos os seus objetos em uma matriz associativa.<\/li>\n<li>Precisamos de m\u00e9todos para <strong>adicionar<\/strong> e <strong>obter<\/strong> um assinante individual e, em seguida, um para recuperar a lista de assinantes inteiros.<\/li>\n<\/ul>\n<p>O stub da classe ficar\u00e1 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-00-registry-stub-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">assim:<\/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>Em seguida, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-01-registry-constructor-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">podemos definir a propriedade b\u00e1sica<\/a>, um array, e inicializ\u00e1-lo no construtor:<\/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>Depois disso, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-02-registry-add-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">podemos criar o m\u00e9todo add<\/a>. Lembre-se que na minha implementa\u00e7\u00e3o, estou optando por lan\u00e7ar uma exce\u00e7\u00e3o se uma chave j\u00e1 estiver definida, mas voc\u00ea n\u00e3o precisa fazer isso.<\/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>Da mesma forma, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-03-registry-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">o m\u00e9todo get<\/a> retornar\u00e1 uma refer\u00eancia \u00e0 inst\u00e2ncia de um objeto identificado com essa chave. Se a chave n\u00e3o estiver definida, ela lan\u00e7ar\u00e1 uma exce\u00e7\u00e3o. Se estiver definido, mas n\u00e3o existir nenhum objeto, retornaremos 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>Finalmente, precisamos de um m\u00e9todo para retornar todos os assinantes registrados. Em um post futuro, o uso para isso ficar\u00e1 muito mais aparente, mas, por enquanto, observe que criaremos um array de qualquer classe que seja uma inst\u00e2ncia da classe <strong>AbstractSubscriber e<\/strong> <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-04-registry-get-subscribers-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">, em seguida, retornaremos o array filtrado.<\/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>Neste ponto, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-05-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">temos a classe<\/a> completa (completa com documenta\u00e7\u00e3o):<\/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>Agora precisamos adicion\u00e1-lo ao bootstrap do nosso plugin.<\/p>\n<h2>Antes do Bootstrap, embora<\/h2>\n<p>Como mencionado anteriormente no post, precisamos adicionar isso ao bootstrap do plugin. Para fazer isso, por\u00e9m, precisamos definir nosso pr\u00f3prio filtro para que possamos passar facilmente o registro pelo resto do plugin (quando chegar a hora de fazer isso).<\/p>\n<p>Antes de fazermos isso, por\u00e9m, \u00e9 importante ter certeza de que voc\u00ea tem um bom controle sobre o Registro que acabamos de criar, que ele se encaixa no plug-in e que voc\u00ea est\u00e1 rastreando com a ramifica\u00e7\u00e3o de <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">desenvolvimento<\/a> que temos at\u00e9 agora.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Um problema que ainda existe no c\u00f3digo como est\u00e1 agora \u00e9 que o construtor do widget WordPress est\u00e1 registrando fun\u00e7\u00f5es e isso n\u00e3o \u00e9 uma coisa boa.<\/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":[898,722,867],"tags":[1170],"class_list":["post-231220","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/231220","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=231220"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/231220\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/223984"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=231220"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=231220"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=231220"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}