WordPress как на ладони

[Решено] Автоматическая смена статуса записи на произвольный и исключение таких записей из цикла

Зарегистрирован свой статус постов '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, или основной цикл подправить.

1
OLD_Grays
5.8 лет назад 44
  • 3

    Повесить на крон задачу:

    1. Выбрать все записи со статусом publish и датой до 31.12.2017
    2. Обновить у этих записей статус на archive
    OLD_Grays 5.8 лет назад

    Спасибо за совет. Решил немного другим способом. Костыль конечно, но, вроде, работает как надо:

    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'.

    Виктор 5.8 лет назад

    Здравствуйте. У вас на init-е перебор постов. Это плохо - каждая загрузка страницы ждет переборку постов ( get_posts( $args ) ). Если у вас постов не много, то это не заметно. Но это временно. Лучше, все таки, на крон повесить задачу - https://wp-kama.ru/function/wp_cron

    OLD_Grays 5.8 лет назад

    Повесил на крон, но есть пара непонятных моментов.

    // 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 формате?

    OLD_Grays 5.8 лет назад

    Вроде, всё получилось. Проверил с малым интервалом, работает.

    Kama 5.8 лет назад

    Крон это конечно самое грамотное решение.

    Но я бы сделал еще проще: при заходе не страницу поста, т.е. когда он просматривается, сравниваем статус и дату, если нужно в архив, то меняем статус у записи. Так суть не изменится, а вычислений и самого кода будет меньше, а значит стабильнее все работать будет...

    OLD_Grays 5.8 лет назад

    Есть ещё маленький вопросик.
    Если вешаю изменение статуса при обновлении/сохранении поста (ну, допустим, если придётся публиковать пост задним числом), он не удаляется, т.е. статус не может смениться на 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');
    	}
    }
    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация