{"id":232055,"date":"2023-01-06T12:03:00","date_gmt":"2023-01-06T09:03:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=232055"},"modified":"2023-01-06T12:33:24","modified_gmt":"2023-01-06T09:33:24","slug":"adicionar-link-personalizado-a-tela-de-todas-as-postagens-com-base-nos-metadados-da-postagem","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/adicionar-link-personalizado-a-tela-de-todas-as-postagens-com-base-nos-metadados-da-postagem\/","title":{"rendered":"Adicionar link personalizado \u00e0 tela de todas as postagens com base nos metadados da postagem"},"content":{"rendered":"\n<p><strong>TL;DR<\/strong>: Este artigo descreve o c\u00f3digo necess\u00e1rio para adicionar um link personalizado na tela <strong>Todas as postagens<\/strong> que usa uma parte personalizada de metadados de postagem.<\/p>\n<p><strong>Nota<\/strong>: Alguns meses atr\u00e1s, escrevi um artigo sobre <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/adicionar-uma-visualizacao-personalizada-a-tela-de-todas-as-postagens\/\" title=\"como adicionar uma visualiza\u00e7\u00e3o personalizada \u00e0 tela Todas as postagens\">como adicionar uma visualiza\u00e7\u00e3o personalizada \u00e0 tela Todas as postagens<\/a>. Este artigo n\u00e3o \u00e9 todos iguais, mas nem todos juntos s\u00e3o diferentes. Pense nisso como uma implementa\u00e7\u00e3o mais detalhada e talvez mais pr\u00e1tica do conceito.<\/p>\n<hr \/>\n<p>Suponha que voc\u00ea tenha um tipo de postagem padr\u00e3o ou um tipo de postagem personalizado e simplesmente filtre por um t\u00edtulo que voc\u00ea define usando um mecanismo que permite salvar dados na <code>post_metadata<\/code>tabela.<\/p>\n<p>Por exemplo, digamos que voc\u00ea tenha uma postagem e ela como um peda\u00e7o de metadados com:<\/p>\n<ul>\n<li>a <code>meta_key<\/code>com o valor de<code>article_attribute<\/code><\/li>\n<li>a <code>meta_value<\/code>com o valor de<code>headline<\/code><\/li>\n<\/ul>\n<p>E voc\u00ea deseja usar essas informa\u00e7\u00f5es para adicionar um novo link de <strong>manchetes<\/strong> que filtra automaticamente tudo, exceto artigos com esses metadados.<\/p>\n<p>Aqui est\u00e1 como faz\u00ea-lo.<\/p>\n<h2>Link personalizado na tela de todas as postagens<\/h2>\n<p>Antes de come\u00e7ar, vale a pena notar que existem duas maneiras de lidar com esse problema:<\/p>\n<ul>\n<li>Poder\u00edamos adicionar o link na parte superior da p\u00e1gina <strong>Todas as postagens<\/strong> primeiro e depois adicionar a funcionalidade para filtrar os dados em segundo lugar,<\/li>\n<li>Ou podemos fazer o contr\u00e1rio, onde adicionamos a l\u00f3gica de back-end primeiro e depois adicionamos o link da p\u00e1gina <strong>Todas as postagens .<\/strong><\/li>\n<\/ul>\n<p>Vou optar por come\u00e7ar com a segunda op\u00e7\u00e3o. N\u00e3o h\u00e1 nenhuma raz\u00e3o para que tenha que ser feito desta forma. \u00c9 minha prefer\u00eancia.<\/p>\n<hr \/>\n<p>Primeiro, preciso me conectar ao <code>[pre_get_posts](https:\/\/developer.wordpress.org\/reference\/hooks\/pre_get_posts\/)<\/code>gancho fornecido pelo WordPress. Eu n\u00e3o vou usar nenhuma classe com namespace ou fun\u00e7\u00f5es prefixadas neste exemplo (dado que eu cobri esse conte\u00fado o suficiente neste site), mas terei um plugin de demonstra\u00e7\u00e3o para este link na parte inferior do post.<\/p>\n<p>De qualquer forma, come\u00e7arei adicionando uma fun\u00e7\u00e3o an\u00f4nima anexada ao gancho mencionado acima:<\/p>\n<pre><code>add_action(\n  'pre_get_posts',\n  function (WP_Query $query) {\n\n  }\n);<\/code><\/pre>\n<p>Observe que a fun\u00e7\u00e3o an\u00f4nima aceita um \u00fanico argumento que \u00e9 uma refer\u00eancia \u00e0 inst\u00e2ncia atual <code>WP_Query<\/code>que est\u00e1 sendo executada na p\u00e1gina. Se voc\u00ea n\u00e3o estiver familiarizado com essa classe, recomendo ler qualquer um <a href=\"https:\/\/tommcfarlin.com\/?s=wp_query\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">desses artigos<\/a> ou a p\u00e1gina <a href=\"https:\/\/developer.wordpress.org\/reference\/classes\/wp_query\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">de recursos do desenvolvedor<\/a>.<\/p>\n<p>Na fun\u00e7\u00e3o, preciso verificar a presen\u00e7a de a <code>meta_value<\/code>na string de consulta. Isso \u00e9 f\u00e1cil de fazer gra\u00e7as \u00e0 <code>[filter_input](https:\/\/www.php.net\/manual\/en\/function.filter-input.php)<\/code>fun\u00e7\u00e3o fornecida pelo PHP.<\/p>\n<pre><code>add_action(\n  'pre_get_posts',\n  function (WP_Query $query) {\n    $meta_value = 'headline';\n\n    if (filter_input( INPUT_GET, 'meta_value') === $meta_value) {\n      $query-&gt;set( 'meta_key', 'article_attribute' );\n      $query-&gt;set( 'meta_value', $meta_value );\n    }\n  }\n);<\/code><\/pre>\n<p>Este gancho verificar\u00e1 se o <code>headline<\/code>valor \u00e9 chave para a <code>meta_value<\/code>chave na string de consulta. Em caso afirmativo, ele adiciona um <code>meta_key<\/code>e <code>meta_value<\/code>\u00e0 inst\u00e2ncia do <code>WP_Query<\/code>qual instruir\u00e1 o WordPress a recuperar todas as postagens apenas com esses metadados.<\/p>\n<hr \/>\n<p>Depois disso, preciso adicionar um link no topo da p\u00e1gina <strong>Todas as postagens<\/strong> para acionar essa funcionalidade. Para fazer isso, vou aproveitar o <code>[views_edit-posts](https:\/\/tommcfarlin.com\/add-a-custom-view\/)<\/code>gancho. Esta fun\u00e7\u00e3o aceitar\u00e1 uma matriz de \u00e2ncoras que ser\u00e3o exibidas na parte superior da p\u00e1gina.<\/p>\n<p>Eu me refiro a isso, <code>$views<\/code>ent\u00e3o \u00e9 isso que a fun\u00e7\u00e3o aceitar\u00e1 quando eu a apagar:<\/p>\n<pre><code>add_action(\n  'views_edit-post',\n  function (array $views) {\n\n    return $views;\n  }\n);<\/code><\/pre>\n<p>Observe que \u00e9 importante retornar o array de volta ao WordPress para que ele saiba o que renderizar, mesmo que nenhuma modifica\u00e7\u00e3o seja feita.<\/p>\n<p>Primeiro, preciso determinar se estou atualmente na p\u00e1gina personalizada. Nesse caso, preciso adicionar os atributos apropriados \u00e0 \u00e2ncora adicionada ao topo da p\u00e1gina:<\/p>\n<pre><code>\n$attributes = 'class=\"\"';\nif (filter_input(INPUT_GET, 'meta_value') === 'headline') {\n  $attributes ='class=\"current aria-current=\"page\"';\n}<\/code><\/pre>\n<p>Depois disso, preciso realmente adicionar a visualiza\u00e7\u00e3o <strong>Headlines<\/strong> \u00e0 p\u00e1gina. Isso exigir\u00e1 o uso de v\u00e1rias fun\u00e7\u00f5es:<\/p>\n<ul>\n<li><code>[array_push](https:\/\/www.php.net\/manual\/en\/function.array-push.php)<\/code>para adicionar um novo link \u00e0 lista de<code>$views<\/code><\/li>\n<li><code>[sprintf](https:\/\/www.php.net\/manual\/en\/function.sprintf.php)<\/code>para adicionar com seguran\u00e7a uma nova string<\/li>\n<li><code>[add_query_arg](https:\/\/developer.wordpress.org\/reference\/functions\/add_query_arg\/)<\/code>para adicionar um conjunto de argumentos de consulta personalizados \u00e0 p\u00e1gina atual.<\/li>\n<\/ul>\n<p>A pr\u00f3xima se\u00e7\u00e3o de c\u00f3digo ficar\u00e1 assim:<\/p>\n<pre><code>\narray_push(\n  $views,\n  sprintf(\n    '&lt;a href=\"%1$s\" %2$s&gt;%3$s \n      &lt;span class=\"count\"&gt;(%4$s)&lt;\/span&gt;\n     &lt;\/a&gt;\n    ',\n    add_query_arg([\n      'post_type'   =&gt; 'post',\n      'post_status' =&gt; 'all',\n      'meta_value'  =&gt; 'headline',\n    ], 'edit.php'),\n    $attributes\n    __('Headlines'),\n    count(  );\n);<\/code><\/pre>\n<p>Mas ainda n\u00e3o terminei. Observe especificamente que estou fazendo uma chamada para <code>[count](https:\/\/www.php.net\/manual\/en\/function.count.php)<\/code>no final da fun\u00e7\u00e3o. Isso \u00e9 para que eu possa exibir corretamente o n\u00famero de posts que possuem esse atributo.<\/p>\n<p>Vou escrever duas fun\u00e7\u00f5es auxiliares para isso e depois retornarei \u00e0 <code>sizeof<\/code>chamada.<\/p>\n<hr \/>\n<p>Aqui est\u00e1 uma fun\u00e7\u00e3o auxiliar para encontrar o n\u00famero de resultados que tem o especificado <code>meta_key<\/code>e <code>meta_value<\/code>que temos para este tipo de post. Observe que estou usando <code>[$wpdb](https:\/\/developer.wordpress.org\/reference\/classes\/wpdb\/)<\/code>para fazer uma chamada direta ao banco de dados e que estou usando especificamente <code>[prepare](https:\/\/developer.wordpress.org\/reference%2Fclasses%2Fwpdb%2Fprepare%2F\/)<\/code>para garantir que fa\u00e7o isso com seguran\u00e7a.<\/p>\n<pre><code>function get_headline_results(): array {\n  global $wpdb;\n  return $wpdb-&gt;get_results( \n    $wpdb-&gt;prepare(\n      \"\n      SELECT post_id FROM $wpdb-&gt;postmeta\n      WHERE meta_key = %s AND meta_value = %s\n      \",\n      'article_attribute',\n      'headline'\n    ),\n    ARRAY_A\n  );\n}<\/code><\/pre>\n<p>Observe que ele retorna todos os resultados (n\u00e3o apenas o n\u00famero) porque esse valor ser\u00e1 passado para outra fun\u00e7\u00e3o momentaneamente.<\/p>\n<p>Neste ponto, poder\u00edamos parar e simplesmente olhar para o conte\u00fado que \u00e9 retornado da consulta, mas se estivermos preocupados apenas com o <code>post<\/code>tipo de postagem, precisaremos considerar isso. Aqui est\u00e1 uma maneira de fazer isso:<\/p>\n<pre><code>function filter_posts_from_pages( array $results ): array {\n  $post_ids = array();\n\n  foreach ($results as $result) {\n    if ('post' === get_post_type( $result['post_type'])) {\n      $post_ids[] = $result['post_id'];\n    }\n  }\n\n  return $post_ids;\n}<\/code><\/pre>\n<p>Com isso, podemos retornar esse valor de volta para a <code>count<\/code>fun\u00e7\u00e3o acima.<\/p>\n<hr \/>\n<p>A vers\u00e3o final do bloco que iniciamos acima deve ser algo assim:<\/p>\n<pre><code>\narray_push(\n  $views,\n  sprintf(\n    '&lt;a href=\"%1$s\" %2$s&gt;%3$s &lt;span class=\"count\"&gt;(%4$s)&lt;\/span&gt;&lt;\/a&gt;',\n    add_query_arg(\n      array(\n        'post_type'   =&gt; 'post',\n        'post_status' =&gt; 'all',\n        'meta_value'  =&gt; 'headlines', \n      ),\n      'edit.php'\n    ),\n    $attributes,\n    __( 'Headlines' ),\n    count(\n      filter_posts_from_pages( get_headline_results()) )) );<\/code><\/pre>\n<p>O que significa que a vers\u00e3o completa da fun\u00e7\u00e3o para adicionar um novo t\u00edtulo se parece com isso:<\/p>\n<pre><code>add_action(\n  'views_edit-post',\n  function (array $views) {\n\n    $attributes = 'class=\"\"';\n    if (filter_input( INPUT_GET, 'meta_value') === 'headline') {\n      $attributes = 'class=\"current aria-current=\"page\"';\n    }\n\n    array_push(\n      $views,\n      sprintf(\n        '&lt;a href=\"%1$s\" %2$s&gt;%3$s &lt;span class=\"count\"&gt;(%4$s)&lt;\/span&gt;&lt;\/a&gt;',\n        add_query_arg(\n          array(\n            'post_type'   =&gt; 'post',\n            'post_status' =&gt; 'all',\n            'meta_value'  =&gt; 'headline', \n          ),\n          'edit.php'\n        ),\n        $attributes,\n        __( 'Headlines' ),\n        count(\n          filter_posts_from_pages( get_headline_results()) )) );\n\n    return $views;\n  }\n);<\/code><\/pre>\n<p>E, como mencionado desde o in\u00edcio, este plugin n\u00e3o tem namespace ou est\u00e1 organizado de uma forma que eu normalmente escrevo c\u00f3digo. Em vez disso, pretende demonstrar uma forma de alcan\u00e7ar algo rapidamente \u2013 uma esp\u00e9cie de prot\u00f3tipo.<\/p>\n<p>Ent\u00e3o, se voc\u00ea estiver interessado em ver algo assim em a\u00e7\u00e3o, voc\u00ea pode conferir o reposit\u00f3rio no GitHub. Observe que \u00e9 o ramo de <strong><a href=\"https:\/\/github.com\/tommcfarlin\/custom-metadata-filter\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">desenvolvimento<\/a><\/strong> no momento. Lembre-se de ver o <code>[README](https:\/\/github.com\/tommcfarlin\/custom-metadata-filter\/blob\/develop\/README.md)<\/code>, pois ele fornecer\u00e1 instru\u00e7\u00f5es sobre como adicionar dados ao banco de dados para postagens para que a \u00e2ncora <strong>Headlines<\/strong> realmente funcione, em vez de mostrar incondicionalmente um valor zero.<\/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>Este artigo descreve o c\u00f3digo necess\u00e1rio para adicionar um link personalizado na tela Todas as postagens que usa uma parte personalizada de metadados de postagem.<\/p>\n","protected":false},"author":1,"featured_media":158583,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,722,837,920,806,846,867],"tags":[1170],"class_list":["post-232055","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-guia-para-iniciantes","category-outro","category-php-8","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/232055","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=232055"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/232055\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/158583"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=232055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=232055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=232055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}