Add hook for loads modifiers and tags

This commit is contained in:
bzick 2013-07-24 19:37:07 +04:00
parent 33a2e685e3
commit d5dcfbe410
6 changed files with 72 additions and 28 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG CHANGELOG
========= =========
## 1.2.0
- Feature #29: add {unset} tag
- Add hook for loading modifiers and tags
## 1.1.0 ## 1.1.0
- Bug #19: Bug with "if" expressions starting with "(" - Bug #19: Bug with "if" expressions starting with "("

View File

@ -16,7 +16,7 @@ use Fenom\Template,
* @author Ivan Shalganov <a.cobest@gmail.com> * @author Ivan Shalganov <a.cobest@gmail.com>
*/ */
class Fenom { class Fenom {
const VERSION = '1.1'; const VERSION = '1.2';
/* Actions */ /* Actions */
const INLINE_COMPILER = 1; const INLINE_COMPILER = 1;
@ -27,7 +27,7 @@ class Fenom {
/* Options */ /* Options */
const DENY_METHODS = 0x10; const DENY_METHODS = 0x10;
const DENY_INLINE_FUNCS = 0x20; const DENY_NATIVE_FUNCS = 0x20;
const FORCE_INCLUDE = 0x40; const FORCE_INCLUDE = 0x40;
const AUTO_RELOAD = 0x80; const AUTO_RELOAD = 0x80;
const FORCE_COMPILE = 0x100; const FORCE_COMPILE = 0x100;
@ -37,6 +37,9 @@ class Fenom {
const AUTO_TRIM = 0x1000; // reserved const AUTO_TRIM = 0x1000; // reserved
const DENY_STATICS = 0x2000; // reserved const DENY_STATICS = 0x2000; // reserved
/* @deprecated */
const DENY_INLINE_FUNCS = 0x20;
/* Default parsers */ /* Default parsers */
const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose'; const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose';
const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser'; const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser';
@ -50,7 +53,7 @@ class Fenom {
*/ */
private static $_options_list = array( private static $_options_list = array(
"disable_methods" => self::DENY_METHODS, "disable_methods" => self::DENY_METHODS,
"disable_native_funcs" => self::DENY_INLINE_FUNCS, "disable_native_funcs" => self::DENY_NATIVE_FUNCS,
"disable_cache" => self::DISABLE_CACHE, "disable_cache" => self::DISABLE_CACHE,
"force_compile" => self::FORCE_COMPILE, "force_compile" => self::FORCE_COMPILE,
"auto_reload" => self::AUTO_RELOAD, "auto_reload" => self::AUTO_RELOAD,
@ -461,40 +464,69 @@ class Fenom {
/** /**
* Return modifier function * Return modifier function
* *
* @param $modifier * @param string $modifier
* @param Fenom\Template $template
* @return mixed * @return mixed
* @throws \Exception
*/ */
public function getModifier($modifier) { public function getModifier($modifier, Template $template = null) {
if(isset($this->_modifiers[$modifier])) { if(isset($this->_modifiers[$modifier])) {
return $this->_modifiers[$modifier]; return $this->_modifiers[$modifier];
} elseif($this->isAllowedFunction($modifier)) { } elseif($this->isAllowedFunction($modifier)) {
return $modifier; return $modifier;
} else { } else {
throw new \Exception("Modifier $modifier not found"); return $this->_loadModifier($modifier, $template);
} }
} }
/** /**
* Return function * @param string $modifier
* * @param Fenom\Template $template
* @return bool
*/
protected function _loadModifier($modifier, $template) {
return false;
}
/**
* @param string $function * @param string $function
* @param Fenom\Template $template
* @return bool|string
* @deprecated
*/
public function getFunction($function, Template $template = null) {
return $this->getTag($function, $template);
}
/**
* Returns tag info
*
* @param string $tag
* @param Fenom\Template $template
* @return string|bool * @return string|bool
*/ */
public function getFunction($function) { public function getTag($tag, Template $template = null) {
if(isset($this->_actions[$function])) { if(isset($this->_actions[$tag])) {
return $this->_actions[$function]; return $this->_actions[$tag];
} else { } else {
return false; return $this->_loadTag($tag, $template);
} }
} }
/**
* @param $tag
* @param Fenom\Template $template
* @return bool
*/
protected function _loadTag($tag, Template $template) {
return false;
}
/** /**
* @param string $function * @param string $function
* @return bool * @return bool
*/ */
public function isAllowedFunction($function) { public function isAllowedFunction($function) {
if($this->_options & self::DENY_INLINE_FUNCS) { if($this->_options & self::DENY_NATIVE_FUNCS) {
return isset($this->_allowed_funcs[$function]); return isset($this->_allowed_funcs[$function]);
} else { } else {
return is_callable($function); return is_callable($function);

View File

@ -879,7 +879,7 @@ class Compiler {
$tpl->escape = false; $tpl->escape = false;
if($tokens->is(':')) { if($tokens->is(':')) {
$func = $tokens->getNext(Tokenizer::MACRO_STRING); $func = $tokens->getNext(Tokenizer::MACRO_STRING);
$tag = $tpl->getStorage()->getFunction($func); $tag = $tpl->getStorage()->getTag($func, $tpl);
if($tag["type"] == \Fenom::INLINE_FUNCTION) { if($tag["type"] == \Fenom::INLINE_FUNCTION) {
$code = $tpl->parseAct($tokens); $code = $tpl->parseAct($tokens);
} elseif ($tag["type"] == \Fenom::BLOCK_FUNCTION) { } elseif ($tag["type"] == \Fenom::BLOCK_FUNCTION) {

View File

@ -520,22 +520,22 @@ class Template extends Render {
return $this->parseMacro($tokens, $name); return $this->parseMacro($tokens, $name);
} }
if($act = $this->_fenom->getFunction($action)) { // call some function if($tag = $this->_fenom->getTag($action, $this)) { // call some function
switch($act["type"]) { switch($tag["type"]) {
case Fenom::BLOCK_COMPILER: case Fenom::BLOCK_COMPILER:
$scope = new Scope($action, $this, $this->_line, $act, count($this->_stack), $this->_body); $scope = new Scope($action, $this, $this->_line, $tag, count($this->_stack), $this->_body);
$code = $scope->open($tokens); $code = $scope->open($tokens);
if(!$scope->is_closed) { if(!$scope->is_closed) {
array_push($this->_stack, $scope); array_push($this->_stack, $scope);
} }
return $code; return $code;
case Fenom::INLINE_COMPILER: case Fenom::INLINE_COMPILER:
return call_user_func($act["parser"], $tokens, $this); return call_user_func($tag["parser"], $tokens, $this);
case Fenom::INLINE_FUNCTION: case Fenom::INLINE_FUNCTION:
return $this->out(call_user_func($act["parser"], $act["function"], $tokens, $this)); return $this->out(call_user_func($tag["parser"], $tag["function"], $tokens, $this));
case Fenom::BLOCK_FUNCTION: case Fenom::BLOCK_FUNCTION:
$scope = new Scope($action, $this, $this->_line, $act, count($this->_stack), $this->_body); $scope = new Scope($action, $this, $this->_line, $tag, count($this->_stack), $this->_body);
$scope->setFuncName($act["function"]); $scope->setFuncName($tag["function"]);
array_push($this->_stack, $scope); array_push($this->_stack, $scope);
$scope->escape = $this->escape; $scope->escape = $this->escape;
$this->escape = false; $this->escape = false;
@ -562,10 +562,10 @@ class Template extends Render {
* *
* @static * @static
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param bool $required * @param bool $required
* @throws \LogicException
* @throws UnexpectedTokenException
* @throws TokenizeException * @throws TokenizeException
* @throws UnexpectedTokenException
* @throws \Exception
* @return string * @return string
*/ */
public function parseExp(Tokenizer $tokens, $required = false) { public function parseExp(Tokenizer $tokens, $required = false) {
@ -625,6 +625,9 @@ class Template extends Render {
$_exp[] = $tokens->getAndNext(); $_exp[] = $tokens->getAndNext();
} elseif($tokens->isNext("(") && !$tokens->getWhitespace()) { } elseif($tokens->isNext("(") && !$tokens->getWhitespace()) {
$func = $this->_fenom->getModifier($tokens->current()); $func = $this->_fenom->getModifier($tokens->current());
if(!$func) {
throw new \Exception("Function ".$tokens->getAndNext()." not found");
}
$tokens->next(); $tokens->next();
$func = $func.$this->parseArgs($tokens); $func = $func.$this->parseArgs($tokens);
if($tokens->is('|')) { if($tokens->is('|')) {
@ -1063,8 +1066,10 @@ class Template extends Render {
*/ */
public function parseModifier(Tokenizer $tokens, $value) { public function parseModifier(Tokenizer $tokens, $value) {
while($tokens->is("|")) { while($tokens->is("|")) {
$mods = $this->_fenom->getModifier( $modifier_name = $tokens->getNext(Tokenizer::MACRO_STRING) ); $mods = $this->_fenom->getModifier($tokens->getNext(Tokenizer::MACRO_STRING) );
if(!$mods) {
throw new \Exception("Modifier ".$tokens->current()." not found");
}
$tokens->next(); $tokens->next();
$args = array(); $args = array();

View File

@ -9,6 +9,8 @@ define('FENOM_RESOURCES', __DIR__."/resources");
require_once FENOM_RESOURCES."/actions.php"; require_once FENOM_RESOURCES."/actions.php";
require_once __DIR__."/TestCase.php"; require_once __DIR__."/TestCase.php";
ini_set('date.timezone', 'Europe/Moscow');
function drop() { function drop() {
call_user_func_array("var_dump", func_get_args()); call_user_func_array("var_dump", func_get_args());
$e = new Exception(); $e = new Exception();

View File

@ -319,7 +319,7 @@ class TemplateTest extends TestCase {
array('Create: {var $v = --$a++} Result: {$v} end', 'Fenom\CompileException', "Can not use two increments and/or decrements for one variable"), array('Create: {var $v = --$a++} Result: {$v} end', 'Fenom\CompileException', "Can not use two increments and/or decrements for one variable"),
array('Create: {var $v = $a|upper++} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '++'"), array('Create: {var $v = $a|upper++} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '++'"),
array('Create: {var $v = max($a,2)++} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '++'"), array('Create: {var $v = max($a,2)++} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '++'"),
array('Create: {var $v = max($a,2)} Result: {$v} end', 'Fenom\CompileException', "Modifier max not found", Fenom::DENY_INLINE_FUNCS), array('Create: {var $v = max($a,2)} Result: {$v} end', 'Fenom\CompileException', "Function max not found", Fenom::DENY_NATIVE_FUNCS),
array('Create: {var $v = 4*} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '*'"), array('Create: {var $v = 4*} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '*'"),
array('Create: {var $v = ""$a} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '\$a'"), array('Create: {var $v = ""$a} Result: {$v} end', 'Fenom\CompileException', "Unexpected token '\$a'"),
array('Create: {var $v = [1,2} Result: {$v} end', 'Fenom\CompileException', "Unexpected end of expression"), array('Create: {var $v = [1,2} Result: {$v} end', 'Fenom\CompileException', "Unexpected end of expression"),