{"id":228964,"date":"2022-10-31T10:25:00","date_gmt":"2022-10-31T07:25:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228964"},"modified":"2022-11-09T04:59:21","modified_gmt":"2022-11-09T01:59:21","slug":"mantener-el-estado-de-una-publicacion-al-actualizar-una-publicacion-de-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/mantener-el-estado-de-una-publicacion-al-actualizar-una-publicacion-de-wordpress\/","title":{"rendered":"Mantener el estado de una publicaci\u00f3n al actualizar una publicaci\u00f3n de WordPress"},"content":{"rendered":"\n<p>Acabo de terminar una funci\u00f3n para un proyecto que utiliza una combinaci\u00f3n de tipos de publicaciones personalizadas, importaciones de datos y actualizaci\u00f3n de publicaciones existentes al eliminar un usuario (o un conjunto de usuarios).<\/p>\n<p>Sin embargo, hay un problema:<\/p>\n<p>Digamos que tiene una publicaci\u00f3n que est\u00e1 publicada actualmente (es decir, su &#8216;post_status&#8217; est\u00e1 configurado en &#8216;publicar&#8217;) pero, cuando actualiza la publicaci\u00f3n a trav\u00e9s de wp_update_post, su atributo post_status est\u00e1 configurado en &#8216;futuro&#8217;.<\/p>\n<p>En otras palabras, cada vez que actualiza una publicaci\u00f3n mediante programaci\u00f3n, el estado de la publicaci\u00f3n se establece en &#8216;Programada&#8217; (seg\u00fan la interfaz de usuario) y &#8216;futuro&#8217; (seg\u00fan la columna de la base de datos).<\/p>\n<p>Entonces, \u00bfqu\u00e9 da?<\/p>\n<h2>Publicar estado al actualizar<\/h2>\n<p>En t\u00e9rminos generales, no soy fan\u00e1tico de hacer que algo funcione, descubrir que funciona y pasar a la siguiente tarea a menos que comprenda exactamente por qu\u00e9 no funcion\u00f3 [como se esperaba] en primer lugar.<\/p>\n<p>Esto no quiere decir que no haya momentos en los que las restricciones hayan provocado que esto suceda (al menos durante las horas de trabajo). Pero si es medianoche, soluciono un error y luego no estoy totalmente seguro de entender por qu\u00e9 aparentemente se rompi\u00f3 en primer lugar, tambi\u00e9n podr\u00eda quedarme despierto y resolverlo, \u00bfno?<\/p>\n<p>Es como la versi\u00f3n del programador del <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\">sesgo del costo irrecuperable<\/a>.<\/p>\n<p>De todos modos, como se describe anteriormente, aqu\u00ed est\u00e1 la esencia del problema:<\/p>\n<ol>\n<li>Una publicaci\u00f3n determinada existe en WordPress.<\/li>\n<li>Cuando se elimina un usuario, el sistema busca si existe cierto contenido dentro de una publicaci\u00f3n determinada y, de ser as\u00ed, lo elimina.<\/li>\n<li>Luego, la publicaci\u00f3n se actualiza utilizando una funci\u00f3n API de WordPress.<\/li>\n<\/ol>\n<p>Todo funciona muy bien, excepto que hay un problema: cada vez que la publicaci\u00f3n se actualiza mediante programaci\u00f3n, marca el estado de la publicaci\u00f3n como &quot;futuro&quot; en la base de datos y, en \u00faltima instancia, configura la l\u00ednea de pedido de la publicaci\u00f3n en la\u00a0 vista <strong>Todas<\/strong> las publicaciones como &quot;Programada&quot;.<\/p>\n<h3>dos soluciones<\/h3>\n<p>Hay dos formas de solucionar este problema:<\/p>\n<ol>\n<li>Ejecute una consulta r\u00e1pida directamente en la base de datos para solucionar el problema.<\/li>\n<li>Actualice los argumentos de la publicaci\u00f3n para usar la hora adecuada en GMT (cubrir\u00e9 esto m\u00e1s en un momento).<\/li>\n<\/ol>\n<p>Si opta por la primera soluci\u00f3n, aseg\u00farese de usar la funci\u00f3n de preparaci\u00f3n y aseg\u00farese de ejecutar la consulta <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-00-direct-database-query-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">despu\u00e9s de que se devuelva la funci\u00f3n de actualizaci\u00f3n<\/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 opta por la segunda soluci\u00f3n, actualice expl\u00edcitamente las propiedades del objeto de publicaci\u00f3n antes de pasarlo <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-01-maintain-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">a la funci\u00f3n de actualizaci\u00f3n<\/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>No soy de los que dicen que no hay lugar para ninguna de estas soluciones cuando se trabaja en un proyecto, pero la pregunta sigue siendo:<\/p>\n<p>\u00bfPor qu\u00e9 WordPress marca una publicaci\u00f3n programada para el futuro cuando la publicaci\u00f3n, antes de pasar por el procedimiento de actualizaci\u00f3n, estaba configurada para publicarse?<\/p>\n<p>Y si no est\u00e1 familiarizado con el resto de los argumentos que se pasan a WordPress al actualizar una publicaci\u00f3n, le llevar\u00e1 alg\u00fan tiempo localizarlo.<\/p>\n<h2>Comprender el problema<\/h2>\n<p>En aras de evitar escribir una consulta directa a la base de datos, opt\u00e9 por la segunda soluci\u00f3n porque es m\u00e1s limpia (aunque no la hace menos confusa).<\/p>\n<p>Para averiguar por qu\u00e9 ocurre este comportamiento, puede preguntarle a otro desarrollador o depurar el c\u00f3digo. Dado que estaba trabajando en esto a altas horas de la noche, opt\u00e9 por lo \u00faltimo.<\/p>\n<p>Ejecutando el depurador y rastreando el c\u00f3digo a trav\u00e9s de post.php.<\/p>\n<p>No voy a hablar sobre todos los puntos de interrupci\u00f3n y relojes que configur\u00e9, as\u00ed que intentar\u00e9 que esto sea lo m\u00e1s conciso posible.<\/p>\n<p>Primero, cuando el c\u00f3digo se ejecuta a trav\u00e9s de la funci\u00f3n <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_update_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_update_post<\/a>, 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 bloque 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>Tenga en cuenta que dentro del condicional, no estamos trabajando con un archivo adjunto y estamos trabajando con un estado de publicaci\u00f3n de &#8216;publicar&#8217;. As\u00ed que vamos a tocar el primer condicional dentro del condicional externo (un poco confuso, \u00bfno?).<\/p>\n<p>Ahora hay una variable, $post_status, que mantiene un valor de publicaci\u00f3n pero no est\u00e1 asignada a ninguna propiedad particular de la publicaci\u00f3n actual. Si contin\u00faa rastreando el 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\">encontrar\u00e1 la siguiente l\u00ednea<\/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>Aqu\u00ed, ver\u00e1 que funciona con un conjunto de claves de matriz que est\u00e1n contenidas en la variable $postarr. Esta variable se usa anteriormente en el c\u00f3digo (v\u00e9ala <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\">aqu\u00ed<\/a> en Trac). Y si observa detenidamente, ver\u00e1 que primero verifica si la propiedad post_date_gmt est\u00e1 vac\u00eda o si est\u00e1 en cero.<\/p>\n<p>Y como no lo es, usar\u00e1 el valor que especificamos en la propiedad <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-04-post-date-gmt-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">cuando inicialmente llamamos a la funci\u00f3n<\/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>Esperar.<\/p>\n<p>\u00bfPor qu\u00e9 volver a la funci\u00f3n cuando el c\u00f3digo ya pas\u00f3? Esa es la naturaleza de la depuraci\u00f3n. A veces ves variables y no piensas en ellas solo para ver que se usan, configuran, manipulan, combinan o cualquier otra cosa m\u00e1s adelante en el c\u00f3digo.<\/p>\n<p>Esa es la realidad.<\/p>\n<p>Pero de todos modos, debido a eso, la propiedad mantendr\u00e1 el valor que proporcionamos antes de llamar a la funci\u00f3n de actualizaci\u00f3n. Por lo general, este ser\u00e1 el mismo valor que cuando se inici\u00f3 la funci\u00f3n, pero puede haber ocasiones en las que desee, por ejemplo, descartar una publicaci\u00f3n.<\/p>\n<p>Y eso es 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>. Pero tiene sus advertencias, especialmente en torno a los tipos de publicaciones personalizadas.<\/p>\n<p>Sin embargo, eso pasa a otra publicaci\u00f3n.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mantener un estado de publicaci\u00f3n al actualizar una publicaci\u00f3n de WordPress puede tener resultados inesperados. Este es el por qu\u00e9 y c\u00f3mo administrarlo adecuadamente.<\/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":[892,716,800,840,861],"tags":[1172],"class_list":["post-228964","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-desarrollador","category-php-2","category-tutoriales","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/228964","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=228964"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/228964\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/223663"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=228964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=228964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=228964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}