如何在不渲染树枝模板的情况下分析它们?
How can I analyze twig templates without rendering them?
对于我们正在开发的自定义 CMS,我们希望使用 twig 模板(因为这是我们的前端构建的基础)。模板可能会使用 twig 提供的 "default" 功能集(例如包含、块、标签、函数等),但我们也想为页面提供某些 "widgets"。
模板可能如下所示:
<h1>{{ 'our_products'|translate }}</h1>
{{ widget_search(widget_parameters) }}
所有以 widget_
开头的函数调用都是我们的特殊 CMS 小部件。
在后端,我们希望我们的编辑器填写我们的小部件需要的参数。因此,例如,对于包含 widget_search
的模板,应该向他们显示一个输入字段,他们可以在其中输入搜索词,但他们不应该能够更改任何其他内容。对于每种页面类型,我们都会创建一个模板,由我们的前端开发人员手工制作。
我现在的问题是:我们如何分析一个 twig 模板并提取所有函数调用的列表,以便我们可以构建后端 GUI(无需为后端渲染模板)?
我调查了 Twig_Parser
,但不确定如何利用它?特别是,如果它包含其他文件会怎样?解析器会解决这个问题吗?
(因为后端 GUI 是独立于 public 面向网站的应用程序(但他们都知道模板文件),我们不能简单地呈现模板,因为前端可能注册了 Twig 函数后端根本无法执行。)
在渲染之前,Twig 代码是:
- 已加载(returns 包含树枝模板的字符串)
- tokenized(returns TokenStream of Tokens,模板中包含的所有 Twig 元素)
- 已解析(returns一个Node_Module,一棵包含模板对象表示的树)
- 已编译(returns 一个包含与树枝模板对应的 php 代码的字符串)
对您有用的对象是 Node_Module
:您可以递归遍历它以非常容易地找到所有函数(或任何其他函数)。
示例(使用原生 Twig 函数,因为我没有你的):
<?php
require("vendor/autoload.php");
$env = new \Twig_Environment(new \Twig_Loader_Array(array()));
$template = "
<h1>{{ 'our_products'|upper }}</h1>
{{ max([1,random(),random()]) }}
";
$tree = $env->parse($env->tokenize($template));
$functions = array();
listFunctionCalls($tree, $functions);
function listFunctionCalls($node, array &$list) {
if ($node instanceof \Twig_Node_Expression_Function) {
$name = $node->getAttribute('name');
if (!in_array($name, $list)) {
$list[] = $name;
}
}
if ($node) {
foreach ($node as $child) {
listFunctionCalls($child, $list);
}
}
}
var_dump($functions);
给出以下结果:
$ php test.php
array(2) {
[0]=>
string(3) "max"
[1]=>
string(6) "random"
}
你可以用这棵树做任何事情,享受吧!
对于我们正在开发的自定义 CMS,我们希望使用 twig 模板(因为这是我们的前端构建的基础)。模板可能会使用 twig 提供的 "default" 功能集(例如包含、块、标签、函数等),但我们也想为页面提供某些 "widgets"。
模板可能如下所示:
<h1>{{ 'our_products'|translate }}</h1>
{{ widget_search(widget_parameters) }}
所有以 widget_
开头的函数调用都是我们的特殊 CMS 小部件。
在后端,我们希望我们的编辑器填写我们的小部件需要的参数。因此,例如,对于包含 widget_search
的模板,应该向他们显示一个输入字段,他们可以在其中输入搜索词,但他们不应该能够更改任何其他内容。对于每种页面类型,我们都会创建一个模板,由我们的前端开发人员手工制作。
我现在的问题是:我们如何分析一个 twig 模板并提取所有函数调用的列表,以便我们可以构建后端 GUI(无需为后端渲染模板)?
我调查了 Twig_Parser
,但不确定如何利用它?特别是,如果它包含其他文件会怎样?解析器会解决这个问题吗?
(因为后端 GUI 是独立于 public 面向网站的应用程序(但他们都知道模板文件),我们不能简单地呈现模板,因为前端可能注册了 Twig 函数后端根本无法执行。)
在渲染之前,Twig 代码是:
- 已加载(returns 包含树枝模板的字符串)
- tokenized(returns TokenStream of Tokens,模板中包含的所有 Twig 元素)
- 已解析(returns一个Node_Module,一棵包含模板对象表示的树)
- 已编译(returns 一个包含与树枝模板对应的 php 代码的字符串)
对您有用的对象是 Node_Module
:您可以递归遍历它以非常容易地找到所有函数(或任何其他函数)。
示例(使用原生 Twig 函数,因为我没有你的):
<?php
require("vendor/autoload.php");
$env = new \Twig_Environment(new \Twig_Loader_Array(array()));
$template = "
<h1>{{ 'our_products'|upper }}</h1>
{{ max([1,random(),random()]) }}
";
$tree = $env->parse($env->tokenize($template));
$functions = array();
listFunctionCalls($tree, $functions);
function listFunctionCalls($node, array &$list) {
if ($node instanceof \Twig_Node_Expression_Function) {
$name = $node->getAttribute('name');
if (!in_array($name, $list)) {
$list[] = $name;
}
}
if ($node) {
foreach ($node as $child) {
listFunctionCalls($child, $list);
}
}
}
var_dump($functions);
给出以下结果:
$ php test.php
array(2) {
[0]=>
string(3) "max"
[1]=>
string(6) "random"
}
你可以用这棵树做任何事情,享受吧!