{"id":229378,"date":"2022-10-31T09:35:00","date_gmt":"2022-10-31T06:35:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=229378"},"modified":"2022-11-09T06:45:29","modified_gmt":"2022-11-09T03:45:29","slug":"mantendo-um-status-de-postagem-ao-atualizar-uma-postagem-do-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/mantendo-um-status-de-postagem-ao-atualizar-uma-postagem-do-wordpress\/","title":{"rendered":"Mantendo um status de postagem ao atualizar uma postagem do WordPress"},"content":{"rendered":"\n<p>Acabei de terminar um recurso para um projeto que usa uma combina\u00e7\u00e3o de tipos de postagem personalizados, importa\u00e7\u00f5es de dados e atualiza\u00e7\u00e3o de postagens existentes ao excluir um usu\u00e1rio (ou conjunto de usu\u00e1rios).<\/p>\n<p>H\u00e1 um problema, por\u00e9m:<\/p>\n<p>Digamos que voc\u00ea tenha uma postagem publicada no momento (ou seja, seu &#8216;post_status&#8217; est\u00e1 definido como &#8216;publicar&#8217;), mas, quando voc\u00ea atualiza a postagem via wp_update_post, seu atributo post_status \u00e9 definido como &#8216;futuro&#8217;.<\/p>\n<p>Em outras palavras, sempre que voc\u00ea atualiza programaticamente uma postagem, o status da postagem \u00e9 definido como &#8216;Agendado&#8217; (de acordo com a interface do usu\u00e1rio) e &#8216;futuro&#8217; (de acordo com a coluna do banco de dados).<\/p>\n<p>Ent\u00e3o o que d\u00e1?<\/p>\n<h2>Status da postagem ao atualizar<\/h2>\n<p>De um modo geral, n\u00e3o sou f\u00e3 de fazer algo funcionar, descobrir que funciona e passar para a pr\u00f3xima tarefa, a menos que entenda exatamente por que n\u00e3o funcionou [como esperado] em primeiro lugar.<\/p>\n<p>Isso n\u00e3o quer dizer que n\u00e3o haja momentos em que as restri\u00e7\u00f5es tenham causado isso (pelo menos durante o hor\u00e1rio de trabalho). Mas se \u00e9 meia-noite, eu conserto um bug e n\u00e3o tenho certeza se entendi por que aparentemente estava quebrado em primeiro lugar, \u00e9 melhor ficar acordado e descobrir, certo?<\/p>\n<p>\u00c9 como a vers\u00e3o do programador do <a href=\"https:\/\/en.wikipedia.org\/wiki\/Sunk_cost#Loss_aversion_and_the_sunk_cost_fallacy\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vi\u00e9s de custo afundado<\/a>.<\/p>\n<p>De qualquer forma, conforme descrito acima, aqui est\u00e1 a ess\u00eancia do problema:<\/p>\n<ol>\n<li>Um determinado post existe no WordPress.<\/li>\n<li>Quando um usu\u00e1rio \u00e9 exclu\u00eddo, o sistema verifica se determinado conte\u00fado existe em uma determinada postagem e, em caso afirmativo, o remove.<\/li>\n<li>A postagem \u00e9 ent\u00e3o atualizada usando uma fun\u00e7\u00e3o da API do WordPress.<\/li>\n<\/ol>\n<p>Tudo funciona muito bem, exceto que h\u00e1 um problema: sempre que a postagem \u00e9 atualizada programaticamente, ela marca o status da postagem como &#8216;futuro&#8217; no banco de dados, definindo o item de linha da postagem na\u00a0 visualiza\u00e7\u00e3o <strong>Todas as postagens<\/strong> como &quot;Agendado&quot;.<\/p>\n<h3>Duas solu\u00e7\u00f5es<\/h3>\n<p>Existem duas maneiras de corrigir esse problema:<\/p>\n<ol>\n<li>Execute uma consulta r\u00e1pida diretamente no banco de dados para corrigir o problema.<\/li>\n<li>Atualize os argumentos da postagem para usar o hor\u00e1rio adequado no GMT (falarei mais sobre isso em um momento).<\/li>\n<\/ol>\n<p>Se voc\u00ea optar pela primeira solu\u00e7\u00e3o, certifique-se de usar a fun\u00e7\u00e3o prepare e certifique-se de executar a consulta <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-00-direct-database-query-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">depois que a fun\u00e7\u00e3o de atualiza\u00e7\u00e3o for retornada<\/a>.<\/p>\n<pre><code>&lt;?php\n\n\/\/ First, update the post using the available WordPress API.\nwp_update_post( $post );\n\n\/**\n * If the post status attribute of the post that was just updated\n * maintains the 'publish' post setatus, then manually update the \n * database column.\n *\/\nif ('publish' === $post-&gt;post_status) {\n\n    global $wpdb;\n    $wpdb-&gt;query(\n        $wpdb-&gt;prepare(\n            \"\n            UPDATE $wpdb-&gt;posts\n            SET post_status = '%s'\n            WHERE ID = %d\n            \",\n            'publish',\n            $post-&gt;ID) );\n}\n<\/code><\/pre>\n<p>Se voc\u00ea optar pela segunda solu\u00e7\u00e3o, atualize explicitamente as propriedades do objeto post antes de pass\u00e1-lo <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-01-maintain-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">para a fun\u00e7\u00e3o de atualiza\u00e7\u00e3o<\/a>.<\/p>\n<pre><code>&lt;?php\n\n$event_post-&gt;post_date_gmt = gmdate( 'Y-m-d H:i:s', $event_post-&gt;post_date_gmt );\nwp_update_post( $event_post );\n<\/code><\/pre>\n<p>N\u00e3o sou de dizer que n\u00e3o h\u00e1 lugar para nenhuma dessas solu\u00e7\u00f5es ao trabalhar em um projeto, mas a pergunta permanece:<\/p>\n<p>Por que o WordPress est\u00e1 marcando uma postagem agendada para o futuro quando a postagem, antes de passar pelo procedimento de atualiza\u00e7\u00e3o, foi definida para publica\u00e7\u00e3o?<\/p>\n<p>E se voc\u00ea n\u00e3o estiver familiarizado com o restante dos argumentos que s\u00e3o passados \u200b\u200bao WordPress ao atualizar um post, levar\u00e1 algum tempo para rastre\u00e1-lo.<\/p>\n<h2>Entendendo o problema<\/h2>\n<p>Para evitar escrever uma consulta direta ao banco de dados, opto pela segunda solu\u00e7\u00e3o porque \u00e9 mais limpa (embora n\u00e3o a torne menos confusa).<\/p>\n<p>Para descobrir por que esse comportamento acontece, voc\u00ea pode perguntar a outro desenvolvedor ou depurar o c\u00f3digo. Dado que eu estava trabalhando nisso tarde da noite, optei pelo \u00faltimo.<\/p>\n<p>Executando o depurador e o c\u00f3digo de rastreamento atrav\u00e9s de post.php.<\/p>\n<p>N\u00e3o vou falar sobre todos os pontos de interrup\u00e7\u00e3o e rel\u00f3gios que defini, ent\u00e3o tentarei ser o mais conciso poss\u00edvel.<\/p>\n<p>Primeiro, quando o c\u00f3digo for executado pela fun\u00e7\u00e3o <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_update_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_update_post<\/a>, ele encontrar\u00e1 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-02-update-post-conditional-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">este bloco de c\u00f3digo<\/a> :<\/p>\n<pre><code>&lt;?php\n\nif ('attachment' !== $post_type) {\n    if ('publish' == $post_status) {\n        $now = gmdate('Y-m-d H:i:59');\n        if (mysql2date('U', $post_date_gmt, false) &gt; mysql2date('U', $now, false)) {\n            $post_status = 'future';\n        }\n    } elseif ('future' == $post_status) {\n        $now = gmdate('Y-m-d H:i:59');\n        if (mysql2date('U', $post_date_gmt, false) &lt;= mysql2date('U', $now, false)) {\n            $post_status = 'publish';\n        }\n    }\n}\n<\/code><\/pre>\n<p>Observe que dentro da condicional, n\u00e3o estamos trabalhando com um anexo e estamos trabalhando com um status de postagem de &#8216;publicar&#8217;. Ent\u00e3o, vamos acertar a primeira condicional dentro da condicional externa (um pouco confuso, n\u00e3o \u00e9?).<\/p>\n<p>Agora h\u00e1 uma vari\u00e1vel, $post_status, mantendo um valor de publica\u00e7\u00e3o, mas n\u00e3o \u00e9 atribu\u00edda a nenhuma propriedade espec\u00edfica da postagem atual. Se voc\u00ea continuar rastreando o c\u00f3digo, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-03-apply-filters-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">voc\u00ea encontrar\u00e1 a pr\u00f3xima linha<\/a> :<\/p>\n<pre><code>&lt;?php\n\n$post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr) ), $postarr );\n<\/code><\/pre>\n<p>Aqui, voc\u00ea ver\u00e1 que est\u00e1 trabalhando com um conjunto de chaves de matriz contidas na vari\u00e1vel $postarr. Esta vari\u00e1vel \u00e9 usada anteriormente no c\u00f3digo (veja <a href=\"https:\/\/core.trac.wordpress.org\/browser\/tags\/4.7\/src\/wp-includes\/post.php#L3137\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">aqui<\/a> no Trac). E se voc\u00ea olhar de perto, ver\u00e1 que primeiro verifica se a propriedade post_date_gmt est\u00e1 vazia ou se est\u00e1 tudo zerado.<\/p>\n<p>E como n\u00e3o \u00e9, ele usar\u00e1 o valor que especificamos na propriedade <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-04-post-date-gmt-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">quando inicialmente chamamos a fun\u00e7\u00e3o<\/a> :<\/p>\n<pre><code>&lt;?php\n\nif (empty( $postarr['post_date_gmt']) || '0000-00-00 00:00:00' == $postarr['post_date_gmt']) {\n        if (! in_array( $post_status, array( 'draft', 'pending', 'auto-draft') )) {\n            $post_date_gmt = get_gmt_from_date( $post_date );\n        } else {\n            $post_date_gmt = '0000-00-00 00:00:00';\n        }\n    } else {\n        $post_date_gmt = $postarr['post_date_gmt'];\n    }\n<\/code><\/pre>\n<p>Espere.<\/p>\n<p>Por que voltar para a fun\u00e7\u00e3o quando o c\u00f3digo j\u00e1 passou por isso? Essa \u00e9 a natureza da depura\u00e7\u00e3o. \u00c0s vezes voc\u00ea v\u00ea vari\u00e1veis \u200b\u200be n\u00e3o pensa nada sobre elas apenas para ver que s\u00e3o usadas, configuradas, manipuladas, combinadas ou qualquer outra coisa posteriormente no c\u00f3digo.<\/p>\n<p>Essa \u00e9 a realidade disso.<\/p>\n<p>Mas de qualquer forma, por causa disso, a propriedade manter\u00e1 o valor que fornecemos antes de chamar a fun\u00e7\u00e3o de atualiza\u00e7\u00e3o. Normalmente, este ser\u00e1 o mesmo valor de quando a fun\u00e7\u00e3o foi iniciada, mas pode haver momentos em que voc\u00ea queira, digamos, descartar uma postagem.<\/p>\n<p>E isso \u00e9 motivo para usar <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_delete_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_delete_post<\/a>. Mas tem suas ressalvas, especialmente em torno dos tipos de postagem personalizados.<\/p>\n<p>Isso fica em outro post, no entanto.<\/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>Manter um status de postagem ao atualizar uma postagem do WordPress pode ter resultados inesperados. \u00c9 por isso e como gerenci\u00e1-lo adequadamente.<\/p>\n","protected":false},"author":1,"featured_media":223663,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,722,806,846,867],"tags":[1170],"class_list":["post-229378","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","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\/229378","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=229378"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/229378\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/223663"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=229378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=229378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=229378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}