はじめてのプラグイン
管理画面に処理を差し込むプラグインを、1つ作ってみます。作業時間は 30 分ほどです。
実験的機能
管理画面の JavaScript 拡張は、Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。変更される範囲と公開 API の扱いは、管理画面の JavaScript 拡張 の注記を確認してください。
このページで作るもの
- 画像をアップロードする前に確認ダイアログを表示する
- メディア詳細画面の alt 入力欄の下に、独自のボタンを追加する
ビルド環境は必要ありません。テキストエディタと、a-blog cms が動く環境だけ用意してください。
1. JavaScript ファイルを作る
a-blog cms を設置したディレクトリに extension/acms/assets/ フォルダを作り、その中に my-plugin.js を作成します。
/extension/acms/assets/my-plugin.js中身は次のとおりです。
ACMS.adminReady(() => {
ACMS.plugins.register('my-plugin', {
version: '1.0.0',
setup(ctx) {
// アップロードする直前に確認ダイアログを出す
ctx.events.on('media.upload.before', async (payload, gate) => {
const ok = await ACMS.Library.dialog.confirm(`${payload.files.length} 件の画像をアップロードします。よろしいですか?`);
if (!ok) {
gate.cancel(); // 呼ぶとアップロードを中止する
}
});
},
});
});ACMS.plugins.register() にプラグイン名と設定を渡すだけです。setup(ctx) の中に、やりたいことを書いていきます。ACMS.adminReady() は、管理画面の JavaScript の準備が終わってから中の処理を呼びます。すでに終わっていれば、すぐに呼びます。
2. 管理画面に読み込む
extension/acms/Hook.php を開き、afterBuild() メソッドに次の内容を追加します。Hook.php は a-blog cms に最初から入っています。
public function afterBuild(&$res)
{
\Acms\Services\Facades\Asset::script('my-plugin', '/' . DIR_OFFSET . 'extension/acms/assets/my-plugin.js', [
'position' => 'body_end',
'attrs' => ['type' => 'module'],
]);
}- 第1引数の
'my-plugin'は、この JS を識別する名前(ハンドル)です。他と重複しない名前にします。 - 第2引数は JS ファイルのパスです。
DIR_OFFSETは a-blog cms を設置したディレクトリを表す定数で、ドキュメントルート直下に設置している場合は空文字になります。 positionは読み込み位置です。body_endを指定します。'attrs' => ['type' => 'module']を指定します。type="module"のスクリプトは、ページの解析が終わってから記述順に実行されるため、プラグインを読み込む順序が決まります。- 管理画面の JavaScript は非同期で読み込まれるため、プラグインのほうが先に実行されることがあります。
ACMS.adminReady()で包むのはそのためです。 包まずにACMS.pluginsを呼ぶと、ACMS.plugins is undefinedのエラーになることがあります。
読み込み方法の詳細は アセット API(JS / CSS の登録) を参照してください。
3. 動作を確認する
- 管理画面にログインします。
- 「メディア」を開き、画像をアップロードします。
- ファイルを選んだ直後に確認ダイアログが表示されます。「キャンセル」を選ぶとアップロードされません。
うまく動かないときは
ブラウザの開発者ツールを開き、次の3点を確認してください。
- コンソールにエラーが出ていないか。
ACMS.plugins is undefinedと出る場合は、ACMS.adminReady()で包まれていません。 - JS ファイルが読み込まれているか。 ネットワークタブに
my-plugin.jsが出ているか確認します。404 の場合はパスを見直してください。 - 管理画面で確認しているか。 この拡張は管理画面(ログイン後の画面)で動作します。サイトの表示側では動きません。
4. コードの読み方
ここまでで使った4つの要素を確認します。
ACMS.adminReady(() => { // (1) 管理画面の準備が終わるのを待つ
ACMS.plugins.register('my-plugin', { // (2) プラグインを登録する
setup(ctx) { // (3) 登録時に一度だけ呼ばれる
ctx.events.on('media.upload.before', handler); // (4) イベントを購読する
},
});
});ACMS.adminReady(関数)— 管理画面の JavaScript の準備が終わってから、関数を呼びます。ACMS.plugins.register(名前, 設定)— プラグインを登録します。名前は管理画面全体で一意にします。setup(ctx)— 登録した直後に呼ばれます。イベントの購読や UI の差し込みは、すべてこの中で行います。ctx.events.on(イベント名, 処理)— イベントを購読します。処理は(payload, gate)を受け取ります。操作の直前に呼ばれるイベント(ゲート)では、gate.cancel()を呼ぶと操作を中止できます。return falseでは中止できません。
イベント名は {機能}.{操作}.{タイミング} の形です。media.upload.before は「メディアのアップロードの直前」という意味になります。ゲートかどうかはイベントごとに決まっていて、イベント一覧 の種別で確認できます。
5. ボタンを追加する
もう1つ、UI の差し込みを試します。my-plugin.js の setup(ctx) の中に追加してください。
// メディア詳細画面の alt 入力欄の下にボタンを追加する
ctx.ui.fill('media.edit-modal.field.alt', (el) => {
const button = document.createElement('button');
button.type = 'button';
button.className = 'acms-admin-btn';
button.textContent = 'ファイル名から入れる';
el.append(button);
return () => button.remove();
});管理画面のメディア一覧から画像をクリックし、alt 入力欄の下にボタンが表示されることを確認してください。
ctx.ui.fill(差し込み位置の名前, 処理)で UI を追加します。- 関数に渡される
elは、差し込み位置に用意された空の要素です。この中に自由に DOM を追加できます。 - 戻り値の関数は、画面が閉じられたときに呼ばれます(後片付け用)。
js/config.jsのmediaShowAltAndCaptionOnModalをfalseにしている場合は、alt 入力欄ごと非表示になり、ボタンも表示されません。
差し込める位置の一覧は UI の差し込み(Slot / Fill) にあります。
完成したコード
ACMS.adminReady(() => {
ACMS.plugins.register('my-plugin', {
version: '1.0.0',
setup(ctx) {
ctx.events.on('media.upload.before', async (payload, gate) => {
const ok = await ACMS.Library.dialog.confirm(`${payload.files.length} 件の画像をアップロードします。よろしいですか?`);
if (!ok) {
gate.cancel();
}
});
ctx.ui.fill('media.edit-modal.field.alt', (el) => {
const button = document.createElement('button');
button.type = 'button';
button.className = 'acms-admin-btn';
button.textContent = 'ファイル名から入れる';
el.append(button);
return () => button.remove();
});
},
});
});次のステップ
- 目的別の手順 → 一覧画面にアクションを追加する / アップロード前にチェックを入れる
- 使える API を一通り知る → プラグイン API
- 購読できるイベントを探す → イベント一覧
- React や TypeScript で書く → 開発環境と型定義