unoh.github.com

Wikiのプラグイン記法を実装する

Wed Oct 10 00:57:17 -0700 2007

bokkoです。

普段からWikiを使っていると、「○○する記法がほしいなあ」と思うことがあると思います。
しかし、単純に記法を追加しようとすると、ほかの記法とぶつかってしまったり、思わぬ副作用を引き起こす可能性があるため、大抵のWikiクローンには独自でプラグインを作るための仕組みがあります。
例えば、どこかにplugin_nameというスクリプトファイルを用意し、{{plugin_name 引数}}と書かれた部分をそのスクリプトファイルを実行した結果に置き換える、という風に。

というわけで、今日は私がローカルで使っているオレオレWikiクローンでのプラグイン機構の実装例を紹介しようと思います。実現するためのコードは以下のようになっています。(ほかの機能のためのコードが混ざってしまっていてちょっと見づらいですが)

private function createPlugin(){
    $dir = Config::GetPluginDir().'/';
    $hd = null;
    $file = null;
    $str = 'if($hd = opendir($dir)){
                  while(false !== $file = readdir($hd)){
                      if($file === \\\'\\2.php\\\'){
                          require_once($dir.$file);
                      }
                  }
              }
              if(function_exists(plugin_\\2)) return \\\'\\1\\\'.plugin_\\2(\\\'\\3\\\', $this->plugined_file).\\\'\\4\\\';
              else return \\\'Not Found!\\4\\\';';
    // 引数なし 例:{{lastupdate}}
    $this->text = preg_replace("/([^<])\{\{([^\{ ]*)()\}\}([^>])/e",
                                          "eval('$str')",
                                          $this->text);
     // 引数あり 例:{{strlen abc}}
     $this->text = preg_replace("/([^<])\{\{([^\{]*)\s([^\{]*)\}\}([^>])/e",
                                           "eval('$str')",
                                           $this->text);
} 


まず、テキストの中{{plugin_name}}、または{{plugin_name 引数}}というのがあれば、その中身をevalに放り込みます。その後、plugin_nameの部分に該当するファイル名と関数名があれば、その関数を実行し、結果を返します。ファイルや関数が存在しない場合は、「Not Found!」という文字列を返します。(実際に実用的なプラグインの仕組みを作る場合はもっと厳密な決まりが必要だと思います)

時刻を取得する場合は、以下のようなコードになります。

function plugin_lastUpdate($arg, $file){
    return date("Y/m/d H:i:s");
}