カテゴリー一覧から不要なカテゴリーを非表示する方法

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

はじめに

WordPressでは、カテゴリーウィジェットを利用して、カテゴリーの一覧をサイドバーなどに表示できます。

しかし、カテゴリーが増えてくると、表示する必要のないカテゴリーが一覧に含まれ、目的のカテゴリーを見つけにくくなることがあります。

そこで、機能を拡張し、カテゴリー一覧画面に「表示/非表示」の切り替えボタンを設置して、カテゴリーごとに表示・非表示を設定できるようにします。

また、親カテゴリーを非表示にした場合は、子カテゴリーも自動的に非表示にすることで、カテゴリー一覧を整理しやすくします。

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

完成イメージ

実装手順

以下のコードをfunctions.phpに追加します。

/**
 * 非表示カテゴリーとその子孫カテゴリーのID一覧を取得
 *
 * @return int[] 非表示対象となるカテゴリーIDの配列
 */
if (!function_exists('my_get_hidden_category_cloud_ids')):
function my_get_hidden_category_cloud_ids() {
  // 非表示フラグが設定されたカテゴリーIDを取得
  $hidden_terms   = get_terms([
    'taxonomy'    => 'category',
    'hide_empty'  => false,
    'meta_query'  => [
      [
        'key'     => 'my_hide_category_cloud',
        'value'   => '1',
        'compare' => '=',
      ],
    ],
    'fields' => 'ids',
  ]);

  // 非表示カテゴリーが存在しない場合は空の配列を返して終了
  if (is_wp_error($hidden_terms) || empty($hidden_terms)) {
    return [];
  }

  $exclude_ids = [];

  foreach ($hidden_terms as $term_id) {
    // 非表示カテゴリー自身のIDを登録
    $exclude_ids[] = (int) $term_id;

    // 子孫カテゴリーのIDを取得
    $children = get_term_children((int) $term_id, 'category');

    // 子孫カテゴリーが存在する場合は除外対象に追加
    if (!is_wp_error($children) && !empty($children)) {
      $exclude_ids = array_merge($exclude_ids, array_map('intval', $children));
    }
  }

  // 重複するカテゴリーIDを除去して返却
  return array_values(array_unique($exclude_ids));
}
endif;


// 管理画面一覧にカラムを追加
add_filter('manage_edit-category_columns', function ($columns) {
  $columns['category_visibility'] = '表示/非表示';

  return $columns;
});


// 管理画面一覧のカラムにデータを表示
add_filter('manage_category_custom_column', function ($value, $column_name, $term_id) {
  if ('category_visibility' !== $column_name) {
    return $value;
  }

  // 非表示カテゴリーとその子孫のIDを取得
  $hidden_ids = my_get_hidden_category_cloud_ids();

  // 対象カテゴリーの非表示状態を判定
  $is_hidden = in_array((int) $term_id, $hidden_ids, true);

  // 非表示状態に応じてCSSクラスを設定
  $btn_class = $is_hidden ? 'category-vis-btn is-hidden' : 'category-vis-btn is-visible';
  $btn_text  = $is_hidden ? '非表示' : '表示中';

  return '<button type="button" class="button button-small ' . esc_attr($btn_class) . '" data-term-id="' . esc_attr($term_id) . '">' . esc_html($btn_text) . '</button>';
}, 10, 3);


// 管理画面用JS・CSSを追加
add_action('admin_enqueue_scripts', function ($hook_suffix) {
  if ($hook_suffix !== 'edit-tags.php') {
    return;
  }

  // 現在の管理画面のスクリーン情報を取得
  $screen = get_current_screen();
  if (!$screen || $screen->taxonomy !== 'category') {
    return;
  }

  ob_start();
  ?>
  .category-vis-btn {
    &.is-visible {
      border-color: #00a32a !important;
      color: #00a32a !important;
    }

    &.is-hidden {
      border-color: #d63638 !important;
      color: #d63638 !important;
    }
  }
  <?php
  wp_add_inline_style('wp-admin', ob_get_clean());

  $handle = 'category-visibility-admin-js';

  wp_register_script($handle, '');
  wp_enqueue_script($handle);

  wp_localize_script($handle, 'categoryVisData', [
    'ajaxurl'                   => admin_url('admin-ajax.php'),
    'category_visibility_nonce' => wp_create_nonce('category_visibility_action')
  ]);

  ob_start();
  ?>
  jQuery(document).ready(function($) {
    $(document).on('click', '.category-vis-btn', function() {
      var $btn = $(this);
      var termId = $btn.data('term-id');

      $btn.prop('disabled', true);

      $.ajax({
        url: categoryVisData.ajaxurl,
        type: 'POST',
        data: {
          action: 'toggle_category_visibility_btn',
          term_id: termId,
          category_visibility_nonce: categoryVisData.category_visibility_nonce
        },
        success: function(response) {
          $btn.prop('disabled', false);
          if (response.success) {
            window.location.reload();
          } else {
            alert(response.data || '更新に失敗しました。');
          }
        },
        error: function() {
          $btn.prop('disabled', false);
          alert('通信エラーが発生しました。');
        }
      });
    });
  });
  <?php
  wp_add_inline_script($handle, ob_get_clean());
});


// Ajaxアクションを追加
add_action('wp_ajax_toggle_category_visibility_btn', function () {
  if (!isset($_POST['term_id'], $_POST['category_visibility_nonce'])) {
    wp_send_json_error('不正なリクエストです。');
  }

  // nonceチェック
  if (!wp_verify_nonce($_POST['category_visibility_nonce'], 'category_visibility_action')) {
    wp_send_json_error('セキュリティチェックに失敗しました。');
  }

  // 権限チェック
  if (!current_user_can('manage_categories')) {
    wp_send_json_error('権限がありません。');
  }

  // リクエストからカテゴリーIDを取得
  $term_id = absint($_POST['term_id']);

  // 対象カテゴリーの情報を取得
  $term = get_term($term_id, 'category');
  if (!$term || is_wp_error($term)) {
    wp_send_json_error('カテゴリーが見つかりません。');
  }

  // 現在の非表示フラグを取得
  $current_hidden = get_term_meta($term_id, 'my_hide_category_cloud', true);

  if ($current_hidden === '1') {
    delete_term_meta($term_id, 'my_hide_category_cloud');
    $new_hidden = '';
  } else {
    update_term_meta($term_id, 'my_hide_category_cloud', '1');
    $new_hidden = '1';
  }

  wp_send_json_success(['is_hidden' => $new_hidden]);
});


/**
 * カテゴリーウィジェットのクエリから非表示カテゴリーを除外
 *
 * @param array $args カテゴリーウィジェットのクエリ設定
 * @return array 非表示カテゴリーを除外したクエリ設定
 */
if (!function_exists('my_exclude_hidden_category_cloud_ids')):
function my_exclude_hidden_category_cloud_ids($args) {
  // 非表示カテゴリーとその子孫のIDを取得
  $hidden_ids = my_get_hidden_category_cloud_ids();

  // 除外対象がない場合は元の設定を返して終了
  if (empty($hidden_ids)) {
    return $args;
  }

  // 既存の除外カテゴリーIDを取得
  $existing_ids = isset($args['exclude'])
    ? wp_parse_id_list($args['exclude'])
    : [];

  // 既存の除外設定に非表示カテゴリーのIDを追加して置換
  $args['exclude'] = implode(',', array_unique(array_merge($existing_ids, $hidden_ids)));

  return $args;
}
endif;


// カテゴリーのクエリを変更
add_filter('widget_categories_args', 'my_exclude_hidden_category_cloud_ids');
add_filter('widget_categories_dropdown_args', 'my_exclude_hidden_category_cloud_ids');

さいごに

今回紹介した方法を使えば、不要なカテゴリーを非表示にして、WordPressのカテゴリー一覧を思い通りにコントロールできるようになります。
管理画面のカテゴリー一覧からワンクリックで表示・非表示を切り替えられるため、運用の手間もかかりません。
カテゴリーが増えて一覧が見づらくなっている方や、親子関係を維持しながら表示するカテゴリーを整理したい方は、ぜひ導入してみてください。

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