¿Por qué wp_update_post() no actualiza el campo post_status?
Estoy usando este código para insertar/actualizar un tipo de publicación personalizado desde el front-end. La fecha se establece desde un selector de fechas personalizado con jQuery.
if (strtotime($date) < strtotime('tomorrow')) {
$newpostdata['post_status'] = 'publish';
} elseif (strtotime($date) > strtotime('today')) {
$newpostdata['post_status'] = 'future';
$newpostdata['post_date'] = date('Y-m-d H:i:s', strtotime($date));
}
if ('insert' == $operation) {
$err = wp_insert_post($newpostdata, true);
} elseif ('edit' == $operation) {
$newpostdata['ID'] = $post_id;
$err = wp_update_post($newpostdata);
}
Esto funciona cuando se publica por primera vez, estableciéndolo correctamente como publish
o future
, con la fecha correcta.
Esto no funciona al editar la misma publicación, ni de publish
a future
ni viceversa. Todo lo demás se actualiza correctamente, excepto el estado de la publicación/future_date.
ACTUALIZACIÓN 9 de Octubre Estoy empezando a pensar que esto podría ser un error, así que inicié una conversación en la lista de correo wp-hackers, sobre esto. Hay algunos resultados de pruebas en instalaciones frescas en el enlace.
OTROS INTENTOS FALLIDOS:
He intentado dejar las decisiones de post_status
a wp_insert_post()
usando:
elseif ('edit' == $operation) {
$newpostdata['post_status'] = '';
$newpostdata['ID'] = $post_id;
$err = wp_update_post($newpostdata);
}
Y esto establece el estado de la publicación como draft
mientras mantiene las fechas solicitadas.
También he intentado llamar a wp_transition_post_status()
nuevamente (se llama una vez dentro de wp_insert_post()):
elseif ('edit' == $operation) {
$newpostdata['ID'] = $post_id;
$err = wp_update_post($newpostdata);
wp_transition_post_status($old_status, $status, $post_id);
}
pero eso tampoco pareció funcionar.
Me estoy quedando sin ideas aquí. ¿Alguna pista?

La respuesta no podría ser más simple.
Como señaló Otto en la lista de wp-hackers, el problema era que no estaba configurando post_date_gmt
al usar wp_update_post()
.
El código final queda así:
if ( $post_date < strtotime( "tomorrow" ) ) {
$status = 'publish';
$newpostdata['post_status'] = $status;
$newpostdata['post_date'] = date( 'Y-m-d H:i:s', $post_date );
// También pasar 'post_date_gmt' para que WP maneje bien las fechas
$newpostdata['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $post_date );
} elseif ( $post_date > strtotime( 'today' ) ) {
$status = 'future';
$newpostdata['post_status'] = $status;
$newpostdata['post_date'] = date( 'Y-m-d H:i:s', $post_date );
// También pasar 'post_date_gmt' para que WP maneje bien las fechas
$newpostdata['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $post_date );
}
if ('insert' == $operation) {
$err = wp_insert_post($newpostdata, true);
} elseif ('edit' == $operation) {
$newpostdata['ID'] = $post_id;
$err = wp_update_post($newpostdata);
}

También probé el código anterior usando wp_update_post()
, pero no funciona bien con WordPress 3.9, deja el post_status
vacío y elimina todos los campos personalizados. Por lo tanto, creé una consulta personalizada utilizando la clase wpdb
. Espero que esto funcione para todos ustedes:
$wpdb->query(
$wpdb->prepare(
"UPDATE $wpdb->posts SET post_status = 'draft' WHERE ID = %d",
$post_id
)
);
y esto funcionó bien tanto en mi localhost como en el hosting.

Bienvenido a [wordpress.se]. Espero que no te importen las modificaciones. Corregí la declaración prepare.

Actualizamos el estado de las publicaciones todo el tiempo, aquí hay un ejemplo de cómo permitimos a los usuarios (en el editor de front-end que construimos) "pausar" anuncios cambiándolos a borrador:
if ($action == 'pause') {
$my_post = array();
$my_post['ID'] = $aid;
$my_post['post_status'] = 'draft';
wp_update_post($my_post);
$action_msg = __('El anuncio ha sido pausado', 'mytheme');
}

No es el problema del OP, pero como un punto de referencia notable para otros que lleguen aquí investigando un problema similar donde wp_update_post()
no actualiza el post_status
...
Como @adrianthedev mencionó anteriormente en un comentario sobre el OP, ten en cuenta que la longitud máxima de un estado de publicación personalizado es de 20 caracteres.
https://developer.wordpress.org/reference/functions/register_post_status/#comment-3927
Cuando se exceden los 20 caracteres, puedes registrar el estado de publicación personalizado usando register_post_status()
, pero actualmente no podrás establecer una publicación con ese estado usando wp_update_post()
, al menos hasta WordPress v5.5.1
