mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Add tag filter. Move benchmark to another project
This commit is contained in:
parent
24f22f8f43
commit
6fec661ea7
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,7 +1,18 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
### 1.4.7 (2013-09-19)
|
||||
## 1.5.0
|
||||
|
||||
- Add tag filter
|
||||
- Redesign `extends` algorithm
|
||||
- Blocks does not support dynamic names
|
||||
- Blocks can't be nested
|
||||
- Add tag options support
|
||||
- Improve Fenom API
|
||||
- Move benchmark to another project
|
||||
- Rename `\Fenom\Compiler` to `\Fenom\Tags`
|
||||
|
||||
### 1.4.7 (2013-09-21)
|
||||
|
||||
- Bug fixes
|
||||
- Tests++
|
||||
|
@ -1,74 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__.'/scripts/bootstrap.php';
|
||||
|
||||
$opt = getopt("h", array(
|
||||
/** @var string $message */
|
||||
"cleanup",
|
||||
/** @var boolean $stress */
|
||||
"stress:",
|
||||
/** @var boolean $auto_reload */
|
||||
"auto_reload",
|
||||
/** @vat boolean $help */
|
||||
/** @vat boolean $h */
|
||||
"help"
|
||||
));
|
||||
|
||||
$opt += array(
|
||||
"stress" => 0
|
||||
);
|
||||
|
||||
extract($opt);
|
||||
|
||||
if(isset($h) || isset($help)) {
|
||||
echo "
|
||||
Start: ".basename(__FILE__)." [--stress COUNT] [--auto_reload] [--cleanup]
|
||||
Usage: ".basename(__FILE__)." [--help | -h]
|
||||
";
|
||||
exit;
|
||||
}
|
||||
|
||||
Benchmark::$stress = intval($stress);
|
||||
Benchmark::$auto_reload = isset($auto_reload);
|
||||
|
||||
exec("rm -rf ".__DIR__."/compile/*");
|
||||
|
||||
echo "Smarty3 vs Twig vs Fenom\n\n";
|
||||
|
||||
echo "Generate templates... ";
|
||||
passthru("php ".__DIR__."/templates/inheritance/smarty.gen.php");
|
||||
passthru("php ".__DIR__."/templates/inheritance/twig.gen.php");
|
||||
echo "Done\n";
|
||||
|
||||
echo "Testing a lot output...\n";
|
||||
|
||||
Benchmark::runs("smarty3", 'echo/smarty.tpl', __DIR__.'/templates/echo/data.json');
|
||||
Benchmark::runs("twig", 'echo/twig.tpl', __DIR__.'/templates/echo/data.json');
|
||||
Benchmark::runs("fenom", 'echo/smarty.tpl', __DIR__.'/templates/echo/data.json');
|
||||
//if(extension_loaded("phalcon")) {
|
||||
// Benchmark::runs("volt", 'echo/twig.tpl', __DIR__.'/templates/echo/data.json');
|
||||
//}
|
||||
echo "\nTesting 'foreach' of big array...\n";
|
||||
|
||||
Benchmark::runs("smarty3", 'foreach/smarty.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
Benchmark::runs("twig", 'foreach/twig.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
Benchmark::runs("fenom", 'foreach/smarty.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
//if(extension_loaded("phalcon")) {
|
||||
// Benchmark::runs("volt", 'foreach/twig.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
//}
|
||||
|
||||
echo "\nTesting deep 'inheritance'...\n";
|
||||
|
||||
Benchmark::runs("smarty3", 'inheritance/smarty/b100.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
Benchmark::runs("twig", 'inheritance/twig/b100.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
Benchmark::runs("fenom", 'inheritance/smarty/b100.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
//if(extension_loaded("phalcon")) {
|
||||
// Benchmark::runs("volt", 'inheritance/twig/b100.tpl', __DIR__.'/templates/foreach/data.json');
|
||||
//}
|
||||
|
||||
echo "\nDone\n";
|
||||
if(isset($cleanup)) {
|
||||
echo "Cleanup.\n";
|
||||
passthru("rm -rf ".__DIR__."/compile/*");
|
||||
passthru("rm -f ".__DIR__."/templates/inheritance/smarty/*");
|
||||
passthru("rm -f ".__DIR__."/templates/inheritance/twig/*");
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
<?php
|
||||
|
||||
require(__DIR__.'/../../vendor/autoload.php');
|
||||
|
||||
class Benchmark {
|
||||
const OUTPUT = "%8s: %-22s %10.4f sec, %10.1f MiB\n";
|
||||
|
||||
public static $stress = 0;
|
||||
public static $auto_reload = false;
|
||||
|
||||
public static function smarty3($tpl, $data, $double, $stress = false, $auto_reload = false) {
|
||||
$smarty = new Smarty();
|
||||
$smarty->compile_check = $auto_reload;
|
||||
|
||||
$smarty->setTemplateDir(__DIR__.'/../templates');
|
||||
$smarty->setCompileDir(__DIR__."/../compile/");
|
||||
|
||||
if($double) {
|
||||
$smarty->assign($data);
|
||||
$smarty->fetch($tpl);
|
||||
}
|
||||
|
||||
$start = microtime(true);
|
||||
if($stress) {
|
||||
for($i=0; $i<$stress; $i++) {
|
||||
$smarty->assign($data);
|
||||
$smarty->fetch($tpl);
|
||||
}
|
||||
} else {
|
||||
$smarty->assign($data);
|
||||
$smarty->fetch($tpl);
|
||||
}
|
||||
return microtime(true) - $start;
|
||||
|
||||
// printf(self::$t, __FUNCTION__, $message, round(microtime(true)-$start, 4), round(memory_get_peak_usage()/1024/1024, 2));
|
||||
}
|
||||
|
||||
public static function twig($tpl, $data, $double, $stress = false, $auto_reload = false) {
|
||||
|
||||
Twig_Autoloader::register();
|
||||
$loader = new Twig_Loader_Filesystem(__DIR__.'/../templates');
|
||||
$twig = new Twig_Environment($loader, array(
|
||||
'cache' => __DIR__."/../compile/",
|
||||
'autoescape' => false,
|
||||
'auto_reload' => $auto_reload,
|
||||
));
|
||||
|
||||
if($double) {
|
||||
$twig->loadTemplate($tpl)->render($data);
|
||||
}
|
||||
|
||||
$start = microtime(true);
|
||||
if($stress) {
|
||||
for($i=0; $i<$stress; $i++) {
|
||||
$twig->loadTemplate($tpl)->render($data);
|
||||
}
|
||||
} else {
|
||||
$twig->loadTemplate($tpl)->render($data);
|
||||
}
|
||||
return microtime(true) - $start;
|
||||
}
|
||||
|
||||
public static function fenom($tpl, $data, $double, $stress = false, $auto_reload = false) {
|
||||
|
||||
$fenom = Fenom::factory(__DIR__.'/../templates', __DIR__."/../compile");
|
||||
if($auto_reload) {
|
||||
$fenom->setOptions(Fenom::AUTO_RELOAD);
|
||||
}
|
||||
if($double) {
|
||||
$fenom->fetch($tpl, $data);
|
||||
}
|
||||
$start = microtime(true);
|
||||
if($stress) {
|
||||
for($i=0; $i<$stress; $i++) {
|
||||
$fenom->fetch($tpl, $data);
|
||||
}
|
||||
} else {
|
||||
$fenom->fetch($tpl, $data);
|
||||
}
|
||||
return microtime(true) - $start;
|
||||
}
|
||||
|
||||
// public static function volt($tpl, $data, $double, $message) {
|
||||
// $view = new \Phalcon\Mvc\View();
|
||||
// //$view->setViewsDir(__DIR__.'/../templates');
|
||||
// $volt = new \Phalcon\Mvc\View\Engine\Volt($view);
|
||||
//
|
||||
//
|
||||
// $volt->setOptions(array(
|
||||
// "compiledPath" => __DIR__.'/../compile'
|
||||
// ));
|
||||
// $tpl = __DIR__.'/../templates/'.$tpl;
|
||||
// if($double) {
|
||||
// $volt->render($tpl, $data);
|
||||
// }
|
||||
//
|
||||
// $start = microtime(true);
|
||||
// $volt->render($tpl, $data);
|
||||
// printf(self::$t, __FUNCTION__, $message, round(microtime(true)-$start, 4), round(memory_get_peak_usage()/1024/1024, 2));
|
||||
// }
|
||||
|
||||
public static function run($engine, $template, $data, $double, $message) {
|
||||
passthru(sprintf(PHP_BINARY." -n -dextension=phalcon.so -ddate.timezone=Europe/Moscow -dmemory_limit=512M %s/run.php --engine '%s' --template '%s' --data '%s' --message '%s' %s --stress %d %s", __DIR__, $engine, $template, $data, $message, $double ? '--double' : '', self::$stress, self::$auto_reload ? '--auto_reload' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $engine
|
||||
* @param $template
|
||||
* @param $data
|
||||
*/
|
||||
public static function runs($engine, $template, $data) {
|
||||
self::run($engine, $template, $data, false, '!compiled and !loaded');
|
||||
self::run($engine, $template, $data, false, ' compiled and !loaded');
|
||||
self::run($engine, $template, $data, true, ' compiled and loaded');
|
||||
echo "\n";
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
$opt = getopt("", array(
|
||||
/** @var string $engine */
|
||||
"engine:",
|
||||
/** @var string $template */
|
||||
"template:",
|
||||
/** @var string $data */
|
||||
"data:",
|
||||
/** @var boolean $double */
|
||||
"double",
|
||||
/** @var string $message */
|
||||
"message:",
|
||||
/** @var boolean $stress */
|
||||
"stress:",
|
||||
/** @var boolean $auto_reload */
|
||||
"auto_reload"
|
||||
));
|
||||
|
||||
require_once __DIR__.'/bootstrap.php';
|
||||
|
||||
$opt += array(
|
||||
"message" => "plain",
|
||||
"stress" => 0,
|
||||
);
|
||||
|
||||
extract($opt);
|
||||
|
||||
|
||||
$time = Benchmark::$engine($template, json_decode(file_get_contents($data), true), isset($double), $stress, isset($auto_reload));
|
||||
|
||||
printf(Benchmark::OUTPUT, $engine, $message, round($time, 4), round(memory_get_peak_usage()/1024/1024, 2));
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +0,0 @@
|
||||
<h1>Вывод 10 полей из 1000 элементов в цикле</h1>
|
||||
{foreach $array as $item}
|
||||
{$item.id} {$item.title} {$item.var1} {$item.var2} {$item.var3} {$item.var4} {$item.var5} {$item.var6} {$item.var5} {$item.var6}
|
||||
{/foreach}
|
@ -1,4 +0,0 @@
|
||||
<h1>Вывод 10 полей из 1000 элементов в цикле<h1>
|
||||
{% for item in array %}
|
||||
{{ item.id }} {{ item.title }} {{ item.var1 }} {{ item.var2 }} {{ item.var3 }} {{ item.var4 }} {{ item.var5 }} {{ item.var6 }} {{ item.var5 }} {{ item.var6 }}
|
||||
{% endfor %}
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
$b0 = '<h1>Вывод статических данных в 500 наследуемых блоков</h1>' . "\r\n";
|
||||
for($i = 1; $i < 501; $i++)
|
||||
{
|
||||
$b0 .= '{block b'.$i.'}{/block}'."\r\n";
|
||||
$data = '{extends "inheritance/smarty/b'.($i-1).'.tpl"}' . "\r\n";
|
||||
$data .= '{block b'.$i.'}data'.$i.'{/block}' . "\r\n";
|
||||
file_put_contents(__DIR__.'/smarty/b'.$i.'.tpl', $data);
|
||||
}
|
||||
file_put_contents(__DIR__.'/smarty/b0.tpl', $b0);
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
$b0 = '<h1>Вывод статических данных в 500 наследуемых блоков</h1>' . "\r\n";
|
||||
for($i = 1; $i < 501; $i++)
|
||||
{
|
||||
$b0 .= '{% block b'.$i.' %}{% endblock %}'."\r\n";
|
||||
$data = '{% extends "inheritance/twig/b'.($i-1).'.tpl" %}' . "\r\n";
|
||||
$data .= '{% block b'.$i.' %}data'.$i.'{% endblock %}' . "\r\n";
|
||||
file_put_contents(__DIR__.'/twig/b'.$i.'.tpl', $data);
|
||||
}
|
||||
file_put_contents(__DIR__.'/twig/b0.tpl', $b0);
|
@ -16,8 +16,6 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*",
|
||||
"smarty/smarty": "3.*",
|
||||
"twig/twig": "1.*",
|
||||
"satooshi/php-coveralls": "dev-master"
|
||||
},
|
||||
"autoload": {
|
||||
|
61
sandbox/compiled/greeting.tpl.baf47f57.10.php
Normal file
61
sandbox/compiled/greeting.tpl.baf47f57.10.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/** Fenom template 'greeting.tpl' compiled at 2013-09-02 17:37:18 */
|
||||
return new Fenom\Render($fenom, function ($tpl) {
|
||||
?>
|
||||
|
||||
A1
|
||||
<?php
|
||||
/* greeting.tpl:4: {mc.factorial num=10} */
|
||||
$_tpl4154309674_1 = $tpl->exchangeArray(array("num" => 10));
|
||||
?><?php
|
||||
/* macros.tpl:2: {if $num} */
|
||||
if($tpl["num"]) { ?>
|
||||
<?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?> <?php
|
||||
/* macros.tpl:3: {macro.factorial num=$num-1} */
|
||||
$_tpl2531688351_1 = $tpl->exchangeArray(array("num" => $tpl["num"] - 1));
|
||||
$tpl->getMacro("factorial")->__invoke($tpl);
|
||||
$tpl->exchangeArray($_tpl2531688351_1); /* X */ unset($_tpl2531688351_1); ?> <?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?>
|
||||
<?php
|
||||
/* macros.tpl:4: {/if} */
|
||||
} ?>
|
||||
<?php
|
||||
$tpl->exchangeArray($_tpl4154309674_1); /* X */ unset($_tpl4154309674_1); ?>
|
||||
A2<?php
|
||||
}, array(
|
||||
'options' => 128,
|
||||
'provider' => false,
|
||||
'name' => 'greeting.tpl',
|
||||
'base_name' => 'greeting.tpl',
|
||||
'time' => 1378125225,
|
||||
'depends' => array (
|
||||
0 =>
|
||||
array (
|
||||
'macros.tpl' => 1378129033,
|
||||
'greeting.tpl' => 1378125225,
|
||||
),
|
||||
),
|
||||
'macros' => array(
|
||||
'factorial' => function ($tpl) {
|
||||
?><?php
|
||||
/* macros.tpl:2: {if $num} */
|
||||
if($tpl["num"]) { ?>
|
||||
<?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?> <?php
|
||||
/* macros.tpl:3: {macro.factorial num=$num-1} */
|
||||
$_tpl2531688351_1 = $tpl->exchangeArray(array("num" => $tpl["num"] - 1));
|
||||
$tpl->getMacro("factorial")->__invoke($tpl);
|
||||
$tpl->exchangeArray($_tpl2531688351_1); /* X */ unset($_tpl2531688351_1); ?> <?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?>
|
||||
<?php
|
||||
/* macros.tpl:4: {/if} */
|
||||
} ?>
|
||||
<?php
|
||||
}),
|
||||
|
||||
));
|
61
sandbox/compiled/greeting.tpl.ef153838.e.php
Normal file
61
sandbox/compiled/greeting.tpl.ef153838.e.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/** Fenom template 'greeting.tpl' compiled at 2013-09-02 17:37:39 */
|
||||
return new Fenom\Render($fenom, function ($tpl) {
|
||||
?>
|
||||
|
||||
A1
|
||||
<?php
|
||||
/* greeting.tpl:4: {mc.factorial num=10} */
|
||||
$_tpl4154309674_1 = $tpl->exchangeArray(array("num" => 10));
|
||||
?><?php
|
||||
/* macros.tpl:2: {if $num} */
|
||||
if($tpl["num"]) { ?>
|
||||
<?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?> <?php
|
||||
/* macros.tpl:3: {macro.factorial num=$num-1} */
|
||||
$_tpl2531688351_1 = $tpl->exchangeArray(array("num" => $tpl["num"] - 1));
|
||||
$tpl->getMacro("factorial")->__invoke($tpl);
|
||||
$tpl->exchangeArray($_tpl2531688351_1); /* X */ unset($_tpl2531688351_1); ?> <?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?>
|
||||
<?php
|
||||
/* macros.tpl:4: {/if} */
|
||||
} ?>
|
||||
<?php
|
||||
$tpl->exchangeArray($_tpl4154309674_1); /* X */ unset($_tpl4154309674_1); ?>
|
||||
A2<?php
|
||||
}, array(
|
||||
'options' => 0,
|
||||
'provider' => false,
|
||||
'name' => 'greeting.tpl',
|
||||
'base_name' => 'greeting.tpl',
|
||||
'time' => 1378125225,
|
||||
'depends' => array (
|
||||
0 =>
|
||||
array (
|
||||
'macros.tpl' => 1378129033,
|
||||
'greeting.tpl' => 1378125225,
|
||||
),
|
||||
),
|
||||
'macros' => array(
|
||||
'factorial' => function ($tpl) {
|
||||
?><?php
|
||||
/* macros.tpl:2: {if $num} */
|
||||
if($tpl["num"]) { ?>
|
||||
<?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?> <?php
|
||||
/* macros.tpl:3: {macro.factorial num=$num-1} */
|
||||
$_tpl2531688351_1 = $tpl->exchangeArray(array("num" => $tpl["num"] - 1));
|
||||
$tpl->getMacro("factorial")->__invoke($tpl);
|
||||
$tpl->exchangeArray($_tpl2531688351_1); /* X */ unset($_tpl2531688351_1); ?> <?php
|
||||
/* macros.tpl:3: {$num} */
|
||||
echo $tpl["num"]; ?>
|
||||
<?php
|
||||
/* macros.tpl:4: {/if} */
|
||||
} ?>
|
||||
<?php
|
||||
}),
|
||||
|
||||
));
|
@ -79,6 +79,11 @@ class Fenom
|
||||
*/
|
||||
public $filters = array();
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
public $tag_filters = array();
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
@ -349,6 +354,22 @@ class Fenom
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $cbcd
|
||||
* @return self
|
||||
*/
|
||||
public function addTagFilter($cb)
|
||||
{
|
||||
$this->tag_filters[] = $cb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getTagFilters()
|
||||
{
|
||||
return $this->tag_filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add modifier
|
||||
*
|
||||
|
@ -139,9 +139,10 @@ class Template extends Render
|
||||
*/
|
||||
public function __construct(Fenom $fenom, $options)
|
||||
{
|
||||
$this->_fenom = $fenom;
|
||||
$this->_options = $options;
|
||||
$this->_filters = $this->_fenom->getFilters();
|
||||
$this->_fenom = $fenom;
|
||||
$this->_options = $options;
|
||||
$this->_filters = $this->_fenom->getFilters();
|
||||
$this->_tag_filters = $this->_fenom->getTagFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,6 +249,11 @@ class Template extends Render
|
||||
$this->_appendText($tag);
|
||||
}
|
||||
} else {
|
||||
if($this->_tag_filters) {
|
||||
foreach($this->_tag_filters as $filter) {
|
||||
$_tag = call_user_func($filter, $_tag, $this);
|
||||
}
|
||||
}
|
||||
$tokens = new Tokenizer($_tag); // tokenize the tag
|
||||
if ($tokens->isIncomplete()) { // all strings finished?
|
||||
$need_more = true;
|
||||
@ -607,6 +613,7 @@ class Template extends Render
|
||||
* Parse expressions. The mix of operators and terms.
|
||||
*
|
||||
* @param Tokenizer $tokens
|
||||
* @return string
|
||||
* @throws Error\UnexpectedTokenException
|
||||
*/
|
||||
public function parseExpr(Tokenizer $tokens)
|
||||
|
@ -163,6 +163,23 @@ class FenomTest extends \Fenom\TestCase
|
||||
$this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} <?php misterio ?> {/var} world')->fetch(array()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group tag-filter
|
||||
*/
|
||||
public function testTagFilter() {
|
||||
$tags = array();
|
||||
$punit = $this;
|
||||
$this->fenom->addTagFilter(function ($text, $tpl) use (&$tags, $punit) {
|
||||
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
||||
$tags[] = $text;
|
||||
return $text;
|
||||
});
|
||||
|
||||
$this->fenom->compileCode('hello {var $a} misterio {/var} world, {$b}!');
|
||||
|
||||
$this->assertSame(array('var $a', '/var', '$b'), $tags);
|
||||
}
|
||||
|
||||
public function testAddInlineCompilerSmart() {
|
||||
$this->fenom->addCompilerSmart('SayA','TestTags');
|
||||
$this->tpl('inline_compiler.tpl', 'I just {SayA}.');
|
||||
|
Loading…
Reference in New Issue
Block a user