[Решено] Автоматическая смена статуса записи на произвольный и исключение таких записей из цикла
Зарегистрирован свой статус постов 'archive'. Статус добавлен в drop-down на странице редактирования постов, добавлена метка статуса и статус добавлен в быстрое редактирование постов:
function posts_custom_status(){
register_post_status( 'archive', array(
'label' => 'Архив',
// 'label' => _x( 'Архив', 'event' ),
'label_count' => _n_noop( 'Архив <span class="count">(%s)</span>', 'Архивы <span class="count">(%s)</span>' ),
'public' => true,
'show_in_admin_status_list' => true
) );
}
add_action( 'init', 'posts_custom_status' );
function append_post_custom_status_list(){
global $post;
$optionselected = '';
$statusname = '';
if( $post->post_type == 'post' ){ // если хотите, можете указать тип поста, для которого регистрируем статус, а можете и вовсе избавиться от этого условия
if($post->post_status == 'archive'){ // если посту присвоен статус архива
$optionselected = ' selected="selected"';
$statusname = "$('#post-status-display').text('Архивировано');";
}
echo "<script>
jQuery(function($){
$('select#post_status').append('<option value=\"archive\"$optionselected>Архив</option>');
$statusname
});
</script>";
}
}
add_action('admin_footer-post-new.php', 'append_post_custom_status_list');
add_action('admin_footer-post.php', 'append_post_custom_status_list');
function post_custom_status_display( $statuses ) {
global $post;
if( get_query_var( 'post_status' ) != 'archive' ){ // проверка, что мы не находимся на странице всех постов данного статуса
if($post->post_status == 'archive'){ // если статус поста - Архив
return array('Архив');
}
}
return $statuses;
}
add_filter( 'display_post_states', 'post_custom_status_display' );
add_action('admin_footer-edit.php','add_post_custom_status');
function add_post_custom_status() {
echo "<script>
jQuery(document).ready( function($) {
$( 'select[name=\"_status\"]' ).append( '<option value=\"archive\">Архив</option>' );
});
</script>";
}
Вопрос. Как сделать так, что бы у определённых постов (допустим у тех, у которых дата публикации старше, к примеру, 2017 года, т.е. все посты до 31.12.2017) статус автоматически менялся с 'publish' на 'archive'? Не при сохранении/обновлении, т.е. не на хуке save_post, а именно автоматом.
Пытался забить в функцию проверку дат постов и wp_update_post(), но не пойму на какой хук вешать.
Ну исключить такие посты просто, достаточно повесить фильтр pre_get_posts, или основной цикл подправить.
Повесить на крон задачу:
Спасибо за совет. Решил немного другим способом. Костыль конечно, но, вроде, работает как надо:
add_action('init', 'update_post_status'); function update_post_status() { $cur_year = date('Y'); $prev_year = date("Y",strtotime("-1 year")); $args = array( 'post_type' => 'post', 'post_status' => 'publish', 'suppress_filters' => true, // подавление работы фильтров изменения SQL запроса 'date_query' => array( array( 'before' => array( // до этой даты 'year' => $prev_year, 'month' => 12, 'day' => 31, ), // 'inclusive'=> true ) ) ); $posts = get_posts( $args ); foreach($posts as $post) { setup_postdata($post); // формат вывода $post_id = $post->ID; $post_date = get_the_date('Y', $post_id); if( $post_date < $cur_year ) wp_update_post(array('ID' => $post_id, 'post_status' => 'archive')); } wp_reset_postdata(); }В результате, все записи, которые были созданы ранее, и создаваемые вновь (если указывать тот же 2017 при создании) автоматом получают статус 'archive'.
Здравствуйте. У вас на init-е перебор постов. Это плохо - каждая загрузка страницы ждет переборку постов ( get_posts( $args ) ). Если у вас постов не много, то это не заметно. Но это временно. Лучше, все таки, на крон повесить задачу - https://wp-kama.ru/function/wp_cron
Повесил на крон, но есть пара непонятных моментов.
// if ( ! wp_next_scheduled( 'update_post_status_task_hook' ) ) { // $cur_year = date('Y'); // $next_year = date('Y',strtotime("+1 year")); // wp_schedule_event( $next_year, 'daily', 'update_post_status_task_hook' ); // } if ( ! wp_next_scheduled( 'update_post_status_task_hook' ) ) { wp_schedule_event( time(), 'my_period' ,'update_post_status_task_hook' ); } // добавляем крон хук add_action( 'update_post_status_task_hook', 'update_post_status' ); function update_post_status() { $cur_year = date('Y'); $prev_year = date("Y",strtotime("-1 year")); $args = array( 'post_type' => 'post', 'post_status' => 'publish', 'suppress_filters' => true, // подавление работы фильтров изменения SQL запроса 'date_query' => array( array( 'before' => array( // до этой даты 'year' => $prev_year, 'month' => 12, 'day' => 31, ), // 'inclusive'=> true ) ) ); $posts = get_posts( $args ); foreach($posts as $post) { setup_postdata($post); // формат вывода $post_id = $post->ID; $post_date = get_the_date('Y', $post_id); if( $post_date < $cur_year ) wp_update_post(array('ID' => $post_id, 'post_status' => 'archive')); } wp_reset_postdata(); }Почему-то, с самого начала статус был присвоен не всем постам за 2017 год. А второй момент, получается мне нужно запланировать выполнение по сути на конкретную дату, типа 1 января следующего года и задать интервал раз в год, так что ли? Как тогда передать вместо time() следующий год в unix формате?
Вроде, всё получилось. Проверил с малым интервалом, работает.
Крон это конечно самое грамотное решение.
Но я бы сделал еще проще: при заходе не страницу поста, т.е. когда он просматривается, сравниваем статус и дату, если нужно в архив, то меняем статус у записи. Так суть не изменится, а вычислений и самого кода будет меньше, а значит стабильнее все работать будет...
Есть ещё маленький вопросик.
Если вешаю изменение статуса при обновлении/сохранении поста (ну, допустим, если придётся публиковать пост задним числом), он не удаляется, т.е. статус не может смениться на trash получается. Как быть?
add_action( 'save_post', 'update_post_status' ); function update_post_status( $post_id ){ if ( ! wp_is_post_revision( $post_id ) ){ remove_action('save_post', 'update_post_status'); $cur_year = date('Y'); $post_date = get_the_date('Y', $post_id); $post_type = get_post_type( $post_id ); if( ($post_type == 'post') && ($post_date < $cur_year) ) wp_update_post(array('ID' => $post_id, 'post_status' => 'archive')); // снова вешаем хук add_action('save_post', 'update_post_status'); } }