EC-CUBEのPlugin間の優先度を制御する機構について説明します。
Edit me

課題

稼働環境に同じイベントをフックする複数のプラグインを同時にインストールし、各プラグインのイベントハンドラがパラメータを書き換える場合、書き換える順序によっては想定しない動作が発生する恐れがある。
さらに、監査、ロギング、デバッグ用等で他のプラグインより必ず先又は後で起動する必要のあるハンドラの起動順序を制御したい

例 :
購入時のFormEventをカード決済プラグインと後払いプラグインのイベントハンドラが書き換える場合、後のハンドラが書き換えるフォーム要素を前のプラグインが削除している可能性がある

対策

管理画面からユーザが各イベントのハンドラの起動順を設定できるようにする
例:後払い(3)→カード決済(2) →監査(1)の順でFormEventのイベントハンドラが起動
起動順序は管理画面等からDB上のハンドラ優先度テーブル(仮)に保持する。
SymfonyのEventDispatcher の仕様に合わせて実行順は-511~+511の降順とする

テーブル構成はプラグインインストーラーの仕様を参照

起動優先度とハンドラ種別

  • 優先度は+400~-399は通常型ハンドラ用とする
  • 優先度-400~-499は後発型ハンドラ用とする(デバッグ、監査用を想定)
  • 優先度+500~+401は先発型ハンドラ用とする(同上)
  • 優先度0は実行時にハンドラを登録しない(ハンドラを無効化)

プラグインインストール時の動作

  • 各プラグインのgetSubscribedEvents内のイベントハンドラと優先度をハンドラ優先度テーブルに挿入する
  • 当該イベントにハンドラが1件も登録されていない場合のデフォルト優先度は以下のとおり
    • 先発型:500
    • 通常型:400
    • 後発型:-400
  • ハンドラが既に登録されている場合、既に存在する同型ハンドラのイベントの優先度の最大値-1を登録する
    (ハンドラが既に400に登録されている場合に通常ハンドラを登録すると399に登録される)
  • ハンドラ種別毎に決められた優先度枠に空きがない場合、プラグインのインストールは失敗する

Webアプリケーション実行時の動作

  • プラグインのイベンドハンドラをディスパッチャに登録する際(Application.php等)、優先度テーブルの優先度(昇順)に各ハンドラを登録する
  • イベントが実際に発生すると登録された順にハンドラが起動する
  • 優先度テーブルに登録されていないイベントハンドラがプラグインに定義されている場合、優先度-500(全てのハンドラの後)とみなされる

ハンドラ優先度変更画面の動作

  • 各ハンドラの優先度をユーザ入力に基づいてアップデートする
  • ただし、優先度はハンドラ種別(通常、先発、後発)毎の範囲内に限定される

プラグイン開発者への影響

  • getSubscribedEventsはハンドラのメソッド名と優先度(数値)を返すが、メソッド名と種別(通常、先発、後発)を返すように変更
  • (開発者向けの指針)通常型プラグインとの衝突を防ぐため、先発型、後発型のハンドラでは渡されたパラメータを書き換えないことが望ましい
Tags: plugin spec