はじめに
「カレンダー」ウィジェットは、標準では投稿タイプを選べず、通常投稿(post)のみが対象になります。
しかし、複数の投稿タイプを使っている場合は、カスタム投稿タイプごとにカレンダーを表示したいこともあるでしょう。
この記事では、この方法について説明します。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
// ウィジェットに設定メニューを追加
add_action('in_widget_form', function ($widget, $return, $instance) {
if ($widget->id_base !== 'calendar') {
return;
}
$post_type = !empty($instance['post_type']) ? $instance['post_type'] : '';
// カスタム投稿タイプを取得
$custom_post_types = array_filter(get_post_types(['public' => true], 'objects'), function ($pt) {
return !in_array($pt->name, ['post', 'page', 'attachment'], true);
});
?>
<p>
<label>投稿タイプ:</label><br>
<select class="widefat" name="<?= esc_attr($widget->get_field_name('post_type')); ?>">
<option value=""><?= esc_html('投稿'); ?></option>
<?php foreach ($custom_post_types as $pt): ?>
<option value="<?= esc_attr($pt->name); ?>" <?php selected($post_type, $pt->name); ?>>
<?= esc_html($pt->label); ?>
</option>
<?php endforeach; ?>
</select>
</p>
<?php
}, 10, 3);
// ウィジェットの入力データを更新
add_filter('widget_update_callback', function ($instance, $new_instance, $old_instance, $widget) {
if ($widget->id_base !== 'calendar') {
return $instance;
}
$instance['post_type'] = !empty($new_instance['post_type']) ? sanitize_text_field($new_instance['post_type']) : '';
return $instance;
}, 10, 4);
// フロントエンド表示に反映
add_filter('widget_display_callback', function ($instance, $widget, $args) {
if ($widget->id_base !== 'calendar') {
return $instance;
}
// 保存済みの投稿タイプを取得
$post_type = $instance['post_type'] ?? '';
if (!$post_type || $post_type === 'post') {
return $instance;
}
// カレンダーのHTMLを取得
$calendar_args = [
'post_type' => $post_type,
'display' => false,
];
$calendar_html = get_calendar($calendar_args);
// カレンダー内のリンクに投稿タイプを追加
$calendar_html = preg_replace_callback(
'/href="([^"]+)"/',
function ($matches) use ($post_type) {
$url = $matches[1];
$url = add_query_arg('post_type', $post_type, html_entity_decode($url));
return 'href="' . esc_url($url) . '"';
},
$calendar_html
);
// ウィジェットを出力
$output = $args['before_widget'];
if (!empty($instance['title'])) {
$output .= $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
}
$output .= '<div id="calendar_wrap">' . $calendar_html . '</div>';
$output .= $args['after_widget'];
echo $output;
return false;
}, 10, 3);
さいごに
今回紹介した方法を使えば、「カレンダー」ウィジェットでカスタム投稿タイプを簡単に表示できるようになります。
標準では対応していないため、複数の投稿タイプを運用しているサイトでは非常に便利です。
