投稿記事を指定した日時で下書きに戻したいことがありますよね。
プラグインがあるのかと思いますが、functions.phpで対応してみました。
できるだけプラグインは使いたくないのでfunctions.phpにコードを追加しました。
指定した日時で下書きに戻し公開を終了することができます。
おまけとして、先頭固定した記事を指定日時で先頭固定を外し、通常の公開にすることもできるようにしてます。
ニーズは無いと思いますが、折角だからメモを残しました。
完成した投稿記事の入力画面がこちら。

赤枠部分が追加した機能です。
公開終了日時を指定して下書きにするかを選択できるようにします。

公開終了日時の指定にはカレンダーからの選択式とします。
もちろん直接入力もできますよ。
以下がfunctions.phpに追加する内容です。
/**
* 投稿記事を指定日時で下書きにする
*/
// メタボックス追加
add_action('add_meta_boxes', 'add_expiration_meta_boxes');
function add_expiration_meta_boxes() {
$post_types = apply_filters('custom_expiration_post_types', ['post']);
foreach ($post_types as $type) {
add_meta_box('expiration_datetime', '公開終了日時', 'render_expiration_datetime_field', $type, 'side');
add_meta_box('expiration_action', '公開終了後の処理', 'render_expiration_action_field', $type, 'side');
}
}
// 公開終了日時入力フィールド
function render_expiration_datetime_field() {
$meta_key = 'expiration_datetime';
global $post;
$stored_value = get_post_meta($post->ID, $meta_key, true);
$formatted_value = $stored_value ? str_replace(' ', 'T', $stored_value) : '';
wp_nonce_field('action-' . $meta_key, 'nonce-' . $meta_key);
echo '<div class="custom-field-input">';
echo '<label for="' . $meta_key . '">公開終了日時</label><br>';
echo '<input type="datetime-local" name="' . $meta_key . '" id="' . $meta_key . '" value="' . esc_attr($formatted_value) . '">';
echo '<p>カレンダーをクリックして日時を設定します。</p>';
echo '</div>';
}
// 公開終了後の状態選択フィールド
function render_expiration_action_field() {
$meta_key = 'post_expiration_action';
global $post;
$stored_value = get_post_meta($post->ID, $meta_key, true) ?: 'none';
$options = [
'none' => '公開を続ける',
'draft' => '下書きにする',
'unpin' => '先頭固定解除し公開を続ける'
];
wp_nonce_field('action-' . $meta_key, 'nonce-' . $meta_key);
echo '<p>投稿の有効期限を設定した場合に期限後の状態を選択します。</p>';
foreach ($options as $value => $label) {
$checked = checked($value, $stored_value, false);
echo '<label><input type="radio" name="' . $meta_key . '" value="' . $value . '" ' . $checked . '> ' . esc_html($label) . '</label><br>';
}
}
// 保存処理とスケジュール登録
add_action('save_post', 'save_expiration_fields');
function save_expiration_fields($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
$post = get_post($post_id);
if (!in_array($post->post_type, apply_filters('custom_expiration_post_types', ['post']))) return;
$meta_keys = ['expiration_datetime', 'post_expiration_action'];
foreach ($meta_keys as $key) {
if (isset($_POST['nonce-' . $key]) && check_admin_referer('action-' . $key, 'nonce-' . $key)) {
if (!empty($_POST[$key])) {
$value = sanitize_text_field($_POST[$key]);
if ($key === 'expiration_datetime') {
$value = str_replace('T', ' ', $value);
}
update_post_meta($post_id, $key, $value);
} else {
delete_post_meta($post_id, $key);
}
}
}
// スケジュール登録
$expiration = get_post_meta($post_id, 'expiration_datetime', true);
if ($expiration && current_time('Y-m-d H:i:s') < $expiration) {
$timestamp = (new DateTime($expiration, wp_timezone()))->getTimestamp();
if (!wp_next_scheduled('handle_post_expiration_event', [$post_id])) {
wp_schedule_single_event($timestamp, 'handle_post_expiration_event', [$post_id]);
}
}
}
// スケジュールされた処理
add_action('handle_post_expiration_event', 'process_post_expiration');
function process_post_expiration($post_id) {
$action = get_post_meta($post_id, 'post_expiration_action', true);
$post = get_post($post_id);
if (!$post || !in_array($post->post_type, apply_filters('custom_expiration_post_types', ['post']))) return;
if ($action === 'draft') {
wp_update_post(['ID' => $post_id, 'post_status' => 'draft']);
} elseif ($action === 'unpin') {
$sticky_posts = get_option('sticky_posts', []);
$key = array_search($post_id, $sticky_posts);
if ($key !== false) {
unset($sticky_posts[$key]);
update_option('sticky_posts', array_values($sticky_posts));
}
}
// 状態リセット
delete_post_meta($post_id, 'expiration_datetime');
update_post_meta($post_id, 'post_expiration_action', 'none');
}
コピペするだけで問題なく動くと思います。
多分。。。
コピペする前にはfunctions.phpをバックアップ取ったりと、万が一に備えて対策しておいてください。
コメント