ウィジェット画面のウィジェットエリアの並び順を変更する方法

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

はじめに

外観→ウィジェットを開くと、登録されたウィジェットエリア(サイドバーなど)が一覧で表示されます。
しかし、この並び順はテーマやプラグインで登録された順序のまま固定されており、管理画面での作業効率が悪く感じることがあります。

そこで、頻繁に操作するウィジェットエリアを先頭に表示できれば、目的の設定にすぐにアクセスできるようになります。
このように、管理者がよく利用するエリアを先頭に配置することで、ウィジェット編集の操作性を大幅に向上させることができます。

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

完成イメージ

実装手順

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

add_action('widgets_init', function () {
  global $wp_registered_sidebars;

  // 先頭に配置するウィジェットエリアIDを指定
  $new_order = [
    '404-page',
    'sidebar-scroll',
    'footer-right',
  ];

  $reordered_sidebars = [];

  foreach ($new_order as $id) {
    if (isset($wp_registered_sidebars[$id])) {
      $reordered_sidebars[$id] = $wp_registered_sidebars[$id];
      unset($wp_registered_sidebars[$id]);
    }
  }

  // 残りのウィジェットエリアを後ろへ追加
  $wp_registered_sidebars = array_merge(
    $reordered_sidebars,
    $wp_registered_sidebars
  );
}, 999);

拡張:ドラッグ&ドロップでウィジェットエリアの表示順を変更する方法

先ほど紹介したコードでは、functions.php内の配列を書き換えることでウィジェットエリアの並び順を固定していました。
しかし、管理者がその都度コードを編集するのは手間がかかります。

そこで、管理画面からドラッグ&ドロップで順序を変更し、その設定を保存できるようにする方法もあります。
この方法なら、ウィジェットエリアを視覚的に並べ替え、保存ボタンで設定を保持し、必要に応じてリセットも可能です。

完成イメージ

実装手順

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

// ウィジェットページに追加
add_action('load-widgets.php', function () {
  global $wp_registered_sidebars;

  $screen = get_current_screen();

  if (!$screen || $screen->id !== 'widgets') {
    return;
  }

  // 使用停止中ウィジェットを除外
  $active_sidebars = array_filter($wp_registered_sidebars, function ($sidebar) {
    return $sidebar['id'] !== 'wp_inactive_widgets';
  });

  // 保存済み順序を取得
  $saved_order = get_option('my_sidebar_order', array_keys($active_sidebars));

  // 並び替え後の配列を作成
  $sidebars = [];

  foreach ($saved_order as $id) {
    if (isset($active_sidebars[$id])) {
      $sidebars[$id] = $active_sidebars[$id];
    }
  }

  // 保存順序にないエリアを追加
  foreach ($active_sidebars as $id => $sidebar) {
    if (!isset($sidebars[$id])) {
      $sidebars[$id] = $sidebar;
    }
  }

  // ヘルプタブのリスト項目を作成
  $list_items = '';

  foreach ($sidebars as $id => $sidebar) {
    $list_items .= '<li class="ui-state-default" data-id="' . esc_attr($id) . '"><span class="grip-icon">⋮⋮</span>' . esc_html($sidebar['name']) . '</li>';
  }

  $nonce_field = wp_nonce_field('sidebar_order_action', 'sidebar_order_nonce', true, false);

  ob_start();
  ?>
  <div id="sidebar-order-settings-wrap">
    <form method="post" id="sidebar-order-form">
      <?= $nonce_field; ?>
      <p style="margin-bottom: 10px; color: #646970;">ドラッグ&ドロップでウィジェットエリアの表示順を変更できます。</p>
      <ul id="sidebar-order-sortable"><?= $list_items; ?></ul>
      <div class="sidebar-order-action-area">
        <button type="submit" name="save_sidebar_order" class="button button-primary">保存</button>
        <button type="submit" name="reset_sidebar_order" class="button button-link-delete">初期にリセット</button>
      </div>
    </form>
  </div>
  <?php
  $content = ob_get_clean();

  $screen->add_help_tab([
    'id'       => 'sidebar-order-tab',
    'title'    => 'ウィジェットエリア順序変更',
    'content'  => $content,
    'priority' => 999,
  ]);
});


// 設定データの更新処理
add_action('load-widgets.php', function () {
  if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    return;
  }

  // nonceチェック
  if (!isset($_POST['sidebar_order_nonce']) || !wp_verify_nonce($_POST['sidebar_order_nonce'], 'sidebar_order_action')) {
    return;
  }

  // 保存処理
  if (isset($_POST['save_sidebar_order'])) {
    $order = isset($_POST['sidebar_order']) ? array_map('sanitize_text_field', $_POST['sidebar_order']) : [];

    update_option('my_sidebar_order', $order);

    set_transient('my_admin_notice', '設定を保存しました。', 30);

    wp_safe_redirect(admin_url('widgets.php'));
    exit;
  }

  // リセット処理
  if (isset($_POST['reset_sidebar_order'])) {
    delete_option('my_sidebar_order');

    set_transient('my_admin_notice', '初期状態にリセットしました。', 30);

    wp_safe_redirect(admin_url('widgets.php'));
    exit;
  }
});


// 対象の処理を実行
add_action('widgets_init', function () {
  global $wp_registered_sidebars;

  if (!is_admin()) {
    return;
  }

  $saved_order = get_option('my_sidebar_order', []);

  if (!$saved_order) {
    return;
  }

  $reordered = [];

  foreach ($saved_order as $id) {
    if (isset($wp_registered_sidebars[$id])) {
      $reordered[$id] = $wp_registered_sidebars[$id];
      unset($wp_registered_sidebars[$id]);
    }
  }

  $wp_registered_sidebars = array_merge($reordered, $wp_registered_sidebars);
}, 999);


// 通知メッセージを出力
add_action('admin_notices', function () {
  if ($notice = get_transient('my_admin_notice')) {
    echo '<div class="notice notice-success is-dismissible"><p>' . esc_html($notice) . '</p></div>';
    delete_transient('my_admin_notice');
  }
});


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

  ob_start();
  ?>
  #sidebar-order-sortable {
    background-color: #fff;
    border: 1px solid #ccd0d4;
    border-radius: 4px;
    max-height: 300px;
    max-width: 400px;
    margin: 10px 0;
    overflow-y: auto;
    padding: 10px;
  }

  #sidebar-order-sortable li {
    align-items: center;
    background-color: #f6f7f7;
    border: 1px solid #dcdcde;
    border-radius: 3px;
    cursor: move;
    display: flex;
    margin: 0 0 5px;
    padding: 8px 12px;
  }

  #sidebar-order-sortable li .grip-icon {
    color: #8c8f94;
    letter-spacing: -1px;
    margin-right: 8px;
  }

  .sidebar-order-action-area {
    align-items: center;
    display: flex;
    gap: 10px;
    margin-top: 15px;
  }

  #sidebar-order-sortable .ui-state-highlight {
    background-color: #f0f6fc;
    border: 1px dashed #2271b1;
    border-radius: 3px;
    height: 36px;
    margin-bottom: 5px;
  }
  <?php
  wp_add_inline_style('wp-admin', ob_get_clean());

  ob_start();
  ?>
  jQuery(function ($) {
    var $sidebarList = $('#sidebar-order-sortable');

    if (!$sidebarList.length) {
      return;
    }

    // jQuery UI Sortableを有効化
    $sidebarList.sortable({
      placeholder: 'ui-state-highlight',
      forcePlaceholderSize: true
    }).disableSelection();

    // フォーム送信時の処理
    $('#sidebar-order-form').on('submit', function (e) {
      if ($(document.activeElement).attr('name') === 'reset_sidebar_order') {
        if (!confirm('ウィジェットエリアの並び順をデフォルトに戻しますか?')) {
          e.preventDefault();
          return;
        }
      }

      // 既存の隠し入力フィールドを削除
      $sidebarList.find('input.sidebar-order-hidden').remove();

      // 現在の並び順を隠しフィールドに設定
      $sidebarList.find('li').each(function () {
        $('<input>').attr({
          type: 'hidden',
          name: 'sidebar_order[]',
          value: $(this).data('id'),
          class: 'sidebar-order-hidden'
        }).appendTo('#sidebar-order-form');
      });
    });
  });
  <?php
  wp_add_inline_script('admin-widgets', ob_get_clean());
});

さいごに

今回紹介した方法を使えば、管理画面で頻繁に利用するウィジェットエリアを先頭に配置でき、編集作業を効率的に進められます。
特に、更新頻度の高いキャンペーンページのフッターや、スクロール追従のサイドバーエリアなどを扱う場合に効果的です。

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