CPTを private
status に保存しています。そのため、移行はpending
からprivate
になります。つまり、投稿が最初に送信されて保留中の場合は、その送信日がdbのpost_date
フィールドにあります。しかし、投稿が公開されると、日付は現在の日付に更新されました。
後日非公開にされる投稿であっても、投稿の当初の投稿日を保存したいです。
だから私は以下のようなことをしました:
function mycpt_keep_pending_date_on_publishing( $new_status, $old_status, $post ) {
if( 'mycpt' === $post->post_type && 'pending' === $old_status && 'private' === $new_status ) :
$pending_datetime = get_post_field( 'post_date', $post->ID, 'raw' );
// Update the post
$modified_post = array(
'ID' => $post->ID,
'post_date' => $pending_datetime,
'post_date_gmt' => get_gmt_from_date( $pending_datetime )
);
// Update the post into the database
wp_update_post( $modified_post );
endif;
}
add_action( 'transition_post_status', 'mycpt_keep_pending_date_on_publishing' );
しかし、うまくいきません。その理由は何ですか?
@Howdy_McGeeは、彼のコメントで正しい方向に進んでいます。 transition_post_status が発生するまでに、投稿はすでに更新されています(つまり、dbに書き込まれています)。
以下のように、 wp_insert_post_data 、の代わりにtransition_post_status
にフックする必要があります。
add_filter ('wp_insert_post_data', 'mycpt_keep_pending_date_on_publishing', 10, 2) ;
function
mycpt_keep_pending_date_on_publishing ($data, $postarr)
{
if ($data['post_type'] != 'mycpt') {
return ($data) ;
}
// this check amounts to the same thing as transition_post_status(private, pending)
if ('private' != $data['post_status'] || 'pending' != $postarr['original_post_status']) {
return ($data) ;
}
$pending_datetime = get_post_field ('post_date', $data['ID'], 'raw') ;
$data['post_date'] = $pending_datetime ;
$data['post_date_gmt'] = get_gmt_from_date ($pending_datetime) ;
return ($data) ;
}
注:私はあなたが使ったのと同じ関数名を使いましたが、その関数の本体は異なります。
他の答えに加えて、これはコードが一度だけ実行されることを確認する小さなプラグインです。後で実行しているプラグインによってデータがリセットされる場合は、PHP_INT_MAX -1
を優先順位として使用してください(公に配布されているプラグインではありません)。この場合、remove_filter()
に同じ値を設定する必要があります。そうしないと、コールバックは削除されません。
<?php
/**
* Plugin Name: (WPSE) Static post date
* Description: Keep the post date as the original date for posts published as private
*/
namespace WPSE;
add_filter( 'wp_insert_post_data', '\WPSE\save', 10, 2 );
function save( $post, $raw ) {
if ( ! in_array( $post['post_status'], [ 'private', 'pending', ] ) ) {
return $post;
}
if ( 'your_post_type' !== $post['post_type'] ) {
return $post;
}
$date = get_post_field( 'post_date', $post['ID'], 'raw' );
$post['post_date'] = $date;
$post['post_date_gmt'] = get_gmt_from_date( $date );
return $post;
}
add_action( 'transition_post_status', function() {
# Make sure above callback is only triggered once
remove_filter( 'wp_insert_post_data', '\WPSE\save' );
} );
IIRCの上記のコードに関する主な問題は、private_to_published
フィルタが廃止されたため、投稿タイプのステータスフィルタを除く _ _ _という特別なものは何もないことです。次のプラグインを試して、それが機能するかどうかを確認してください(あなたの投稿タイプが本当にmycpt
という名前の場合):
<?php
/* Plugin Name: (WPSE) Test post type status actions */
add_action( 'private_mycpt', function( $ID, \WP_Post $post ) {
var_dump( current_filter() );
exit;
}, 10, 2 );