ajaxやhelper、actionプラグインなどからプラグイン独自のメタ情報を使いたい場合があります。方法として考えられるのは
Cookieを使う
セッションを使う
DokuWikiページのメタ情報を使う
プラグイン毎のメタ情報ファイルを使う
などがあります。1.については、貴重なCookie空間(サイトごとに個数が制限されている)をプラグインごときのために使うのはもったいないので、これは無しとする。2.は、サーバ側のメモリ以外のリソースを食わないので悪くはないですが、セッション切れのときはどうするかを考えねばならないので、意外と面倒です。3.はページ情報のみを取得するときに無用にプラグインのメタ情報がくっついてきてしまうのが気持ち悪いし、メインプログラムのリソースを書き換えるのはあまり行儀がよくありません。そこで、4.の方法を使うことにします。
DokuWikiページメタ情報は
データディレクトリ/meta/名前空間のパス/ページID.meta
に保存されるので、この場所を使うことにします。以下のコードは、グローバルな名前空間を汚さないよう、プラグインのクラス内で定義してください。
【メタ情報の書き込み】
/**
* メタ情報オブジェクトをファイルに書き込む。
*/
function setmeta($id, $meta) {
$fname = metaFN($id, ".プラグイン名"); //メタファイルはプラグイン名を拡張子としたものにする。
io_makeFileDir($fname); //メタファイルの保管ディレクトリがまだ存在しなければ作成する。
io_lock($fname); //メタファイルをロックする。
$fh = @fopen($fname, "wb"); //メタファイルを書き込みオープンする。
if (!$fh) {
//エラー出力
io_unlock($fname);
return false;
}
fwrite($fh, serialize($meta)); //メタファイルにオブジェクトを直列化して書き込む。
fclose($fh); //メタファイルをクローズする。
io_unlock($fname); //メタファイルのロックを解除する。
return true;
}
【メタ情報の読み込み】
/**
* メタ情報を読み込み、オブジェクトとして返す。
*/
function getmeta($id) {
$fname = metaFN($id, ".プラグイン名"); //メタファイルはプラグイン名を拡張子としたものにする。
if (!@file_exists($fname)) {
//エラー出力
return null;
}
//メタファイルから直列化されたオブジェクトを読み込んで復元して返す。
return unserialize(file_get_contents($fname));
}
【読み書きのタイミング】
メタ情報の書き込みは、syntaxプラグインでparseのタイミングで行うのが楽でいいのですが、発想を変えてIO_PAGE_WRITEイベントを使って書き込み時に行うことを考えてみます。優先度とか入れ子のことを考えると、ちゃんとDokuWikiパーサで処理するほうが良いとは思いますが、そこは目をつぶって単純な正規表現マッチングで解析処理を行うことにします。
そうすると、syntaxプラグインの仕事はparserから受け取ったデータではなく、自身のactionプラグインが書き込んだメタ情報を読み込んで使うことになります。
こうすることのメリットは、不必要にメタ情報ファイルを書き換えないことに加えて、必要なときに書き換えられるということがあります。つまり、syntaxプラグインを経由しないajax的な手法でデータを書き換えたい場合に対応できるということです。
【メタ情報のみを書き換えたとき、Wikiの編集をして保存すると古い情報が上書きされてしまう】
あぁ、その通りです。Wikiテキスト内にデータを埋め込むことと表示画面からデータを更新することは両立しないかも?想定しているのはspreadsheetのようなもので、Wikiテキストにインラインで初期データを書き込んで、表示画面上でさらに編集する場合です。
これを解決するには、インラインデータを優先してそのデータをロックすればどうでしょうか。表示画面上でセル単位でロックして編集できなくするのです。これには巧妙なメタデータ設計が必要そうです。