プラグイン API
管理画面のプラグインを登録する ACMS.plugins と、setup(ctx) で受け取る ctx のリファレンスです。
実験的機能
この API は、Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。引数や ctx の構成はマイナーバージョンアップで変更される可能性があります。管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。
このドキュメントに掲載している API を公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。PHP 側のフック処理・テンプレート挿入・アセット API は、この実験的機能の対象外です(従来どおりの仕様として提供しています)。
はじめてプラグインを書く場合は はじめてのプラグイン から読んでください。
ACMS.plugins
register(name, definition)
プラグインを登録します。
ACMS.adminReady(() => {
ACMS.plugins.register('my-plugin', {
version: '1.0.0',
setup(ctx) {
// ここでイベント購読・UI 差し込み・機能登録を行う
},
});
});| 引数 | 型 | 説明 |
|---|---|---|
name | string | プラグイン名。管理画面全体で一意にします。同じ名前で2回登録するとエラーになります。 |
definition.version | string(省略可) | プラグインのバージョン。ACMS.plugins.get() / getAll() の戻り値に入ります。 |
definition.setup | function | 登録直後に呼ばれる関数。ctx を受け取ります。 |
register() は、ACMS.adminReady() の中で呼びます(登録するタイミング を参照)。
プラグイン名は、他のプラグインと衝突しないよう配布名やベンダー名を含めた形(acme-media-tools など)を推奨します。
unregister(name)
プラグインを登録解除します。setup(ctx) の中で行ったイベント購読・機能登録・UI 差し込みはすべて自動的に解除されます。個別に後片付けを書く必要はありません。
ACMS.plugins.unregister('my-plugin'); // 登録されていた場合 true を返すget(name) / getAll()
登録済みのプラグインを取得します。デバッグ用です。
ACMS.plugins.getAll();
// [{ name: 'my-plugin', version: '1.0.0', registrations: [{ kind: 'event', key: 'media.upload.before' }, ...] }]registrations には、そのプラグインが何を登録したかが登録順に入ります。イベント名や Slot 名の書き間違いを調べるときに使えます。
withFillProps(Component)
Slot が渡す値を React コンポーネントで受け取るためのラッパーです。使い方は UI の差し込み(Slot / Fill) を参照してください。
setup(ctx) で使える API
ctx は次のプロパティを持ちます。
| プロパティ | 用途 | 詳細 |
|---|---|---|
ctx.name | 自分のプラグイン名(読み取り専用) | — |
ctx.events.on(type, handler) | イベントを購読する | イベント |
ctx.ui.fill(slotName, entry) | UI を差し込む | Slot / Fill |
ctx.unitEditor.registerUnitDefinition(name, def) | ユニットの種類を追加する | オリジナルユニット |
ctx.blockEditor.registerBlockDefinition(name, factory) | ブロックの種類を追加する | オリジナルブロック |
ctx.blockEditor.registerExtension(name, factory) | ブロックエディターに要素・機能を追加する | オリジナルブロック |
ctx.dataview.registerColumnType(name, type) | 一覧画面のカラム型を追加する | レジストリ |
ctx.dataview.registerAction(view, name, def) | 一覧画面の行アクションを追加する | 一覧画面のカスタマイズ |
ctx.dataview.registerBulkAction(view, name, def) | 一覧画面の一括アクションを追加する | 同上 |
ctx.dataview.registerMenu(view, name, def) | 一覧画面のメニュー項目を追加する | 同上 |
ctx.keyboardShortcuts.registerCategory(id, category) / registerShortcut(id, shortcut) | キーボードショートカット一覧にカテゴリーとショートカットを追加する | このページ下部 |
ctx.i18n.addResources(lng, resources) | 翻訳を追加する | このページ下部 |
ctx.config | PHP から渡された設定値 | このページ下部 |
登録系のメソッドはすべて解除用の関数を返します。ふつうは使う必要はありません(unregister で一括解除されます)が、条件によって途中で外したい場合に使えます。
const off = ctx.events.on('media.upload.before', handler);
off(); // 購読を解除する登録するタイミング
ACMS.plugins は、管理画面の JavaScript(admin.js)が実行されるまで存在しません。 admin.js は非同期で読み込まれるため、<script type="module"> のプラグインのほうが先に実行されることがあります。登録は ACMS.adminReady() の中で行ってください。admin.js の初期化が終わってから呼ばれ、すでに終わっていれば、すぐに呼ばれます。
// ○ 正しい
ACMS.adminReady(() => {
ACMS.plugins.register('my-plugin', {
setup(ctx) {
ctx.events.on('media.upload.before', handler);
},
});
});
// × 動かないことがあります(ACMS.plugins が未定義のことがあります)
ACMS.plugins.register('my-plugin', {
setup(ctx) {
ctx.events.on('media.upload.before', handler);
},
});
// × 動きません
document.addEventListener('DOMContentLoaded', () => {
ACMS.adminReady(() => {
ACMS.plugins.register('my-plugin', { setup(ctx) { /* ... */ } });
});
});DOMContentLoaded を待ったり、時間のかかる非同期処理のあとで登録したりすると、管理画面側がすでに処理を進めているため、購読が間に合わないことがあります。ACMS.adminReady() の呼び出し自体は、スクリプトが読み込まれた時点で同期的に行ってください。ACMS.adminReady() を使っても、初期化中にすでに発生したイベントは購読できません。
読み込みは <script type="module"> で行ってください(アセット API の attrs に ['type' => 'module'] を指定)。type="module" のスクリプトは、ページの解析が終わってから記述順に実行されます。
複数プラグインの実行順
同じイベントを複数のプラグインが購読した場合、登録した順に実行されます。type="module" のスクリプトは記述順に実行されるため、ふつうは JS ファイルが読み込まれた順になります。優先度の指定はありません。順序を制御したい場合は、アセット API を呼ぶ順番で調整してください。
setup が失敗したとき
setup(ctx) の中で例外が発生した場合、そのプラグインが途中まで行った登録はすべて取り消されます。半分だけ有効な状態にはなりません。
PHP から設定値を渡す(ctx.config)
PHP 側で jsModule() を使って渡した値を、ctx.config から読み取れます。
// PHP(プラグインの ServiceProvider::init() や Hook.php の afterBuild() など)
jsModule('myPlugin', [
'apiEndpoint' => '/api/my-plugin/',
'maxItems' => '20',
]);// JavaScript
ACMS.plugins.register('my-plugin', {
setup(ctx) {
console.log(ctx.config.apiEndpoint); // '/api/my-plugin/'
},
});キーはプラグイン名をキャメルケースに変換したものを使います(my-plugin → myPlugin)。設定が渡されていない場合、ctx.config は空のオブジェクトになります。
値の受け渡しの制約
この値は URL のクエリ文字列として渡される仕組みのため、次の制約があります。
- 数値・真偽値はすべて文字列になります。 PHP の
20(数値)は JavaScript では'20'(文字列)、true/falseは'1'/'0'になります。数値として使う場合はNumber()で変換してください。 nullはキーごと消えます。 JavaScript 側でそのキー自体が存在しなくなります。- 入れ子は5段までです。 それより深い構造は正しく復元されません。深い設定を渡したい場合は、フラットなキーにするか、JSON 文字列を1つ渡して JavaScript 側で
JSON.parse()してください。
API キーやトークンを ctx.config に渡さないでください
この値はブラウザの開発者ツールやアクセスログから閲覧できます。秘密にすべき情報を扱う連携は、PHP 側(フック処理や独自のエンドポイント)で行ってください。
翻訳を追加する(ctx.i18n)
ctx.i18n.addResources(lng, resources) で、プラグインの文言を追加できます。名前空間はプラグイン名に固定されるため、本体や他のプラグインとキーが衝突しません。同じ言語へ何度でも追加でき、既存の内容とマージされます。
ACMS.adminReady(() => {
ACMS.plugins.register('my-plugin', {
setup(ctx) {
ctx.i18n.addResources('ja', { greeting: 'こんにちは' });
ctx.i18n.addResources('en', { greeting: 'Hello' });
},
});
});参照するときは 名前空間:キー の形で書きます。上の例なら、ACMS.i18n('my-plugin:greeting') が現在の言語の文言を返します。setup(ctx) の実行中は翻訳の準備が終わっていないことがあるため、文言の参照は画面を操作したときの処理(イベントのハンドラなど)の中で行ってください。unregister すると、そのプラグインの翻訳も破棄されます。
キーボードショートカット一覧への追加(ctx.keyboardShortcuts)
registerCategory(id, category) と registerShortcut(id, shortcut) で、キーボードショートカット一覧のモーダルに項目を追加できます。shortcut.categoryId には、同じプラグインで登録したカテゴリーの id を指定します。
| 引数 | 内容 |
|---|---|
category.heading | カテゴリーの見出し |
category.order | 表示順(小さい値が先。省略可) |
shortcut.label | ショートカットの説明 |
shortcut.commands | コマンド ID の配列 |
shortcut.categoryId | 所属するカテゴリーの id |
shortcut.order | 表示順(小さい値が先。省略可) |
デバッグ
ACMS.plugins.getAll()— 登録内容を確認する。- 開発中はコンソールの警告を確認してください。 すでに発生済みのイベントを後から購読した場合など、動かない原因になる状況で警告が出ます(本番ビルドでは出ません)。
変更履歴
| バージョン | 変更内容 |
|---|---|
| Ver. 3.2 | 新規追加(実験的機能) |