Add filters for templates (#30)

This commit is contained in:
bzick
2013-08-01 01:05:19 +04:00
parent e68f3dd99a
commit f1d252a3cc
4 changed files with 99 additions and 36 deletions

View File

@ -7,8 +7,8 @@
* For the full copyright and license information, please view the license.md * For the full copyright and license information, please view the license.md
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
use Fenom\Template, use Fenom\ProviderInterface;
Fenom\ProviderInterface; use Fenom\Template;
/** /**
* Fenom Template Engine * Fenom Template Engine
@ -67,10 +67,26 @@ class Fenom
"disable_statics" => self::DENY_STATICS, "disable_statics" => self::DENY_STATICS,
); );
/**
* @var callable[]
*/
public $pre_filters = array();
/**
* @var callable[]
*/
public $filters = array();
/**
* @var callable[]
*/
public $post_filters = array();
/** /**
* @var Fenom\Render[] Templates storage * @var Fenom\Render[] Templates storage
*/ */
protected $_storage = array(); protected $_storage = array();
/** /**
* @var string compile directory * @var string compile directory
*/ */
@ -81,10 +97,6 @@ class Fenom
*/ */
protected $_options = 0; protected $_options = 0;
protected $_on_pre_cmp = array();
protected $_on_cmp = array();
protected $_on_post_cmp = array();
/** /**
* @var ProviderInterface * @var ProviderInterface
*/ */
@ -98,28 +110,28 @@ class Fenom
* @var string[] list of modifiers [modifier_name => callable] * @var string[] list of modifiers [modifier_name => callable]
*/ */
protected $_modifiers = array( protected $_modifiers = array(
"upper" => 'strtoupper', "upper" => 'strtoupper',
"up" => 'strtoupper', "up" => 'strtoupper',
"lower" => 'strtolower', "lower" => 'strtolower',
"low" => 'strtolower', "low" => 'strtolower',
"date_format" => 'Fenom\Modifier::dateFormat', "date_format" => 'Fenom\Modifier::dateFormat',
"date" => 'Fenom\Modifier::date', "date" => 'Fenom\Modifier::date',
"truncate" => 'Fenom\Modifier::truncate', "truncate" => 'Fenom\Modifier::truncate',
"escape" => 'Fenom\Modifier::escape', "escape" => 'Fenom\Modifier::escape',
"e" => 'Fenom\Modifier::escape', // alias of escape "e" => 'Fenom\Modifier::escape', // alias of escape
"unescape" => 'Fenom\Modifier::unescape', "unescape" => 'Fenom\Modifier::unescape',
"strip" => 'Fenom\Modifier::strip', "strip" => 'Fenom\Modifier::strip',
"length" => 'Fenom\Modifier::length', "length" => 'Fenom\Modifier::length',
"iterable" => 'Fenom\Modifier::isIterable' "iterable" => 'Fenom\Modifier::isIterable'
); );
/** /**
* @var array of allowed PHP functions * @var array of allowed PHP functions
*/ */
protected $_allowed_funcs = array( protected $_allowed_funcs = array(
"count" => 1, "is_string" => 1, "is_array" => 1, "is_numeric" => 1, "is_int" => 1, "count" => 1, "is_string" => 1, "is_array" => 1, "is_numeric" => 1, "is_int" => 1,
"is_object" => 1, "strtotime" => 1, "gettype" => 1, "is_double" => 1, "json_encode" => 1, "json_decode" => 1, "is_object" => 1, "strtotime" => 1, "gettype" => 1, "is_double" => 1, "json_encode" => 1, "json_decode" => 1,
"ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 1 "ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 1
); );
/** /**
@ -292,27 +304,47 @@ class Fenom
/** /**
* *
* @param callable $cb * @param callable $cb
* @return self
*/ */
public function addPreCompileFilter($cb) public function addPreFilter($cb)
{ {
$this->_on_pre_cmp[] = $cb; $this->pre_filters[] = $cb;
return $this;
}
public function getPreFilters() {
return $this->pre_filters;
} }
/** /**
* *
* @param callable $cb * @param callable $cb
* @return self
*/ */
public function addPostCompileFilter($cb) public function addPostFilter($cb)
{ {
$this->_on_post_cmp[] = $cb; $this->post_filters[] = $cb;
return $this;
}
public function getPostFilters() {
return $this->post_filters;
} }
/** /**
* @param callable $cb * @param callable $cb
* @return self
*/ */
public function addCompileFilter($cb) public function addFilter($cb)
{ {
$this->_on_cmp[] = $cb; $this->filters[] = $cb;
return $this;
}
public function getFilters() {
return $this->filters;
} }
/** /**

View File

@ -8,8 +8,8 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Fenom; namespace Fenom;
use Fenom, use Fenom;
Fenom\Error\UnexpectedTokenException; use Fenom\Error\UnexpectedTokenException;
use Fenom\Error\CompileException; use Fenom\Error\CompileException;
use Fenom\Error\InvalidUsageException; use Fenom\Error\InvalidUsageException;
use Fenom\Error\SecurityException; use Fenom\Error\SecurityException;
@ -97,7 +97,7 @@ class Template extends Render
private $_before; private $_before;
private $_filter = array(); private $_filters = array();
private static $_checkers = array( private static $_checkers = array(
'integer' => 'is_int(%s)', 'integer' => 'is_int(%s)',
@ -136,6 +136,7 @@ class Template extends Render
{ {
$this->_fenom = $fenom; $this->_fenom = $fenom;
$this->_options = $options; $this->_options = $options;
$this->_filters = $this->_fenom->getFilters();
} }
/** /**
@ -196,6 +197,9 @@ class Template extends Render
{ {
$end = $pos = 0; $end = $pos = 0;
$this->escape = $this->_options & Fenom::AUTO_ESCAPE; $this->escape = $this->_options & Fenom::AUTO_ESCAPE;
foreach($this->_fenom->getPreFilters() as $filter) {
$this->_src = call_user_func($filter, $this->_src, $this);
}
while (($start = strpos($this->_src, '{', $pos)) !== false) { // search open-symbol of tags while (($start = strpos($this->_src, '{', $pos)) !== false) { // search open-symbol of tags
switch ($this->_src[$start + 1]) { // check next character switch ($this->_src[$start + 1]) { // check next character
@ -275,11 +279,15 @@ class Template extends Render
} }
} }
$this->addDepend($this); // for 'verify' performance $this->addDepend($this); // for 'verify' performance
foreach($this->_fenom->getPostFilters() as $filter) {
$this->_body = call_user_func($filter, $this->_body, $this);
}
} }
/** /**
* Execute some code in loading cache * Execute some code at loading cache
* @param $code * @param $code
* @return void
*/ */
public function before($code) public function before($code)
{ {
@ -303,15 +311,18 @@ class Template extends Render
private function _appendText($text) private function _appendText($text)
{ {
$this->_line += substr_count($text, "\n"); $this->_line += substr_count($text, "\n");
if ($this->_filter) { if ($this->_filters) {
if (strpos($text, "<?") === false) { if (strpos($text, "<?") === false) {
foreach ($this->_filters as $filter) {
$text = call_user_func($filter, $text, $this);
}
$this->_body .= $text; $this->_body .= $text;
} else { } else {
$fragments = explode("<?", $text); $fragments = explode("<?", $text);
foreach ($fragments as &$fragment) { foreach ($fragments as &$fragment) {
if ($fragment) { if ($fragment) {
foreach ($this->_filter as $filter) { foreach ($this->_filters as $filter) {
$fragment = call_user_func($filter, $fragment); $fragment = call_user_func($filter, $fragment, $this);
} }
} }
} }

View File

@ -47,7 +47,7 @@ class MacrosTest extends TestCase
$this->tpl("macro_recursive.tpl", '{macro factorial(num)} $this->tpl("macro_recursive.tpl", '{macro factorial(num)}
{if $num} {if $num}
{$num} {macro.factorial num=$num-1} {$num} {macro.factorial num=$num-1} {$num}
{/if} {/if}
{/macro} {/macro}
@ -104,6 +104,6 @@ class MacrosTest extends TestCase
$this->fenom->compile('macro_recursive.tpl'); $this->fenom->compile('macro_recursive.tpl');
$this->fenom->flush(); $this->fenom->flush();
$tpl = $this->fenom->getTemplate('macro_recursive.tpl'); $tpl = $this->fenom->getTemplate('macro_recursive.tpl');
$this->assertSame("10 9 8 7 6 5 4 3 2 1", Modifier::strip($tpl->fetch(array()), true)); $this->assertSame("10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10", Modifier::strip($tpl->fetch(array()), true));
} }
} }

View File

@ -114,4 +114,24 @@ class FenomTest extends \Fenom\TestCase
// printf("remove %010b from option %010b, flags %010b\n", $option, $this->fenom->getOptions(), $flags & ~$option); // printf("remove %010b from option %010b, flags %010b\n", $option, $this->fenom->getOptions(), $flags & ~$option);
// $this->assertSame($this->fenom->getOptions(), $flags & ~$option); // $this->assertSame($this->fenom->getOptions(), $flags & ~$option);
} }
public function testFilter() {
$punit = $this;
$this->fenom->addPreFilter(function ($src, $tpl) use ($punit) {
$this->assertInstanceOf('Fenom\Template', $tpl);
return "== $src ==";
});
$this->fenom->addPostFilter(function ($code, $tpl) use ($punit) {
$this->assertInstanceOf('Fenom\Template', $tpl);
return "+++ $code +++";
});
$this->fenom->addFilter(function ($text, $tpl) use ($punit) {
$this->assertInstanceOf('Fenom\Template', $tpl);
return "|--- $text ---|";
});
$this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} god {/var} world')->fetch(array()));
}
} }