diff --git a/src/Fenom.php b/src/Fenom.php index 17cdefc..20fd6d5 100644 --- a/src/Fenom.php +++ b/src/Fenom.php @@ -844,16 +844,31 @@ class Fenom } /** - * Add global accessor ($.) + * Add global accessor as PHP code ($.) * @param string $name * @param mixed $accessor * @param string $parser * @return Fenom */ - public function addAccessorSmart($name, $accessor, $parser) { + public function addAccessorSmart($name, $accessor, $parser = self::ACCESSOR_VAR) + { $this->_accessors[$name] = array( "accessor" => $accessor, - "parser" => $parser + "parser" => $parser, + ); + return $this; + } + + /** + * Add global accessor handler as callback ($.X) + * @param string $name + * @param callable $callback + * @return Fenom + */ + public function addAccessorCallback($name, callable $callback) + { + $this->_accessors[$name] = array( + "callback" => $callback ); return $this; } @@ -872,11 +887,17 @@ class Fenom /** * Get an accessor * @param string $name + * @param string $key * @return callable */ - public function getAccessor($name) { + public function getAccessor($name, $key = null) + { if(isset($this->_accessors[$name])) { - return $this->_accessors[$name]; + if($key) { + return $this->_accessors[$name][$key]; + } else { + return $this->_accessors[$name]; + } } else { return false; } @@ -888,7 +909,8 @@ class Fenom * @param string $pattern * @return $this */ - public function addCallFilter($pattern) { + public function addCallFilter($pattern) + { $this->call_filters[] = $pattern; return $this; } @@ -1029,7 +1051,7 @@ class Fenom */ protected function _load($template, $opts) { - $file_name = $this->getCompilePath($template, $opts); + $file_name = $this->getCompileName($template, $opts); if (is_file($this->_compile_dir . "/" . $file_name)) { $fenom = $this; // used in template $_tpl = include($this->_compile_dir . "/" . $file_name); @@ -1047,11 +1069,11 @@ class Fenom /** * Generate unique name of compiled template * - * @param string $tpl - * @param int $options + * @param string|string[] $tpl + * @param int $options additional options * @return string */ - public function getCompilePath($tpl, $options = 0) + public function getCompileName($tpl, $options = 0) { $options = $this->_options | $options; if (is_array($tpl)) { @@ -1086,7 +1108,7 @@ class Fenom } } if ($store) { - $cache_name = $this->getCompilePath($tpl, $options); + $cache_name = $this->getCompileName($tpl, $options); $compile_path = $this->_compile_dir . "/" . $cache_name . "." . mt_rand(0, 100000) . ".tmp"; if(!file_put_contents($compile_path, $template->getTemplateCode())) { throw new \RuntimeException("Can't to write to the file $compile_path. Directory " . $this->_compile_dir . " is writable?"); diff --git a/src/Fenom/Compiler.php b/src/Fenom/Compiler.php index a598122..f72e52b 100644 --- a/src/Fenom/Compiler.php +++ b/src/Fenom/Compiler.php @@ -964,7 +964,7 @@ class Compiler return; } $tokens->next(); - if($tokens->is('(') || !$tokens->isNext(')')){ + if ($tokens->is('(') || !$tokens->isNext(')')) { $tokens->next(); while ($tokens->is(Tokenizer::MACRO_STRING, T_VARIABLE)) { $param = $tokens->current(); diff --git a/src/Fenom/Template.php b/src/Fenom/Template.php index edc18c6..a7624cb 100644 --- a/src/Fenom/Template.php +++ b/src/Fenom/Template.php @@ -1003,12 +1003,18 @@ class Template extends Render $is_var = false; if($parser) { if(is_array($parser)) { - return call_user_func_array($parser['parser'], array($parser['accessor'], $tokens->next(), $this, &$is_var)); + if(isset($parser['callback'])) { + $tokens->next(); + return 'call_user_func($tpl->getStorage()->getAccessor('.var_export($accessor, true). + ', "callback"), '.var_export($accessor, true).', $tpl, $var)'; + } else { + return call_user_func_array($parser['parser'], array($parser['accessor'], $tokens->next(), $this, &$is_var)); + } } else { return call_user_func_array($parser, array($tokens->next(), $this, &$is_var)); } } else { - throw new \RuntimeException("Unknown accessor '$accessor'"); + throw new \RuntimeException("Unknown accessor '\$.$accessor'"); } } @@ -1025,7 +1031,7 @@ class Template extends Render { $empty = $tokens->is('?'); $tokens->next(); - if ($tokens->is(":")) { + if ($tokens->is(":", "?")) { $tokens->next(); if ($empty) { if ($is_var) { diff --git a/tests/cases/Fenom/AccessorTest.php b/tests/cases/Fenom/AccessorTest.php index 9b09100..e85a082 100644 --- a/tests/cases/Fenom/AccessorTest.php +++ b/tests/cases/Fenom/AccessorTest.php @@ -256,4 +256,20 @@ class AccessorTest extends TestCase $this->fenom->addAccessorSmart($name, $accessor, $type); $this->assertRender($code, $result, $this->getVars()); } + + /** + * @group dev + */ + public function testCallbackAccessor() { + $index = 1; + $this->fenom->addAccessorCallback('index', function($name, $template, $vars) use (&$index) { + $this->assertInstanceOf('Fenom\Render', $template); + $this->assertSame(1, $vars['one']); + $this->assertSame('index', $name); + + return $index++; + }); + + $this->assertRender('{$.index}, {$.index}, {$.index}', '1, 2, 3', $this->getVars()); + } } \ No newline at end of file