Mantener el estado de una publicación al actualizar una publicación de WordPress
Acabo de terminar una función para un proyecto que utiliza una combinación de tipos de publicaciones personalizadas, importaciones de datos y actualización de publicaciones existentes al eliminar un usuario (o un conjunto de usuarios).
Sin embargo, hay un problema:
Digamos que tiene una publicación que está publicada actualmente (es decir, su ‘post_status’ está configurado en ‘publicar’) pero, cuando actualiza la publicación a través de wp_update_post, su atributo post_status está configurado en ‘futuro’.
En otras palabras, cada vez que actualiza una publicación mediante programación, el estado de la publicación se establece en ‘Programada’ (según la interfaz de usuario) y ‘futuro’ (según la columna de la base de datos).
Entonces, ¿qué da?
Publicar estado al actualizar
En términos generales, no soy fanático de hacer que algo funcione, descubrir que funciona y pasar a la siguiente tarea a menos que comprenda exactamente por qué no funcionó [como se esperaba] en primer lugar.
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é aparentemente se rompió en primer lugar, también podría quedarme despierto y resolverlo, ¿no?
Es como la versión del programador del sesgo del costo irrecuperable.
De todos modos, como se describe anteriormente, aquí está la esencia del problema:
- Una publicación determinada existe en WordPress.
- Cuando se elimina un usuario, el sistema busca si existe cierto contenido dentro de una publicación determinada y, de ser así, lo elimina.
- Luego, la publicación se actualiza utilizando una función API de WordPress.
Todo funciona muy bien, excepto que hay un problema: cada vez que la publicación se actualiza mediante programación, marca el estado de la publicación como "futuro" en la base de datos y, en última instancia, configura la línea de pedido de la publicación en la vista Todas las publicaciones como "Programada".
dos soluciones
Hay dos formas de solucionar este problema:
- Ejecute una consulta rápida directamente en la base de datos para solucionar el problema.
- Actualice los argumentos de la publicación para usar la hora adecuada en GMT (cubriré esto más en un momento).
Si opta por la primera solución, asegúrese de usar la función de preparación y asegúrese de ejecutar la consulta después de que se devuelva la función de actualización.
<?php
// First, update the post using the available WordPress API.
wp_update_post( $post );
/**
* If the post status attribute of the post that was just updated
* maintains the 'publish' post setatus, then manually update the
* database column.
*/
if ('publish' === $post->post_status) {
global $wpdb;
$wpdb->query(
$wpdb->prepare(
"
UPDATE $wpdb->posts
SET post_status = '%s'
WHERE ID = %d
",
'publish',
$post->ID) );
}
Si opta por la segunda solución, actualice explícitamente las propiedades del objeto de publicación antes de pasarlo a la función de actualización.
<?php
$event_post->post_date_gmt = gmdate( 'Y-m-d H:i:s', $event_post->post_date_gmt );
wp_update_post( $event_post );
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:
¿Por qué WordPress marca una publicación programada para el futuro cuando la publicación, antes de pasar por el procedimiento de actualización, estaba configurada para publicarse?
Y si no está familiarizado con el resto de los argumentos que se pasan a WordPress al actualizar una publicación, le llevará algún tiempo localizarlo.
Comprender el problema
En aras de evitar escribir una consulta directa a la base de datos, opté por la segunda solución porque es más limpia (aunque no la hace menos confusa).
Para averiguar por qué ocurre este comportamiento, puede preguntarle a otro desarrollador o depurar el código. Dado que estaba trabajando en esto a altas horas de la noche, opté por lo último.
Ejecutando el depurador y rastreando el código a través de post.php.
No voy a hablar sobre todos los puntos de interrupción y relojes que configuré, así que intentaré que esto sea lo más conciso posible.
Primero, cuando el código se ejecuta a través de la función wp_update_post, encontrará este bloque de código :
<?php
if ('attachment' !== $post_type) {
if ('publish' == $post_status) {
$now = gmdate('Y-m-d H:i:59');
if (mysql2date('U', $post_date_gmt, false) > mysql2date('U', $now, false)) {
$post_status = 'future';
}
} elseif ('future' == $post_status) {
$now = gmdate('Y-m-d H:i:59');
if (mysql2date('U', $post_date_gmt, false) <= mysql2date('U', $now, false)) {
$post_status = 'publish';
}
}
}
Tenga en cuenta que dentro del condicional, no estamos trabajando con un archivo adjunto y estamos trabajando con un estado de publicación de ‘publicar’. Así que vamos a tocar el primer condicional dentro del condicional externo (un poco confuso, ¿no?).
Ahora hay una variable, $post_status, que mantiene un valor de publicación pero no está asignada a ninguna propiedad particular de la publicación actual. Si continúa rastreando el código, encontrará la siguiente línea :
<?php
$post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr) ), $postarr );
Aquí, verá que funciona con un conjunto de claves de matriz que están contenidas en la variable $postarr. Esta variable se usa anteriormente en el código (véala aquí en Trac). Y si observa detenidamente, verá que primero verifica si la propiedad post_date_gmt está vacía o si está en cero.
Y como no lo es, usará el valor que especificamos en la propiedad cuando inicialmente llamamos a la función :
<?php
if (empty( $postarr['post_date_gmt']) || '0000-00-00 00:00:00' == $postarr['post_date_gmt']) {
if (! in_array( $post_status, array( 'draft', 'pending', 'auto-draft') )) {
$post_date_gmt = get_gmt_from_date( $post_date );
} else {
$post_date_gmt = '0000-00-00 00:00:00';
}
} else {
$post_date_gmt = $postarr['post_date_gmt'];
}
Esperar.
¿Por qué volver a la función cuando el código ya pasó? Esa es la naturaleza de la depuración. A veces ves variables y no piensas en ellas solo para ver que se usan, configuran, manipulan, combinan o cualquier otra cosa más adelante en el código.
Esa es la realidad.
Pero de todos modos, debido a eso, la propiedad mantendrá el valor que proporcionamos antes de llamar a la función de actualización. Por lo general, este será el mismo valor que cuando se inició la función, pero puede haber ocasiones en las que desee, por ejemplo, descartar una publicación.
Y eso es motivo para usar wp_delete_post. Pero tiene sus advertencias, especialmente en torno a los tipos de publicaciones personalizadas.
Sin embargo, eso pasa a otra publicación.