From f1d252a3ccdc56257c8141361a4daa023b35606d Mon Sep 17 00:00:00 2001 From: bzick Date: Thu, 1 Aug 2013 01:05:19 +0400 Subject: [PATCH] Add filters for templates (#30) --- src/Fenom.php | 86 ++++++++++++++++++++++---------- src/Fenom/Template.php | 25 +++++++--- tests/cases/Fenom/MacrosTest.php | 4 +- tests/cases/FenomTest.php | 20 ++++++++ 4 files changed, 99 insertions(+), 36 deletions(-) diff --git a/src/Fenom.php b/src/Fenom.php index bdaae07..6ff7393 100644 --- a/src/Fenom.php +++ b/src/Fenom.php @@ -7,8 +7,8 @@ * For the full copyright and license information, please view the license.md * file that was distributed with this source code. */ -use Fenom\Template, - Fenom\ProviderInterface; +use Fenom\ProviderInterface; +use Fenom\Template; /** * Fenom Template Engine @@ -67,10 +67,26 @@ class Fenom "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 */ protected $_storage = array(); + /** * @var string compile directory */ @@ -81,10 +97,6 @@ class Fenom */ protected $_options = 0; - protected $_on_pre_cmp = array(); - protected $_on_cmp = array(); - protected $_on_post_cmp = array(); - /** * @var ProviderInterface */ @@ -98,28 +110,28 @@ class Fenom * @var string[] list of modifiers [modifier_name => callable] */ protected $_modifiers = array( - "upper" => 'strtoupper', - "up" => 'strtoupper', - "lower" => 'strtolower', - "low" => 'strtolower', + "upper" => 'strtoupper', + "up" => 'strtoupper', + "lower" => 'strtolower', + "low" => 'strtolower', "date_format" => 'Fenom\Modifier::dateFormat', - "date" => 'Fenom\Modifier::date', - "truncate" => 'Fenom\Modifier::truncate', - "escape" => 'Fenom\Modifier::escape', - "e" => 'Fenom\Modifier::escape', // alias of escape - "unescape" => 'Fenom\Modifier::unescape', - "strip" => 'Fenom\Modifier::strip', - "length" => 'Fenom\Modifier::length', - "iterable" => 'Fenom\Modifier::isIterable' + "date" => 'Fenom\Modifier::date', + "truncate" => 'Fenom\Modifier::truncate', + "escape" => 'Fenom\Modifier::escape', + "e" => 'Fenom\Modifier::escape', // alias of escape + "unescape" => 'Fenom\Modifier::unescape', + "strip" => 'Fenom\Modifier::strip', + "length" => 'Fenom\Modifier::length', + "iterable" => 'Fenom\Modifier::isIterable' ); /** * @var array of allowed PHP functions */ protected $_allowed_funcs = array( - "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, - "ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 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, + "ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 1 ); /** @@ -292,27 +304,47 @@ class Fenom /** * * @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 + * @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 + * @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; } /** diff --git a/src/Fenom/Template.php b/src/Fenom/Template.php index 63efc36..3dc6293 100644 --- a/src/Fenom/Template.php +++ b/src/Fenom/Template.php @@ -8,8 +8,8 @@ * file that was distributed with this source code. */ namespace Fenom; -use Fenom, - Fenom\Error\UnexpectedTokenException; +use Fenom; +use Fenom\Error\UnexpectedTokenException; use Fenom\Error\CompileException; use Fenom\Error\InvalidUsageException; use Fenom\Error\SecurityException; @@ -97,7 +97,7 @@ class Template extends Render private $_before; - private $_filter = array(); + private $_filters = array(); private static $_checkers = array( 'integer' => 'is_int(%s)', @@ -136,6 +136,7 @@ class Template extends Render { $this->_fenom = $fenom; $this->_options = $options; + $this->_filters = $this->_fenom->getFilters(); } /** @@ -196,6 +197,9 @@ class Template extends Render { $end = $pos = 0; $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 switch ($this->_src[$start + 1]) { // check next character @@ -275,11 +279,15 @@ class Template extends Render } } $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 + * @return void */ public function before($code) { @@ -303,15 +311,18 @@ class Template extends Render private function _appendText($text) { $this->_line += substr_count($text, "\n"); - if ($this->_filter) { + if ($this->_filters) { if (strpos($text, "_filters as $filter) { + $text = call_user_func($filter, $text, $this); + } $this->_body .= $text; } else { $fragments = explode("_filter as $filter) { - $fragment = call_user_func($filter, $fragment); + foreach ($this->_filters as $filter) { + $fragment = call_user_func($filter, $fragment, $this); } } } diff --git a/tests/cases/Fenom/MacrosTest.php b/tests/cases/Fenom/MacrosTest.php index 42e36c6..ded112f 100644 --- a/tests/cases/Fenom/MacrosTest.php +++ b/tests/cases/Fenom/MacrosTest.php @@ -47,7 +47,7 @@ class MacrosTest extends TestCase $this->tpl("macro_recursive.tpl", '{macro factorial(num)} {if $num} - {$num} {macro.factorial num=$num-1} + {$num} {macro.factorial num=$num-1} {$num} {/if} {/macro} @@ -104,6 +104,6 @@ class MacrosTest extends TestCase $this->fenom->compile('macro_recursive.tpl'); $this->fenom->flush(); $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)); } } diff --git a/tests/cases/FenomTest.php b/tests/cases/FenomTest.php index 4c49846..0a1a4bd 100644 --- a/tests/cases/FenomTest.php +++ b/tests/cases/FenomTest.php @@ -114,4 +114,24 @@ class FenomTest extends \Fenom\TestCase // printf("remove %010b from option %010b, flags %010b\n", $option, $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())); + } } \ No newline at end of file