メニュー画面でカスタム投稿とタクソノミーをセットにして色分けする方法

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

はじめに

メニュー画面

外観→メニューを開いたとき、左側にある「メニュー項目を追加」のアコーディオンパネルがごちゃごちゃしていて使いづらいと感じたことはありませんか?
デフォルトの仕様では、項目が増えれば増えるほど目的のページを探すのが難しくなります。

そこで、関連する項目同士を自動でグループ化して並べ替え、色分けして整理します。

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

目的

WordPress標準のメニュー編集画面(外観→メニュー)では、項目が増えるにつれて主に3つの課題が生じます。

  1. 関連する項目が上下に離れて表示されてしまう
    標準仕様では「投稿タイプが先、タクソノミー(カテゴリーなど)が後」という順序で処理されます。
    そのため、カスタム投稿「レッスン」が上のほうにあるのに、紐づく「プログラム」は一番下までスクロールしないと見つからないという、まとまりのない並び順になってしまいます。
  1. 標準機能と拡張機能が混ざり、画面が混沌としてくる
    固定ページや通常の投稿といった「よく使う標準機能」のすぐ下に、後から追加したカスタム投稿タイプがそのまま割り込んで並びます。
    そのため、運用歴が長くなり項目が増えるほど区別がつかなくなります。
  1. すべて同じデザインで視認性が悪い
    どれだけ項目が増えても全て同じグレー背景と黒文字のアコーディオンで並ぶため、視覚的な区切りがなく、パッと見で目的のブロックを判別できません。

今回紹介するコードを導入することで、これらの課題を以下のようにスマートに解決できます。

  1. 投稿タイプとタクソノミーが「1セット」で隣り合う
    システムが自動判別し、カスタム投稿と紐づくタクソノミーをすぐ後ろに密着させて配置します。
    常に隣り合わせの1セットとして並ぶため、画面内を上下にスクロールして探し回る必要がなくなります。
  1. 標準機能と拡張機能が完全に分離される
    固定ページや通常の投稿、カテゴリーといった最も頻繁に使う標準項目が常に最上部に固定されます。
    後から追加した項目はその下に配置されるため、運用の基本となる動線が常にクリアに保たれます。

完成イメージ

実装手順

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

add_action('admin_head-nav-menus.php', function () {
  global $wp_meta_boxes;

  // メニュー項目なしは処理対象外
  if (empty($wp_meta_boxes['nav-menus']['side']['default'])) {
    return;
  }

  // 登録済みのメニュー用メタボックスを取得
  $boxes = $wp_meta_boxes['nav-menus']['side']['default'];

  // 画面上部に固定するWordPress標準の項目IDを設定
  $standard_ids = [
    'add-post-type-page', // 固定ページ
    'add-post-type-post', // 投稿
    'add-custom-links',   // カスタムリンク
    'add-category',       // カテゴリー
    'add-post_tag',       // タグ
  ];

  // メタボックスの分類用配列を設定
  $top_boxes   = [];
  $custom_sets = [];
  $other_boxes = [];

  // WordPress標準の項目を抽出
  foreach ($standard_ids as $id) {
    if (isset($boxes[$id])) {
      $top_boxes[$id] = $boxes[$id];
      unset($boxes[$id]);
    }
  }

  // カスタムセット用のカラーパレットを設定
  $hex_colors = [
    '#8bc34a',
    '#00bcd4',
    '#ffc107',
  ];

  $css_rules   = [];
  $color_index = 0;

  // 有効なカスタム投稿タイプを取得
  $post_types = get_post_types([
    'public'   => true,
    '_builtin' => false,
  ], 'objects');

  // カスタム投稿タイプごとに処理
  foreach ($post_types as $post_type_name => $post_type_obj) {
    $pt_id = 'add-post-type-' . $post_type_name;

    // カスタム投稿タイプのメタボックスなしは処理対象外
    if (isset($boxes[$pt_id])) {
      // カスタム投稿タイプのメタボックスをセットに登録
      $custom_sets[$pt_id] = $boxes[$pt_id];
      unset($boxes[$pt_id]);

      // 使用するカラーを設定
      $current_hex   = $hex_colors[$color_index % count($hex_colors)];
      $css_selectors = [];

      // カスタム投稿タイプのタイトルセレクターを設定
      $css_selectors[] = "#side-sortables .{$pt_id} .accordion-section-title";

      // カスタム投稿タイプに紐づくタクソノミーを取得
      $taxonomies = get_object_taxonomies($post_type_name, 'objects');

      // タクソノミーごとに処理
      foreach ($taxonomies as $tax_name => $tax_obj) {
        // メニュー画面に表示可能なタクソノミーを取得
        if ($tax_obj->show_in_nav_menus) {
          $tax_id = 'add-' . $tax_name;

          // タクソノミーのメタボックスなしは処理対象外
          if (isset($boxes[$tax_id])) {
            // タクソノミーのメタボックスをセットに登録
            $custom_sets[$tax_id] = $boxes[$tax_id];
            unset($boxes[$tax_id]);

            // タクソノミーのタイトルセレクターを追加
            $css_selectors[] = "#side-sortables .{$tax_id} .accordion-section-title";
          }
        }
      }

      // セレクターを結合
      $selectors_str = implode(', ', $css_selectors);

      // セットのCSSルールを設定
      $css_rules[]   = "{$selectors_str} { background: color-mix(in srgb, {$current_hex} 5%, transparent) !important; color: {$current_hex} !important; }";
      $css_rules[]   = "{$selectors_str} button { color: {$current_hex} !important; }";

      $color_index++;
    }
  }

  // 標準・カスタムセット・その他の順にメタボックスを設定
  $other_boxes = $boxes;
  $wp_meta_boxes['nav-menus']['side']['default'] = array_merge($top_boxes, $custom_sets, $other_boxes);

  // CSSを出力
  if (!empty($css_rules)) {
    echo '<style>' . "\n" . implode("\n", $css_rules) . "\n" . '</style>' . "\n";
  }
});

さいごに

今回紹介した方法を使えば、カスタム投稿タイプとそれに紐づくタクソノミーが常にセットで並び、カラーで視覚的にグループ分けされるため、サイトの規模が大きくなっても迷うことがありません。
クライアントワークでの納品時に、管理画面の親切さをアピールするためのカスタマイズとしても非常に強力です。

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