Почему wp_update_post() не обновляет поле post_status?
Я использую этот код для добавления/обновления пользовательского типа записи с фронтенда. Дата устанавливается из кастомного jQuery datepicker.
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);
}
Это работает при первой публикации поста, правильно устанавливая статус как publish
или future
, с корректной датой.
Это не работает при редактировании того же поста - ни при смене с publish
на future
, ни в обратную сторону. Все остальные поля обновляются правильно, кроме статуса поста/будущей даты.
ОБНОВЛЕНИЕ 9 октября Я начинаю думать, что это может быть баг, поэтому я начал обсуждение в рассылке wp-hackers. По ссылке есть результаты тестов на свежей установке.
ДРУГИЕ НЕУДАЧНЫЕ ПОПЫТКИ:
Я пробовал оставить решение о post_status
на усмотрение wp_insert_post()
, используя:
elseif ('edit' == $operation) {
$newpostdata['post_status'] = '';
$newpostdata['ID'] = $post_id;
$err = wp_update_post($newpostdata);
}
Это устанавливает статус поста в draft
, сохраняя при этом запрошенные даты.
Я также пробовал вызвать wp_transition_post_status()
снова (эта функция вызывается один раз внутри wp_insert_post()):
elseif ('edit' == $operation) {
$newpostdata['ID'] = $post_id;
$err = wp_update_post($newpostdata);
wp_transition_post_status($old_status, $status, $post_id);
}
но это тоже не сработало.
У меня заканчиваются идеи. Есть какие-нибудь подсказки?

Ответ не мог быть проще.
Как указал Отто в списке рассылки wp-hackers, проблема была в том, что я не устанавливал post_date_gmt
при использовании wp_update_post()
.
Итоговый код выглядит так:
if ( $post_date < strtotime( "tomorrow" ) ) {
$status = 'publish';
$newpostdata['post_status'] = $status;
$newpostdata['post_date'] = date( 'Y-m-d H:i:s', $post_date );
// Также передаем 'post_date_gmt', чтобы WordPress корректно работал с датами
$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 );
// Также передаем 'post_date_gmt', чтобы WordPress корректно работал с датами
$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);
}

Я также пробовал приведенный выше код с использованием wp_update_post()
, но он плохо работает в WordPress 3.9 — делает post_status
пустым и удаляет все произвольные поля. Поэтому я создал собственный запрос, используя класс wpdb
. Надеюсь, это сработает и для вас:
$wpdb->query(
$wpdb->prepare(
"UPDATE $wpdb->posts SET post_status = 'draft' WHERE ID = %d",
$post_id
)
);
Этот вариант отлично сработал как на локальном сервере, так и на хостинге.

Добро пожаловать на [wordpress.se]. Надеюсь, вы не против изменений. Я исправил prepare-запрос.

Мы постоянно обновляем статус записей, вот пример того, как мы позволяем пользователям (во фронтенд-редакторе, который был создан) "приостанавливать" объявления, переводя их в черновики:
if ($action == 'pause') {
$my_post = array();
$my_post['ID'] = $aid;
$my_post['post_status'] = 'draft';
wp_update_post($my_post);
$action_msg = __('Объявление приостановлено', 'mytheme');
}

Не проблема автора исходного сообщения, но важное замечание для тех, кто приходит сюда в поисках решения похожей проблемы, когда wp_update_post()
не обновляет post_status
...
Как отметил @adrianthedev выше в комментарии к исходному сообщению, обратите внимание, что максимальная длина пользовательского статуса записи составляет 20 символов.
https://developer.wordpress.org/reference/functions/register_post_status/#comment-3927
При превышении 20 символов вы можете зарегистрировать пользовательский статус записи с помощью register_post_status()
, но на данный момент (по крайней мере, в WordPress версии 5.5.1) вы не сможете установить этот статус для записи с помощью wp_update_post()
.
