複数ユーザー運営時に、ドラッグ&ドロップでユーザーロールを割り当てる方法

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

はじめに

管理画面でユーザーのロールをドラッグ&ドロップで割り当てる機能を実装します。

jQuery UIを用いたドラッグ&ドロップ機能を使うことで、直感的にユーザーの役割を変更できるインターフェースを作成できます。

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

完成イメージ

実装手順

プラグインの形式で実装します。

以下の手順で実装します。

  • my-user-role-assign
    • user-role-assign.php
    • assets
      • css
        • admin.css
      • js
        • admin.js
  • ラベル
    PHPを追加

    以下のコードuser-role-assign.phpに追加します。

    <?php
    /**
     * Plugin Name: My User Role Assign
     * Description: 管理画面でユーザーをロールにドラッグ&ドロップで割り当てます。
     * Version: 1.0.0
     * Author: CHU-YA
     */
    
    if (!defined('ABSPATH')) {
      exit;
    }
    
    
    /**
     * 管理画面ページを出力
     *
     * @return void
     */
    if (!function_exists('render_user_role_assign')):
    function render_user_role_assign() {
      $roles = wp_roles()->roles;
      unset($roles['administrator']);
    
      $users = get_users([
        'role__not_in' => ['administrator'],
      ]);
    
      $role_names_ja = [
        'editor'      => '編集者',
        'author'      => '投稿者',
        'contributor' => '寄稿者',
        'subscriber'  => '購読者',
      ];
    
      ?>
      <div class="wrap">
        <h1>ユーザーロール割り当て</h1>
    
        <form method="post" action="<?= esc_url(admin_url('admin-post.php')); ?>">
    
          <?php wp_nonce_field('user_role_assign_action', 'user_role_assign_nonce'); ?>
    
          <input type="hidden" name="action" value="user_role_assign_save">
          <input type="hidden" name="user_role_assign_data" id="user-role-assign-data">
    
          <div class="user-role-assign__container">
    
            <?php foreach ($roles as $role_key => $role): ?>
    
              <?php $role_name = $role_names_ja[$role_key] ?? $role['name']; ?>
    
              <div class="user-role-assign__role">
    
                <h2><?= esc_html($role_name); ?></h2>
    
                <div class="user-role-assign__dropzone" data-role="<?= esc_attr($role_key); ?>">
    
                  <?php foreach ($users as $user): ?>
    
                    <?php if (($user->roles[0] ?? '') !== $role_key) {
                      continue;
                    } ?>
    
                    <div class="user-role-assign__item" draggable="true" data-user-id="<?= esc_attr($user->ID); ?>">
    
                      <div class="user-role-assign__avatar">
                        <?= get_avatar($user->ID, 32); ?>
                      </div>
    
                      <div class="user-role-assign__info">
                        <strong><?= esc_html($user->display_name); ?></strong>
                      </div>
    
                    </div>
    
                  <?php endforeach; ?>
    
                </div>
    
              </div>
    
            <?php endforeach; ?>
    
          </div>
    
          <p>
            <button type="submit" class="button button-primary">変更を保存</button>
          </p>
    
        </form>
      </div>
      <?php
    }
    endif;
    
    
    // 管理画面メニューを追加
    add_action('admin_menu', function () {
      add_users_page(
        'ユーザーロール割り当て',
        'ロール割り当て',
        'manage_options',
        'user-role-assign',
        'render_user_role_assign'
      );
    });
    
    
    // 管理画面JS・CSS読み込み
    add_action('admin_enqueue_scripts', function ($hook_suffix) {
      if ($hook_suffix !== 'users_page_user-role-assign') {
        return;
      }
    
      wp_enqueue_script('jquery-ui-draggable');
      wp_enqueue_script('jquery-ui-droppable');
    
      wp_enqueue_style('user-role-assign', plugin_dir_url(__FILE__) . 'assets/css/admin.css');
      wp_enqueue_script('user-role-assign', plugin_dir_url(__FILE__) . 'assets/js/admin.js', ['jquery', 'jquery-ui-draggable', 'jquery-ui-droppable'], null, true);
    });
    
    
    // ロールを保存
    add_action('admin_post_user_role_assign_save', function () {
    
      // nonceチェック
      if (!isset($_POST['user_role_assign_nonce']) || !wp_verify_nonce($_POST['user_role_assign_nonce'], 'user_role_assign_action')) {
        wp_die('不正な操作です。');
      }
    
      // 権限チェック
      if (!current_user_can('manage_options')) {
        wp_die('権限がありません。');
      }
    
      if (empty($_POST['user_role_assign_data'])) {
        wp_die('データがありません。');
      }
    
      $data = json_decode(stripslashes($_POST['user_role_assign_data']), true);
    
      if (!is_array($data)) {
        wp_die('データ形式が不正です。');
      }
    
      foreach ($data as $role => $user_ids) {
    
        foreach ((array) $user_ids as $uid) {
    
          $uid = intval($uid);
          $user = get_user_by('ID', $uid);
    
          if (
            $user &&
            ($user->roles[0] ?? '') !== $role &&
            $role !== 'administrator'
          ) {
            $user->set_role($role);
          }
        }
      }
    
      wp_redirect(admin_url('users.php?page=user-role-assign&updated=1'));
      exit;
    });
    
    
    // 通知メッセージを出力
    add_action('admin_notices', function () {
      if (isset($_GET['updated']) && $_GET['updated'] === '1') {
        echo '<div class="notice notice-success is-dismissible"><p>設定を保存しました。</p></div>';
      }
    });
  • ラベル
    JavaScriptを追加

    以下のコードをadmin.jsに追加します。

    jQuery(function ($) {
      // ユーザーアイテムをドラッグ可能に設定
      $('.user-role-assign__item').draggable({
        helper: 'clone',
        revert: 'invalid',
    
        start: function () {
          // ドラッグ中のユーザーアイテムにクラスを追加
          $(this).addClass('user-role-assign__item--dragging');
        },
    
        stop: function () {
          // ドラッグ終了時にクラスを削除
          $(this).removeClass('user-role-assign__item--dragging');
        }
      });
    
    
      // ロールごとのドロップゾーンを設定
      $('.user-role-assign__dropzone').droppable({
        accept: '.user-role-assign__item',
        hoverClass: 'user-role-assign__dropzone--hover',
    
        drop: function (event, ui) {
          const $dropZone = $(this);
          const $dragItem = $(ui.draggable);
    
          // ドロップ先に同じユーザーが存在しない場合のみ追加
          if ($dropZone.find('[data-user-id="' + $dragItem.data('user-id') + '"]').length === 0) {
            // ユーザーアイテムをドロップ先に移動
            $dragItem.detach().appendTo($dropZone);
          }
        }
      });
    
    
      // フォーム送信時にロールごとのユーザーID配列を構築
      $('form').on('submit', function () {
        const result = {};
    
        // 全てのドロップゾーンからユーザーIDを取得
        $('.user-role-assign__dropzone').each(function () {
          const roleKey = $(this).data('role');
    
          // ドロップゾーン内のユーザーIDを配列として取得
          const userIds = $(this)
            .find('.user-role-assign__item')
            .map(function () {
              return $(this).data('user-id');
            })
            .get();
    
          // ロールごとにユーザーID配列を格納
          result[roleKey] = userIds;
        });
    
        // ユーザーID配列をJSON形式で隠しフィールドに設定
        $('#user-role-assign-data').val(JSON.stringify(result));
      });
    });
  • ラベル
    CSSを追加

    以下のコードをadmin.cssに追加します。

    .user-role-assign__container {
      display: flex;
      gap: 2em;
    }
    
    .user-role-assign__role {
      background-color: #fff;
      border: 1px solid #ccc;
      border-radius: 6px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
      flex: 1;
      min-height: 400px;
      padding: 1em;
    }
    
    .user-role-assign__role h2 {
      color: #0073aa;
      font-size: 18px;
      margin-bottom: 0.5em;
    }
    
    .user-role-assign__dropzone {
      background-color: #f9f9f9;
      border: 2px dashed #bbb;
      border-radius: 6px;
      max-height: 350px;
      min-height: 100px;
      overflow-y: auto;
      padding: 8px;
    }
    
    .user-role-assign__dropzone--hover {
      background-color: #f0f8ff;
      border-color: #0073aa;
    }
    
    .user-role-assign__item {
      align-items: center;
      background-color: #fafafa;
      border: 1px solid #ddd;
      border-radius: 4px;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
      cursor: move;
      display: flex;
      gap: 8px;
      margin: 6px 0;
      padding: 8px;
      transition:
        background-color 0.15s ease,
        box-shadow 0.15s ease;
      user-select: none;
    }
    
    .user-role-assign__item:hover {
      background-color: #f0f8ff;
      box-shadow: 0 0 8px rgba(21, 156, 228, 0.6);
    }
    
    .user-role-assign__item--dragging {
      opacity: 0.5;
    }
    
    .user-role-assign__avatar img {
      border-radius: 50%;
      height: 32px;
      width: 32px;
    }
    
    .user-role-assign__info strong {
      font-weight: 600;
    }

さいごに

今回紹介した方法を使えば、管理画面からドラッグ&ドロップによってユーザーのロールを簡単かつ視覚的に割り当てることができます。
管理者が多くのユーザーを一括で管理したい場面や、直感的な操作でロールを変更したい場合に非常に有効です。
また、jQuery UIを使ったこの仕組みは、WordPressの拡張性を活かした柔軟なカスタマイズ例としても参考になります。

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