「カレンダー」ウィジェットでカスタム投稿タイプを表示する方法

Cocoonカスタマイズ集
この記事は約5分で読めます。
記事内に広告が含まれています。

はじめに

「カレンダー」ウィジェットは、標準では投稿タイプを選べず、通常投稿(post)のみが対象になります。

しかし、複数の投稿タイプを使っている場合は、カスタム投稿タイプごとにカレンダーを表示したいこともあるでしょう。

この記事では、この方法について説明します。

WordPressの仕様上、1ページに複数のカレンダーを設置している場合、前後月ボタンを操作すると、全てのカレンダーの表示月が同時に切り替わります。

完成イメージ

実装手順

以下のコードを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);

さいごに

今回紹介した方法を使えば、「カレンダー」ウィジェットでカスタム投稿タイプを簡単に表示できるようになります。
標準では対応していないため、複数の投稿タイプを運用しているサイトでは非常に便利です。

タイトルとURLをコピーしました