{"id":229290,"date":"2022-10-31T10:01:00","date_gmt":"2022-10-31T07:01:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=229290"},"modified":"2022-11-09T06:19:53","modified_gmt":"2022-11-09T03:19:53","slug":"maintenir-un-statut-de-publication-lors-de-la-mise-a-jour-dune-publication-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/maintenir-un-statut-de-publication-lors-de-la-mise-a-jour-dune-publication-wordpress\/","title":{"rendered":"Maintenir un statut de publication lors de la mise \u00e0 jour d&rsquo;une publication WordPress"},"content":{"rendered":"\n<p>Je viens de terminer une fonctionnalit\u00e9 pour un projet qui utilise une combinaison de types de publication personnalis\u00e9s, d&rsquo;importations de donn\u00e9es et de mise \u00e0 jour des publications existantes lors de la suppression d&rsquo;un utilisateur (ou d&rsquo;un ensemble d&rsquo;utilisateurs).<\/p>\n<p>Il y a cependant un probl\u00e8me :<\/p>\n<p>Disons que vous avez un message qui est actuellement publi\u00e9 (c&rsquo;est-\u00e0-dire que &lsquo;post_status&rsquo; est d\u00e9fini sur &lsquo;publish&rsquo;) mais, lorsque vous mettez \u00e0 jour le message via wp_update_post, son attribut post_status est d\u00e9fini sur &lsquo;future&rsquo;.<\/p>\n<p>En d&rsquo;autres termes, chaque fois que vous mettez \u00e0 jour une publication par programme, le statut de la publication est d\u00e9fini sur &quot;Planifi\u00e9&quot; (selon l&rsquo;interface utilisateur) et &quot;futur&quot; (selon la colonne de la base de donn\u00e9es).<\/p>\n<p>Alors qu&rsquo;est-ce qui donne ?<\/p>\n<h2>Statut de publication lors de la mise \u00e0 jour<\/h2>\n<p>D&rsquo;une mani\u00e8re g\u00e9n\u00e9rale, je ne suis pas fan de faire fonctionner quelque chose, de d\u00e9couvrir que c&rsquo;est le cas et de passer \u00e0 la t\u00e2che suivante \u00e0 moins que je ne comprenne exactement pourquoi cela n&rsquo;a pas fonctionn\u00e9 [comme pr\u00e9vu] en premier lieu.<\/p>\n<p>Cela ne veut pas dire qu&rsquo;il n&rsquo;y a pas de moments o\u00f9 des contraintes ont provoqu\u00e9 cela (au moins pendant les heures de travail). Mais s&rsquo;il est minuit, je corrige un bug, et je ne suis pas tout \u00e0 fait s\u00fbr de comprendre pourquoi il a apparemment \u00e9t\u00e9 cass\u00e9 en premier lieu, autant rester \u00e9veill\u00e9 et comprendre, n&rsquo;est-ce pas\u00a0?<\/p>\n<p>C&rsquo;est comme la version du programmeur du <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\">biais de co\u00fbt irr\u00e9cup\u00e9rable<\/a>.<\/p>\n<p>Quoi qu&rsquo;il en soit, comme indiqu\u00e9 ci-dessus, voici l&rsquo;essentiel du probl\u00e8me:<\/p>\n<ol>\n<li>Un article donn\u00e9 existe dans WordPress.<\/li>\n<li>Lorsqu&rsquo;un utilisateur est supprim\u00e9, le syst\u00e8me v\u00e9rifie si un certain contenu existe dans une publication donn\u00e9e et, si c&rsquo;est le cas, le supprime.<\/li>\n<li>La publication est ensuite mise \u00e0 jour \u00e0 l&rsquo;aide d&rsquo;une fonction API WordPress.<\/li>\n<\/ol>\n<p>Tout fonctionne tr\u00e8s bien sauf qu&rsquo;il y a un probl\u00e8me\u00a0: chaque fois que la publication est mise \u00e0 jour par programme, elle marque le statut de la publication comme &quot;futur&quot; dans la base de donn\u00e9es, d\u00e9finissant finalement l&rsquo;\u00e9l\u00e9ment de campagne de la publication dans la\u00a0 vue <strong>Toutes<\/strong> les publications comme &quot;Planifi\u00e9&quot;.<\/p>\n<h3>Deux solutions<\/h3>\n<p>Il existe deux fa\u00e7ons de r\u00e9soudre ce probl\u00e8me\u00a0:<\/p>\n<ol>\n<li>Ex\u00e9cutez une requ\u00eate rapide directement sur la base de donn\u00e9es pour r\u00e9soudre le probl\u00e8me.<\/li>\n<li>Mettez \u00e0 jour les arguments de la publication pour utiliser l&rsquo;heure appropri\u00e9e en GMT (je couvrirai cela plus en d\u00e9tail dans un instant).<\/li>\n<\/ol>\n<p>Si vous optez pour la premi\u00e8re solution, assurez-vous d&rsquo;utiliser la fonction prepare et assurez-vous d&rsquo;ex\u00e9cuter la requ\u00eate <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-00-direct-database-query-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">apr\u00e8s le retour de la fonction update<\/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>Si vous optez pour la seconde solution, mettez alors explicitement \u00e0 jour les propri\u00e9t\u00e9s de l&rsquo;objet post avant de le passer <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-01-maintain-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u00e0 la fonction update<\/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>Je ne suis pas du genre \u00e0 dire qu&rsquo;il n&rsquo;y a pas de place pour l&rsquo;une ou l&rsquo;autre de ces solutions lorsque vous travaillez sur un projet, mais la question demeure\u00a0:<\/p>\n<p>Pourquoi WordPress marque-t-il une publication pr\u00e9vue pour le futur alors que la publication, avant de passer par la proc\u00e9dure de mise \u00e0 jour, \u00e9tait configur\u00e9e pour \u00eatre publi\u00e9e ?<\/p>\n<p>Et si vous n&rsquo;\u00eates pas familier avec le reste des arguments qui sont transmis \u00e0 WordPress lors de la mise \u00e0 jour d&rsquo;un article, il faudra un certain temps pour le retrouver.<\/p>\n<h2>Comprendre le probl\u00e8me<\/h2>\n<p>Afin d&rsquo;\u00e9viter d&rsquo;\u00e9crire une requ\u00eate directe \u00e0 la base de donn\u00e9es, j&rsquo;opte pour la deuxi\u00e8me solution car elle est plus propre (bien que cela ne la rende pas moins d\u00e9routante).<\/p>\n<p>Pour comprendre pourquoi ce comportement se produit, vous pouvez demander \u00e0 un autre d\u00e9veloppeur ou d\u00e9boguer le code. \u00c9tant donn\u00e9 que je travaillais dessus tard dans la nuit, j&rsquo;ai opt\u00e9 pour ce dernier.<\/p>\n<p>Ex\u00e9cution du d\u00e9bogueur et du code de tra\u00e7age via post.php.<\/p>\n<p>Je ne vais pas parler de tous les points d&rsquo;arr\u00eat et de toutes les montres que j&rsquo;ai d\u00e9finis, je vais donc essayer de le rendre aussi concis que possible.<\/p>\n<p>Tout d&rsquo;abord, lorsque le code passe par la fonction <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_update_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_update_post<\/a>, il rencontre <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-02-update-post-conditional-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ce bloc de code<\/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>Notez que dans le conditionnel, nous ne travaillons pas avec une pi\u00e8ce jointe et nous travaillons avec un statut de publication de &quot;publier&quot;. Nous allons donc frapper le premier conditionnel dans le conditionnel externe (un peu d\u00e9routant, n&rsquo;est-ce pas\u00a0?).<\/p>\n<p>Maintenant, il y a une variable, $ post_status, conservant une valeur de publication mais elle n&rsquo;est affect\u00e9e \u00e0 aucune propri\u00e9t\u00e9 particuli\u00e8re du message actuel. Si vous continuez \u00e0 tracer le code, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-03-apply-filters-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vous tomberez sur la ligne suivante<\/a>\u00a0:<\/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>Ici, vous verrez qu&rsquo;il fonctionne avec un ensemble de cl\u00e9s de tableau contenues dans la variable $postarr. Cette variable est utilis\u00e9e plus t\u00f4t dans le code (voir <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\">ici<\/a> sur Trac). Et si vous regardez attentivement, vous verrez qu&rsquo;il v\u00e9rifie d&rsquo;abord si la propri\u00e9t\u00e9 post_date_gmt est vide ou si tout est mis \u00e0 z\u00e9ro.<\/p>\n<p>Et puisque ce n&rsquo;est pas le cas, il utilisera la valeur que nous avons sp\u00e9cifi\u00e9e sur la propri\u00e9t\u00e9 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-04-post-date-gmt-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">lorsque nous avons initialement appel\u00e9 la fonction<\/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>Attendre.<\/p>\n<p>Pourquoi remonter dans la fonction alors que le code a d\u00e9j\u00e0 d\u00e9pass\u00e9 cela? C&rsquo;est la nature du d\u00e9bogage. Parfois, vous voyez des variables et ne pensez \u00e0 rien d&rsquo;elles uniquement pour voir qu&rsquo;elles sont utilis\u00e9es, d\u00e9finies, manipul\u00e9es, combin\u00e9es ou quoi que ce soit d&rsquo;autre plus tard dans le code.<\/p>\n<p>C&rsquo;est la r\u00e9alit\u00e9.<\/p>\n<p>Mais de toute fa\u00e7on, \u00e0 cause de cela, la propri\u00e9t\u00e9 conservera la valeur que nous avons fournie avant d&rsquo;appeler la fonction de mise \u00e0 jour. Habituellement, ce sera la m\u00eame valeur que lorsque la fonction a d\u00e9marr\u00e9, mais il peut arriver que vous souhaitiez, par exemple, supprimer un message.<\/p>\n<p>Et c&rsquo;est une raison pour utiliser <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_delete_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_delete_post<\/a>. Mais il a ses mises en garde, en particulier autour des types de publication personnalis\u00e9s.<\/p>\n<p>Cela entre dans un autre poste, cependant.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Le maintien d&rsquo;un statut de publication lors de la mise \u00e0 jour d&rsquo;une publication WordPress peut avoir des r\u00e9sultats inattendus. C&rsquo;est pourquoi et comment bien le g\u00e9rer.<\/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":[893,717,801,841,862],"tags":[1167],"class_list":["post-229290","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-code-2","category-developpeur","category-php-3","category-tutoriels","category-wordpress-3","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/229290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=229290"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/229290\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/223663"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=229290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=229290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=229290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}