カスタム投稿タイプ lms_live_seminar の編集画面。register_post_type() で 'supports' => ['title'] のみ有効化し、全フィールドをカスタムメタボックス(add_meta_box())で構成する。メタボックスは「基本情報」「開催情報」「参加者管理」を 'normal'(メインカラム)、「公開」「開催ステータス」「カテゴリ」「開催統計」を 'side'(サイドカラム)に配置。保存処理は save_post_lms_live_seminar フックで実装。Zoom URLからのミーティングID自動抽出は正規表現 /zoom\.us\/j\/(\d+)/ で処理。参加者管理はカスタムテーブルのデータを参照・更新するAJAX処理(管理画面内のみ)で実装。
編集画面アクセス: manage_lms_content 権限チェック。参加者一覧の閲覧・キャンセル処理は同権限で許可。参加者への一斉メール送信は manage_lms_members 権限も必要。ゴミ箱移動は manage_lms_content、完全削除は管理者(manage_options)のみ。開催統計は全権限者に読み取り専用で表示。
投稿テーブル: 管理UI層はカスタム投稿タイプ lms_live_seminar(正準データは lms_contents・content_type='live' に同期。開催情報は live_start_at/live_end_at/registration_deadline_at/event_status カラム)。Zoom連携情報(ミーティングID・参加URL・パスコード)は別テーブル lms_content_zoom_secrets に暗号化保存(AES-256-GCM)。申込データはカスタムテーブル lms_seminar_registrations(registration_id / content_id / account_id / corp_id / site_id / status〔registered/cancelled〕/ registered_at / cancelled_at / note)に格納。申込時の任意メモは lms_seminar_registrations.note(自由記述)に保存し、参加者一覧の「申込メモ」列に表示する。
参加者管理メタボックス内の一括操作で「キャンセル処理」を実装。処理はAJAX(wp_ajax_lms_update_participant)で非同期実行し、Nonce検証後に lms_seminar_registrations テーブルを更新。参加者個別の「キャンセル」は確認ダイアログを表示後に処理。キャンセル時はSendGridで参加者へキャンセル確認メールを自動送信。申込状況メタボックスから申込の手動追加(受講主体アカウントを指定して代理登録・重複申込はUNIQUE制約で防止)と、申込者への一斉メール送信(SendGrid・申込済みのみ宛先・手動送信のみ)が可能。Excel出力は設けない。
編集画面のメタボックス表示/非表示はWP標準の Screen Options で制御。「開催統計」メタボックスは開催終了後のゼミでのみデフォルト表示(ステータス判定で切替)。メタボックスの折りたたみ状態はユーザーメタ closedpostboxes_live_seminar に保存される。「参加者管理」メタボックスはデフォルト展開状態を維持し、折りたたみを無効化することも検討。ページあたり表示件数は参加者テーブル部分のみ対応し、デフォルト20件。
全フォーム送信時に wp_nonce_field('lms_save_live_seminar', 'lms_live_seminar_nonce') でNonce検証。Zoom URL・パスコードは esc_url() / sanitize_text_field() でサニタイズ。参加者管理のAJAX処理には個別Nonce(wp_create_nonce('lms_participant_action'))を設定。参加者テーブルへのアクセスは $wpdb->prepare() でSQLインジェクション対策を徹底。参加者統計はトランジェントAPI(set_transient('lms_seminar_stats_' . $post_id, $stats, HOUR_IN_SECONDS))でキャッシュし、参加者の申込・キャンセル時にキャッシュを削除(delete_transient())。Zoom URL・パスコードは機密情報として扱い、REST APIエンドポイントでは権限チェック後に限定公開。