目次
DokuWiki Event Handlers
DokuWikiでは、ユーザー独自のイベントやトリガーを作成することができます。そして、DokuWikiによって発動されるトリガーに対して、自分のイベントコードを実行できるように登録することができます。このページでは、DokuWikiによって発動されるトリガーに対して、イベントハンドラーをどう使い、どうコードするかを見ていきます。(DokuWikiのイベント一覧)
The Event Loop
まず、どのようにイベントが処理されるかを見ていくとわかりやすいでしょう。あるイベントの発生を知らされるためには、あなたのコードをそのイベント通知(notification)に登録しておく必要があります。あなたのコードをあるイベント通知に登録すると、通知に対する要求がそのイベントのリストの末尾に追加されます。このリストは、登録順に実行されていきます。このようにして、ひとつのイベント通知に対して複数のコードが順番に実行されることを実現しています。1)
DokuWikiがイベントに紐付けられたアクションのコードを処理するとき、すぐにその場で実行されるわけではありません。その代わり、このアクションに対するイベントが発生されます。たとえば、DokuWikiがwikiページを出力し始める時には、IO_WIKIPAGE_WRITEトリガーが発生され、イベント通知処理を始めます。
実際には2つのリストがあります:ひとつはDokuWikiのアクションの前(名前にBEFORE
が付けられています)、もうひとつはアクションの後(AFTER
)です。DokuWikiのあるアクションが実行される前に、BEFORE某に登録されたリクエストを順番に実行します。これにより、DokuWikiが何かを実行する前にあなたのコードを実行することができます。たとえば、IO_WIKIPAGE_WRITEの場合、ブラウザにページ内容が送られる前にそれを変更することができるのです。
DokuWikiのアクションが終わった後に、DokuWikiはAFTER
に登録されたリクエストが順に実行されます。たとえば、TPL_ACT_RENDERイベントの場合、wikiページの後にページ内容を追加することができます。2)
DokuWikiのアクションはdefaultです。しかし、BEFORE
リクエスト群の処理中に、defaultアクションを起こさないようにもできます。同様に、イベントハンドラーは他の未処理のイベントハンドラーを実行せずに飛ばすこともできます。
単純化した擬似コードで表すと、そのイベントプロセスはこのようになるでしょう。
var $process_event = true; var $default_stopped = false; loop_through_BEFORE_List() { return if $process_event == false; } do_DokuWiki_Action() { return if $default_stopped; } var $process_event = true; loop_through_AFTER_List(){ return if $process_event == false; }
Registering an Event
イベントハンドラはEVENT_HANDLER
クラスのregister_hook()
メソッドを呼び出すことで登録でき、その使用はDokuWikiのevents pageで確認できます。
register_hook()
メソッドの定義は次のようになっています。
void register_hook(string $event, string $advise, mixed &$obj, string $method, mixed $param = null, int $seq = 0)
$event
はイベントの名前です。たとえば、IO_WIKIPAGE_WRITE$advise
はBEFORE
かAFTER
。$obj
は参照側のオブジェクト。プラグインであれば$this
インスタンス、他のものであればNULL。コールバック関数の場合はグローバルスコープでなければならない。$method
イベント処理を実行するコールバックメソッドの名前。$param
はオプション。もしコールバックが何かしらのデータを必要とする場合に使う。$seq
はオプション。処理が実行される順番を制御する番号(release 2014-05-05 “Ponder Stibbons”から).
Global Scope
グローバルスコープからregister_hook()
を呼び出す場合、 $obj
をnullにセットし、グローバル変数である$EVENT_HANDLER
を直接使います。
$EVENT_HANDLER->register_hook( ... )
$EVENT_HANDLER
はDoku_Event_Handler
への参照です。これは、DokuWikiで定義されたものもユーザー定義にものも、すべてのイベントの実行を制御しています。
Action plugins
Action plugins do not need direct access to the global $EVENT_HANDLER
. They are specifically designed for adding handles to DokuWiki events, and typically you would be calling register_hook()
from an action plugin.
In action plugins, event handlers are registered in the register()
method, which all action plugins must implement. It takes one parameter, $controller
, which is in effect an alias for $EVENT_HANDLER
and which is used to register event handlers:
public function register(Doku_Event_Handler $controller) { $controller->register_hook('TPL_ACT_RENDER','AFTER',$this,'tpl_render'); }
- The event is TPL_ACT_RENDER, which is activated in
inc/template.php
by the function which dispatches the page to be formatted and printed. - The event handler is
tpl_render()
, which will be found in the plugin object. - The
$this
parameter, which points to the plugin object, will give DokuWiki's event module access to the handler. - Finally, the handler is to be called after DokuWiki formats the page content.
The Event Handler
The handler has this basic form:
/** * @param Doku_Event $event the Doku_Event object * @param mixed $param value provided as fifth argument to register_hook() */ function handler (&$event, $param) { // handler code }
When Doku_Event_Handler calls the handler function, it passes in two parameters, the current $event
object and $param
. which is designed to hold any additional data relevant to the event. $param
is the $param
that is passed through as the fifth parameter in register_hook().
3)
The Event Object
The authoritative specification for the event object Doku_Event is found on the event page and should be consulted.
The $event
object has six fields:
name
: Event Name;data
: Specific to each event, data may include, page content, headers, meta data, objects, the current action (e.g. edit, index), whatever is needed of for the execution of the event; it may also hold no data, and it has no fixed structure: it may be a string, array, multidimensional array, object.result
: First it holds the return value from the default handler, which can then be consulted by anAFTER
handler. It can then be modified by anAFTER
handler, in which case it might be information for any subsequentAFTER
handlers. Ultimately, it will be returned to thetrigger_event()
function. In most case this value is eithertrue
, if the default action has taken place, ornull
if it hasn't.canPreventDefault
:true
orfalse
, indicating whether or not the default action for this event can be stopped; this information is available from DokuWiki's events list._default
:true
orfalse
, indicating whether the default action for this event should be enabled; its default value is true but can be set to false by calling $event->preventDefault()._continue
: This value defaults totrue
. If$event->stopPropagation()
is called, it is set to false, stopping “any further processing of the event by event handlers” but “this function does not prevent the default action taking place”.4)
Methods
$event->preventDefault()
- Calling this method from a
BEFORE
handler prevents the default action taking from place; it has no effect if called from anAFTER
handler. It sets$event->_default
tofalse
. Being able to prevent the default action has considerable utility. It can stop a page from being cached when used with the PARSER_CACHE_USE event. It can also prevent a page from being sent to the browser at various stages of the rendering and output process, each of which is represented by an event. One enticing idea is preventing the TPL_ACT_UNKNOWN default to set up your own action in response to an unrecognized action request. However, this idea would not work because it is blocked the byaction_clean()
method in inc/action.php. See the events list on the DokuWiki site for details and possibilities.
$event->stopPropagation()
.- Calling this method sets
$event->_continue
tofalse
and stops any further processing of the event by event handlers; it does not prevent the default action taking place. It comes into play where you have set more than one handler for the same event. If you have registered an event for bothBEFORE
andAFTER
execution, canceling theBEFORE
does not stop propagation of theAFTER
events. (See the above section on the Event Loop).
-
- This is a global function, not a method of the
Doku_Event
class. Calling this function enables the triggering of a user-defined event. Its parameters are as follows:$name
: This is the name of the event. If you implement your own event, then this is the name of that event.$data
: Whatever is required for your data$action
: This is the default action, most probably a function in the global scope.$canPreventDefault
:true
orfalse
, to indicate whether or not the default action can be stopped. In user-defined events, this can be left at the default value oftrue
.- mixed return value: This is whatever is stored in the event's property
$event->result
.
- It's possible to use this function to trigger a standard DokuWiki event, but this would require careful coding and a knowledge of when and how the DokuWiki event is processed. Moreover, triggering a standard event doesn't prevent it from being triggered by DokuWiki. It would also have to be an event which doesn't have a default action5), since using this function replaces the event's default action with the
$action
parameter oftrigger_event()
.
Examples
See event handlers code samples.
See also
- The Event system
- Events List with existing events.
- Use Action plugins to register handlers on events.
BEFORE
を使えばページ内容の前に何かを挿入することができます。$param
, but it is available if needed in user-designed events.