2010年5月8日土曜日

【Twig】テンプレートにassignした変数を取得

あらかじめ

 {{ foo1 }}とか

 {{ foo2|safe }}とか

 {{ foo3.func('bar') }}とか

などと書かれたテンプレートを解析して、

foo1とかfoo2とかfoo3を抽出したい、というような場合。

※需要、ないなあ・・・。



パッと思いつくのはpreg_matchとかで

文字列解析する方法ですが、

テンプレートエンジンの場合、

タグの開始・終了文字(*1)をユーザが自由に

変更できたりするなど、

あまり単純な方法ではダメなのではないか、と思い。



でも、twigの場合、parser,lexerが外から操作できたり

簡単に拡張できたりするので、それでやってみよう、と。



・・・ということをやってみました。



抽出する関数
function getAssignVarsFrom($stream)
{
$ret = array();
$bIn = false;
$bInFirst = false;
while(! $stream->isEOF())
{
// get current node
$curr = $stream->getCurrent();

switch ($curr->getType()) {
case Twig_Token::VAR_START_TYPE:
$bIn = true;
$bInFirst = true;
break;
case Twig_Token::NAME_TYPE:
if ($bInFirst) {
$ret[$curr->getValue()] = $curr->getLine();
}
$bInFirst = false;
break;
case Twig_Token::VAR_END_TYPE:
$bIn = false;
$bInFirst = false;
break;
default:
break;
}

// next
$stream->next();
}
return $ret;
}



呼び出し側
$loader = new Twig_Loader_Filesystem('/path/to/template/');
$twig = new Twig_Environment( $loader,
array(
'cache' => '/path/to/cache',
'auto_reload' => true,
)
);
$escaper = new Twig_Extension_Escaper(true);
$twig->addExtension($escaper);
$stream = $twig->tokenize($twig->getLoader()->getSource('sample2.html'), 'sample2.html');
$assigned_vars = getAssignVarsFrom($stream);

※かなり手抜きです。
 "Twigの使い方"みたいなヤツのサンプルを簡単にイジっただけなので、
 余計な処理がテンコ盛りだと思います。
 (コンパイルしてないからcacheいらないんじゃないか、とか。
  extenssionは関係ないんじゃないか、とか。)



tokenize()が返してくるstreamの中にtokenが格納されているので、

NAME_TYPEだけ引っこ抜く、と。



それだけだと、safeとかfuncだとかも引っこ抜いてきてしまうので、

取り敢えず、VAR_START_TYPEからVAR_END_TYPEの間で

最初に出てきたNAME_TYPEだけ引っこ抜く、と。



これで本当によいのかどうか、かなり怪しいところですが、

取り敢えず、ちゃんとfoo1,foo2,foo3だけ返してきてます。



ちなみに、Twigのバージョンは、0.9.6-DEVを使いました。

0 件のコメント:

コメントを投稿

どうかお気軽にコメント頂ければ幸いです。