mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Reformat. Fix pipe. Add more tests
This commit is contained in:
parent
6f969ee124
commit
cd490d2bf6
337
src/Fenom.php
337
src/Fenom.php
@ -20,33 +20,33 @@ class Fenom
|
|||||||
const VERSION = '2.0';
|
const VERSION = '2.0';
|
||||||
/* Actions */
|
/* Actions */
|
||||||
const INLINE_COMPILER = 1;
|
const INLINE_COMPILER = 1;
|
||||||
const BLOCK_COMPILER = 5;
|
const BLOCK_COMPILER = 5;
|
||||||
const INLINE_FUNCTION = 2;
|
const INLINE_FUNCTION = 2;
|
||||||
const BLOCK_FUNCTION = 7;
|
const BLOCK_FUNCTION = 7;
|
||||||
|
|
||||||
/* Options */
|
/* Options */
|
||||||
const DENY_ACCESSOR = 0x8;
|
const DENY_ACCESSOR = 0x8;
|
||||||
const DENY_METHODS = 0x10;
|
const DENY_METHODS = 0x10;
|
||||||
const DENY_NATIVE_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;
|
||||||
const AUTO_ESCAPE = 0x200;
|
const AUTO_ESCAPE = 0x200;
|
||||||
const DISABLE_CACHE = 0x400;
|
const DISABLE_CACHE = 0x400;
|
||||||
const FORCE_VERIFY = 0x800;
|
const FORCE_VERIFY = 0x800;
|
||||||
const AUTO_TRIM = 0x1000; // reserved
|
const AUTO_TRIM = 0x1000; // reserved
|
||||||
const DENY_STATICS = 0x2000;
|
const DENY_STATICS = 0x2000;
|
||||||
const AUTO_STRIP = 0x4000;
|
const AUTO_STRIP = 0x4000;
|
||||||
|
|
||||||
/* @deprecated */
|
/* @deprecated */
|
||||||
const DENY_INLINE_FUNCS = 0x20;
|
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';
|
||||||
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
|
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
|
||||||
const DEFAULT_FUNC_CLOSE = 'Fenom\Compiler::stdFuncClose';
|
const DEFAULT_FUNC_CLOSE = 'Fenom\Compiler::stdFuncClose';
|
||||||
const SMART_FUNC_PARSER = 'Fenom\Compiler::smartFuncParser';
|
const SMART_FUNC_PARSER = 'Fenom\Compiler::smartFuncParser';
|
||||||
|
|
||||||
const MAX_MACRO_RECURSIVE = 32;
|
const MAX_MACRO_RECURSIVE = 32;
|
||||||
|
|
||||||
@ -55,17 +55,17 @@ class Fenom
|
|||||||
* @see setOptions
|
* @see setOptions
|
||||||
*/
|
*/
|
||||||
private static $_options_list = array(
|
private static $_options_list = array(
|
||||||
"disable_accessor" => self::DENY_ACCESSOR,
|
"disable_accessor" => self::DENY_ACCESSOR,
|
||||||
"disable_methods" => self::DENY_METHODS,
|
"disable_methods" => self::DENY_METHODS,
|
||||||
"disable_native_funcs" => self::DENY_NATIVE_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,
|
||||||
"force_include" => self::FORCE_INCLUDE,
|
"force_include" => self::FORCE_INCLUDE,
|
||||||
"auto_escape" => self::AUTO_ESCAPE,
|
"auto_escape" => self::AUTO_ESCAPE,
|
||||||
"force_verify" => self::FORCE_VERIFY,
|
"force_verify" => self::FORCE_VERIFY,
|
||||||
"auto_trim" => self::AUTO_TRIM,
|
"auto_trim" => self::AUTO_TRIM,
|
||||||
"disable_statics" => self::DENY_STATICS,
|
"disable_statics" => self::DENY_STATICS,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,138 +121,153 @@ 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, 'constant' => 1,
|
"count" => 1,
|
||||||
"is_object" => 1, "strtotime" => 1, "gettype" => 1, "is_double" => 1, "json_encode" => 1, "json_decode" => 1,
|
"is_string" => 1,
|
||||||
"ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 1
|
"is_array" => 1,
|
||||||
|
"is_numeric" => 1,
|
||||||
|
"is_int" => 1,
|
||||||
|
'constant' => 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
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array[] of compilers and functions
|
* @var array[] of compilers and functions
|
||||||
*/
|
*/
|
||||||
protected $_actions = array(
|
protected $_actions = array(
|
||||||
'foreach' => array( // {foreach ...} {break} {continue} {foreachelse} {/foreach}
|
'foreach' => array( // {foreach ...} {break} {continue} {foreachelse} {/foreach}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::foreachOpen',
|
'open' => 'Fenom\Compiler::foreachOpen',
|
||||||
'close' => 'Fenom\Compiler::foreachClose',
|
'close' => 'Fenom\Compiler::foreachClose',
|
||||||
'tags' => array(
|
'tags' => array(
|
||||||
'foreachelse' => 'Fenom\Compiler::foreachElse',
|
'foreachelse' => 'Fenom\Compiler::foreachElse',
|
||||||
'break' => 'Fenom\Compiler::tagBreak',
|
'break' => 'Fenom\Compiler::tagBreak',
|
||||||
'continue' => 'Fenom\Compiler::tagContinue',
|
'continue' => 'Fenom\Compiler::tagContinue',
|
||||||
),
|
),
|
||||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||||
),
|
),
|
||||||
'if' => array( // {if ...} {elseif ...} {else} {/if}
|
'if' => array( // {if ...} {elseif ...} {else} {/if}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::ifOpen',
|
'open' => 'Fenom\Compiler::ifOpen',
|
||||||
'close' => 'Fenom\Compiler::stdClose',
|
'close' => 'Fenom\Compiler::stdClose',
|
||||||
'tags' => array(
|
'tags' => array(
|
||||||
'elseif' => 'Fenom\Compiler::tagElseIf',
|
'elseif' => 'Fenom\Compiler::tagElseIf',
|
||||||
'else' => 'Fenom\Compiler::tagElse'
|
'else' => 'Fenom\Compiler::tagElse'
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'switch' => array( // {switch ...} {case ..., ...} {default} {/switch}
|
'switch' => array( // {switch ...} {case ..., ...} {default} {/switch}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::switchOpen',
|
'open' => 'Fenom\Compiler::switchOpen',
|
||||||
'close' => 'Fenom\Compiler::switchClose',
|
'close' => 'Fenom\Compiler::switchClose',
|
||||||
'tags' => array(
|
'tags' => array(
|
||||||
'case' => 'Fenom\Compiler::tagCase',
|
'case' => 'Fenom\Compiler::tagCase',
|
||||||
'default' => 'Fenom\Compiler::tagDefault'
|
'default' => 'Fenom\Compiler::tagDefault'
|
||||||
),
|
),
|
||||||
'float_tags' => array('break' => 1)
|
'float_tags' => array('break' => 1)
|
||||||
),
|
),
|
||||||
'for' => array( // {for ...} {break} {continue} {/for}
|
'for' => array( // {for ...} {break} {continue} {/for}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::forOpen',
|
'open' => 'Fenom\Compiler::forOpen',
|
||||||
'close' => 'Fenom\Compiler::forClose',
|
'close' => 'Fenom\Compiler::forClose',
|
||||||
'tags' => array(
|
'tags' => array(
|
||||||
'forelse' => 'Fenom\Compiler::forElse',
|
'forelse' => 'Fenom\Compiler::forElse',
|
||||||
'break' => 'Fenom\Compiler::tagBreak',
|
'break' => 'Fenom\Compiler::tagBreak',
|
||||||
'continue' => 'Fenom\Compiler::tagContinue',
|
'continue' => 'Fenom\Compiler::tagContinue',
|
||||||
),
|
),
|
||||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||||
),
|
),
|
||||||
'while' => array( // {while ...} {break} {continue} {/while}
|
'while' => array( // {while ...} {break} {continue} {/while}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::whileOpen',
|
'open' => 'Fenom\Compiler::whileOpen',
|
||||||
'close' => 'Fenom\Compiler::stdClose',
|
'close' => 'Fenom\Compiler::stdClose',
|
||||||
'tags' => array(
|
'tags' => array(
|
||||||
'break' => 'Fenom\Compiler::tagBreak',
|
'break' => 'Fenom\Compiler::tagBreak',
|
||||||
'continue' => 'Fenom\Compiler::tagContinue',
|
'continue' => 'Fenom\Compiler::tagContinue',
|
||||||
),
|
),
|
||||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||||
),
|
),
|
||||||
'include' => array( // {include ...}
|
'include' => array( // {include ...}
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagInclude'
|
'parser' => 'Fenom\Compiler::tagInclude'
|
||||||
),
|
),
|
||||||
'insert' => array( // {include ...}
|
'insert' => array( // {include ...}
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagInsert'
|
'parser' => 'Fenom\Compiler::tagInsert'
|
||||||
),
|
),
|
||||||
'var' => array( // {var ...}
|
'var' => array( // {var ...}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::varOpen',
|
'open' => 'Fenom\Compiler::varOpen',
|
||||||
'close' => 'Fenom\Compiler::varClose'
|
'close' => 'Fenom\Compiler::varClose'
|
||||||
),
|
),
|
||||||
'block' => array( // {block ...} {parent} {/block}
|
'block' => array( // {block ...} {parent} {/block}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::tagBlockOpen',
|
'open' => 'Fenom\Compiler::tagBlockOpen',
|
||||||
'close' => 'Fenom\Compiler::tagBlockClose',
|
'close' => 'Fenom\Compiler::tagBlockClose',
|
||||||
'tags' => array('parent' => 'Fenom\Compiler::tagParent'),
|
'tags' => array('parent' => 'Fenom\Compiler::tagParent'),
|
||||||
'float_tags' => array('parent' => 1)
|
'float_tags' => array('parent' => 1)
|
||||||
),
|
),
|
||||||
'extends' => array( // {extends ...}
|
'extends' => array( // {extends ...}
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagExtends'
|
'parser' => 'Fenom\Compiler::tagExtends'
|
||||||
),
|
),
|
||||||
'use' => array( // {use}
|
'use' => array( // {use}
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagUse'
|
'parser' => 'Fenom\Compiler::tagUse'
|
||||||
),
|
),
|
||||||
'filter' => array( // {filter} ... {/filter}
|
'filter' => array( // {filter} ... {/filter}
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::filterOpen',
|
'open' => 'Fenom\Compiler::filterOpen',
|
||||||
'close' => 'Fenom\Compiler::filterClose'
|
'close' => 'Fenom\Compiler::filterClose'
|
||||||
),
|
),
|
||||||
'macro' => array(
|
'macro' => array(
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::macroOpen',
|
'open' => 'Fenom\Compiler::macroOpen',
|
||||||
'close' => 'Fenom\Compiler::macroClose'
|
'close' => 'Fenom\Compiler::macroClose'
|
||||||
),
|
),
|
||||||
'import' => array(
|
'import' => array(
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagImport'
|
'parser' => 'Fenom\Compiler::tagImport'
|
||||||
),
|
),
|
||||||
'cycle' => array(
|
'cycle' => array(
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagCycle'
|
'parser' => 'Fenom\Compiler::tagCycle'
|
||||||
),
|
),
|
||||||
'raw' => array(
|
'raw' => array(
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => 'Fenom\Compiler::tagRaw'
|
'parser' => 'Fenom\Compiler::tagRaw'
|
||||||
),
|
),
|
||||||
'autoescape' => array(
|
'autoescape' => array(
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::autoescapeOpen',
|
'open' => 'Fenom\Compiler::autoescapeOpen',
|
||||||
'close' => 'Fenom\Compiler::autoescapeClose'
|
'close' => 'Fenom\Compiler::autoescapeClose'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -263,31 +278,31 @@ class Fenom
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_tests = array(
|
protected $_tests = array(
|
||||||
'integer' => 'is_int(%s)',
|
'integer' => 'is_int(%s)',
|
||||||
'int' => 'is_int(%s)',
|
'int' => 'is_int(%s)',
|
||||||
'float' => 'is_float(%s)',
|
'float' => 'is_float(%s)',
|
||||||
'double' => 'is_float(%s)',
|
'double' => 'is_float(%s)',
|
||||||
'decimal' => 'is_float(%s)',
|
'decimal' => 'is_float(%s)',
|
||||||
'string' => 'is_string(%s)',
|
'string' => 'is_string(%s)',
|
||||||
'bool' => 'is_bool(%s)',
|
'bool' => 'is_bool(%s)',
|
||||||
'boolean' => 'is_bool(%s)',
|
'boolean' => 'is_bool(%s)',
|
||||||
'number' => 'is_numeric(%s)',
|
'number' => 'is_numeric(%s)',
|
||||||
'numeric' => 'is_numeric(%s)',
|
'numeric' => 'is_numeric(%s)',
|
||||||
'scalar' => 'is_scalar(%s)',
|
'scalar' => 'is_scalar(%s)',
|
||||||
'object' => 'is_object(%s)',
|
'object' => 'is_object(%s)',
|
||||||
'callable' => 'is_callable(%s)',
|
'callable' => 'is_callable(%s)',
|
||||||
'callback' => 'is_callable(%s)',
|
'callback' => 'is_callable(%s)',
|
||||||
'array' => 'is_array(%s)',
|
'array' => 'is_array(%s)',
|
||||||
'iterable' => '\Fenom\Modifier::isIterable(%s)',
|
'iterable' => '\Fenom\Modifier::isIterable(%s)',
|
||||||
'const' => 'defined(%s)',
|
'const' => 'defined(%s)',
|
||||||
'template' => '$tpl->getStorage()->templateExists(%s)',
|
'template' => '$tpl->getStorage()->templateExists(%s)',
|
||||||
'empty' => 'empty(%s)',
|
'empty' => 'empty(%s)',
|
||||||
'set' => 'isset(%s)',
|
'set' => 'isset(%s)',
|
||||||
'_empty' => '!%s', // for none variable
|
'_empty' => '!%s', // for none variable
|
||||||
'_set' => '(%s !== null)', // for none variable
|
'_set' => '(%s !== null)', // for none variable
|
||||||
'odd' => '(%s & 1)',
|
'odd' => '(%s & 1)',
|
||||||
'even' => '!(%s %% 2)',
|
'even' => '!(%s %% 2)',
|
||||||
'third' => '!(%s %% 3)'
|
'third' => '!(%s %% 3)'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,7 +444,7 @@ class Fenom
|
|||||||
public function addCompiler($compiler, $parser)
|
public function addCompiler($compiler, $parser)
|
||||||
{
|
{
|
||||||
$this->_actions[$compiler] = array(
|
$this->_actions[$compiler] = array(
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => $parser
|
'parser' => $parser
|
||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
@ -444,7 +459,7 @@ class Fenom
|
|||||||
{
|
{
|
||||||
if (method_exists($storage, "tag" . $compiler)) {
|
if (method_exists($storage, "tag" . $compiler)) {
|
||||||
$this->_actions[$compiler] = array(
|
$this->_actions[$compiler] = array(
|
||||||
'type' => self::INLINE_COMPILER,
|
'type' => self::INLINE_COMPILER,
|
||||||
'parser' => array($storage, "tag" . $compiler)
|
'parser' => array($storage, "tag" . $compiler)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -460,13 +475,17 @@ class Fenom
|
|||||||
* @param array $tags
|
* @param array $tags
|
||||||
* @return Fenom
|
* @return Fenom
|
||||||
*/
|
*/
|
||||||
public function addBlockCompiler($compiler, $open_parser, $close_parser = self::DEFAULT_CLOSE_COMPILER, array $tags = array())
|
public function addBlockCompiler(
|
||||||
{
|
$compiler,
|
||||||
|
$open_parser,
|
||||||
|
$close_parser = self::DEFAULT_CLOSE_COMPILER,
|
||||||
|
array $tags = array()
|
||||||
|
) {
|
||||||
$this->_actions[$compiler] = array(
|
$this->_actions[$compiler] = array(
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => $open_parser,
|
'open' => $open_parser,
|
||||||
'close' => $close_parser ? : self::DEFAULT_CLOSE_COMPILER,
|
'close' => $close_parser ? : self::DEFAULT_CLOSE_COMPILER,
|
||||||
'tags' => $tags,
|
'tags' => $tags,
|
||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -482,8 +501,8 @@ class Fenom
|
|||||||
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array())
|
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array())
|
||||||
{
|
{
|
||||||
$c = array(
|
$c = array(
|
||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
"tags" => array(),
|
"tags" => array(),
|
||||||
"float_tags" => array()
|
"float_tags" => array()
|
||||||
);
|
);
|
||||||
if (method_exists($storage, $compiler . "Open")) {
|
if (method_exists($storage, $compiler . "Open")) {
|
||||||
@ -519,8 +538,8 @@ class Fenom
|
|||||||
public function addFunction($function, $callback, $parser = self::DEFAULT_FUNC_PARSER)
|
public function addFunction($function, $callback, $parser = self::DEFAULT_FUNC_PARSER)
|
||||||
{
|
{
|
||||||
$this->_actions[$function] = array(
|
$this->_actions[$function] = array(
|
||||||
'type' => self::INLINE_FUNCTION,
|
'type' => self::INLINE_FUNCTION,
|
||||||
'parser' => $parser,
|
'parser' => $parser,
|
||||||
'function' => $callback,
|
'function' => $callback,
|
||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
@ -534,8 +553,8 @@ class Fenom
|
|||||||
public function addFunctionSmart($function, $callback)
|
public function addFunctionSmart($function, $callback)
|
||||||
{
|
{
|
||||||
$this->_actions[$function] = array(
|
$this->_actions[$function] = array(
|
||||||
'type' => self::INLINE_FUNCTION,
|
'type' => self::INLINE_FUNCTION,
|
||||||
'parser' => self::SMART_FUNC_PARSER,
|
'parser' => self::SMART_FUNC_PARSER,
|
||||||
'function' => $callback,
|
'function' => $callback,
|
||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
@ -548,12 +567,16 @@ class Fenom
|
|||||||
* @param callable|string $parser_close
|
* @param callable|string $parser_close
|
||||||
* @return Fenom
|
* @return Fenom
|
||||||
*/
|
*/
|
||||||
public function addBlockFunction($function, $callback, $parser_open = self::DEFAULT_FUNC_OPEN, $parser_close = self::DEFAULT_FUNC_CLOSE)
|
public function addBlockFunction(
|
||||||
{
|
$function,
|
||||||
|
$callback,
|
||||||
|
$parser_open = self::DEFAULT_FUNC_OPEN,
|
||||||
|
$parser_close = self::DEFAULT_FUNC_CLOSE
|
||||||
|
) {
|
||||||
$this->_actions[$function] = array(
|
$this->_actions[$function] = array(
|
||||||
'type' => self::BLOCK_FUNCTION,
|
'type' => self::BLOCK_FUNCTION,
|
||||||
'open' => $parser_open,
|
'open' => $parser_open,
|
||||||
'close' => $parser_close,
|
'close' => $parser_close,
|
||||||
'function' => $callback,
|
'function' => $callback,
|
||||||
);
|
);
|
||||||
return $this;
|
return $this;
|
||||||
@ -766,17 +789,16 @@ class Fenom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Creates pipe-line of template's data to callback
|
||||||
*
|
* @param string $template name of the template
|
||||||
* @param string $template name of template
|
* @param callable $callback template's data handler
|
||||||
* @param array $vars
|
* @param array $vars
|
||||||
* @param callable $callback
|
* @param float $chunk amount of bytes of chunk
|
||||||
* @param float $chunk
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function pipe($template, $callback, array $vars = array(), $chunk = 1e6)
|
public function pipe($template, $callback, array $vars = array(), $chunk = 1e6)
|
||||||
{
|
{
|
||||||
ob_start($callback, $chunk, true);
|
ob_start($callback, $chunk, PHP_OUTPUT_HANDLER_STDFLAGS);
|
||||||
$data = $this->getTemplate($template)->display($vars);
|
$data = $this->getTemplate($template)->display($vars);
|
||||||
ob_end_flush();
|
ob_end_flush();
|
||||||
return $data;
|
return $data;
|
||||||
@ -792,7 +814,6 @@ class Fenom
|
|||||||
public function getTemplate($template, $options = 0)
|
public function getTemplate($template, $options = 0)
|
||||||
{
|
{
|
||||||
$options |= $this->_options;
|
$options |= $this->_options;
|
||||||
// var_dump($this->_options & self::FORCE_COMPILE);
|
|
||||||
if (is_array($template)) {
|
if (is_array($template)) {
|
||||||
$key = dechex($options) . "@" . implode(",", $template);
|
$key = dechex($options) . "@" . implode(",", $template);
|
||||||
} else {
|
} else {
|
||||||
@ -843,7 +864,7 @@ class Fenom
|
|||||||
$file_name = $this->_getCacheName($template, $opts);
|
$file_name = $this->_getCacheName($template, $opts);
|
||||||
if (is_file($this->_compile_dir . "/" . $file_name)) {
|
if (is_file($this->_compile_dir . "/" . $file_name)) {
|
||||||
$fenom = $this; // used in template
|
$fenom = $this; // used in template
|
||||||
$_tpl = include($this->_compile_dir . "/" . $file_name);
|
$_tpl = include($this->_compile_dir . "/" . $file_name);
|
||||||
/* @var Fenom\Render $_tpl */
|
/* @var Fenom\Render $_tpl */
|
||||||
if (!($this->_options & self::AUTO_RELOAD) || ($this->_options & self::AUTO_RELOAD) && $_tpl->isValid()) {
|
if (!($this->_options & self::AUTO_RELOAD) || ($this->_options & self::AUTO_RELOAD) && $_tpl->isValid()) {
|
||||||
return $_tpl;
|
return $_tpl;
|
||||||
@ -895,9 +916,9 @@ class Fenom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($store) {
|
if ($store) {
|
||||||
$cache = $this->_getCacheName($tpl, $options);
|
$cache = $this->_getCacheName($tpl, $options);
|
||||||
$tpl_tmp = tempnam($this->_compile_dir, $cache);
|
$tpl_tmp = tempnam($this->_compile_dir, $cache);
|
||||||
$tpl_fp = fopen($tpl_tmp, "w");
|
$tpl_fp = fopen($tpl_tmp, "w");
|
||||||
if (!$tpl_fp) {
|
if (!$tpl_fp) {
|
||||||
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory " . $this->_compile_dir . " is writable?");
|
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory " . $this->_compile_dir . " is writable?");
|
||||||
}
|
}
|
||||||
@ -972,14 +993,16 @@ class Fenom
|
|||||||
*/
|
*/
|
||||||
public static function registerAutoload($dir = null)
|
public static function registerAutoload($dir = null)
|
||||||
{
|
{
|
||||||
if(!$dir) {
|
if (!$dir) {
|
||||||
$dir = __DIR__;
|
$dir = __DIR__;
|
||||||
}
|
}
|
||||||
return spl_autoload_register(function($classname) use ($dir) {
|
return spl_autoload_register(
|
||||||
$file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $classname).'.php';
|
function ($classname) use ($dir) {
|
||||||
if(is_file($file)) {
|
$file = $dir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $classname) . '.php';
|
||||||
require_once $file;
|
if (is_file($file)) {
|
||||||
|
require_once $file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,10 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function tagInclude(Tokenizer $tokens, Tag $tag)
|
public static function tagInclude(Tokenizer $tokens, Tag $tag)
|
||||||
{
|
{
|
||||||
$tpl = $tag->tpl;
|
$tpl = $tag->tpl;
|
||||||
$name = false;
|
$name = false;
|
||||||
$cname = $tpl->parsePlainArg($tokens, $name);
|
$cname = $tpl->parsePlainArg($tokens, $name);
|
||||||
$p = $tpl->parseParams($tokens);
|
$p = $tpl->parseParams($tokens);
|
||||||
if ($name) {
|
if ($name) {
|
||||||
if ($tpl->getStorage()->getOptions() & \Fenom::FORCE_INCLUDE) {
|
if ($tpl->getStorage()->getOptions() & \Fenom::FORCE_INCLUDE) {
|
||||||
$inc = $tpl->getStorage()->compile($name, false);
|
$inc = $tpl->getStorage()->compile($name, false);
|
||||||
@ -134,17 +134,17 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function foreachOpen(Tokenizer $tokens, Tag $scope)
|
public static function foreachOpen(Tokenizer $tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
$p = array("index" => false, "first" => false, "last" => false);
|
$p = array("index" => false, "first" => false, "last" => false);
|
||||||
$key = null;
|
$key = null;
|
||||||
$before = $body = array();
|
$before = $body = array();
|
||||||
if ($tokens->is(T_VARIABLE)) {
|
if ($tokens->is(T_VARIABLE)) {
|
||||||
$from = $scope->tpl->parseTerm($tokens);
|
$from = $scope->tpl->parseTerm($tokens);
|
||||||
$prepend = "";
|
$prepend = "";
|
||||||
} elseif ($tokens->is('[')) {
|
} elseif ($tokens->is('[')) {
|
||||||
$from = $scope->tpl->parseArray($tokens);
|
$from = $scope->tpl->parseArray($tokens);
|
||||||
$uid = '$v' . $scope->tpl->i++;
|
$uid = '$v' . $scope->tpl->i++;
|
||||||
$prepend = $uid . ' = ' . $from . ';';
|
$prepend = $uid . ' = ' . $from . ';';
|
||||||
$from = $uid;
|
$from = $uid;
|
||||||
} else {
|
} else {
|
||||||
throw new UnexpectedTokenException($tokens, null, "tag {foreach}");
|
throw new UnexpectedTokenException($tokens, null, "tag {foreach}");
|
||||||
}
|
}
|
||||||
@ -153,12 +153,12 @@ class Compiler
|
|||||||
$value = $scope->tpl->parseVariable($tokens);
|
$value = $scope->tpl->parseVariable($tokens);
|
||||||
if ($tokens->is(T_DOUBLE_ARROW)) {
|
if ($tokens->is(T_DOUBLE_ARROW)) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
$key = $value;
|
$key = $value;
|
||||||
$value = $scope->tpl->parseVariable($tokens);
|
$value = $scope->tpl->parseVariable($tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope["after"] = array();
|
$scope["after"] = array();
|
||||||
$scope["else"] = false;
|
$scope["else"] = false;
|
||||||
|
|
||||||
while ($token = $tokens->key()) {
|
while ($token = $tokens->key()) {
|
||||||
$param = $tokens->get(T_STRING);
|
$param = $tokens->get(T_STRING);
|
||||||
@ -171,22 +171,22 @@ class Compiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($p["index"]) {
|
if ($p["index"]) {
|
||||||
$before[] = $p["index"] . ' = 0';
|
$before[] = $p["index"] . ' = 0';
|
||||||
$scope["after"][] = $p["index"] . '++';
|
$scope["after"][] = $p["index"] . '++';
|
||||||
}
|
}
|
||||||
if ($p["first"]) {
|
if ($p["first"]) {
|
||||||
$before[] = $p["first"] . ' = true';
|
$before[] = $p["first"] . ' = true';
|
||||||
$scope["after"][] = $p["first"] . ' && (' . $p["first"] . ' = false )';
|
$scope["after"][] = $p["first"] . ' && (' . $p["first"] . ' = false )';
|
||||||
}
|
}
|
||||||
if ($p["last"]) {
|
if ($p["last"]) {
|
||||||
$before[] = $p["last"] . ' = false';
|
$before[] = $p["last"] . ' = false';
|
||||||
$scope["uid"] = "v" . $scope->tpl->i++;
|
$scope["uid"] = "v" . $scope->tpl->i++;
|
||||||
$before[] = '$' . $scope["uid"] . " = count($from)";
|
$before[] = '$' . $scope["uid"] . " = count($from)";
|
||||||
$body[] = 'if(!--$' . $scope["uid"] . ') ' . $p["last"] . ' = true';
|
$body[] = 'if(!--$' . $scope["uid"] . ') ' . $p["last"] . ' = true';
|
||||||
}
|
}
|
||||||
|
|
||||||
$before = $before ? implode("; ", $before) . ";" : "";
|
$before = $before ? implode("; ", $before) . ";" : "";
|
||||||
$body = $body ? implode("; ", $body) . ";" : "";
|
$body = $body ? implode("; ", $body) . ";" : "";
|
||||||
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
||||||
if ($key) {
|
if ($key) {
|
||||||
return "$prepend if($from) { $before foreach($from as $key => $value) { $body";
|
return "$prepend if($from) { $before foreach($from as $key => $value) { $body";
|
||||||
@ -235,41 +235,55 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function forOpen(Tokenizer $tokens, Tag $scope)
|
public static function forOpen(Tokenizer $tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
$p = array("index" => false, "first" => false, "last" => false, "step" => 1, "to" => false, "max" => false, "min" => false);
|
$p = array(
|
||||||
|
"index" => false,
|
||||||
|
"first" => false,
|
||||||
|
"last" => false,
|
||||||
|
"step" => 1,
|
||||||
|
"to" => false,
|
||||||
|
"max" => false,
|
||||||
|
"min" => false
|
||||||
|
);
|
||||||
$scope["after"] = $before = $body = array();
|
$scope["after"] = $before = $body = array();
|
||||||
$i = array('', '');
|
$i = array('', '');
|
||||||
$c = "";
|
$c = "";
|
||||||
$var = $scope->tpl->parseTerm($tokens, $is_var);
|
$var = $scope->tpl->parseTerm($tokens, $is_var);
|
||||||
if (!$is_var) {
|
if (!$is_var) {
|
||||||
throw new UnexpectedTokenException($tokens);
|
throw new UnexpectedTokenException($tokens);
|
||||||
}
|
}
|
||||||
$tokens->get("=");
|
$tokens->get("=");
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
$val = $scope->tpl->parseExpr($tokens);
|
$val = $scope->tpl->parseExpr($tokens);
|
||||||
$p = $scope->tpl->parseParams($tokens, $p);
|
$p = $scope->tpl->parseParams($tokens, $p);
|
||||||
|
|
||||||
if (is_numeric($p["step"])) {
|
if (is_numeric($p["step"])) {
|
||||||
if ($p["step"] > 0) {
|
if ($p["step"] > 0) {
|
||||||
$condition = "$var <= {$p['to']}";
|
$condition = "$var <= {$p['to']}";
|
||||||
if ($p["last"]) $c = "($var + {$p['step']}) > {$p['to']}";
|
if ($p["last"]) {
|
||||||
|
$c = "($var + {$p['step']}) > {$p['to']}";
|
||||||
|
}
|
||||||
} elseif ($p["step"] < 0) {
|
} elseif ($p["step"] < 0) {
|
||||||
$condition = "$var >= {$p['to']}";
|
$condition = "$var >= {$p['to']}";
|
||||||
if ($p["last"]) $c = "($var + {$p['step']}) < {$p['to']}";
|
if ($p["last"]) {
|
||||||
|
$c = "($var + {$p['step']}) < {$p['to']}";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidUsageException("Invalid step value");
|
throw new InvalidUsageException("Invalid step value");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$condition = "({$p['step']} > 0 && $var <= {$p['to']} || {$p['step']} < 0 && $var >= {$p['to']})";
|
$condition = "({$p['step']} > 0 && $var <= {$p['to']} || {$p['step']} < 0 && $var >= {$p['to']})";
|
||||||
if ($p["last"]) $c = "({$p['step']} > 0 && ($var + {$p['step']}) <= {$p['to']} || {$p['step']} < 0 && ($var + {$p['step']}) >= {$p['to']})";
|
if ($p["last"]) {
|
||||||
|
$c = "({$p['step']} > 0 && ($var + {$p['step']}) <= {$p['to']} || {$p['step']} < 0 && ($var + {$p['step']}) >= {$p['to']})";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($p["first"]) {
|
if ($p["first"]) {
|
||||||
$before[] = $p["first"] . ' = true';
|
$before[] = $p["first"] . ' = true';
|
||||||
$scope["after"][] = $p["first"] . ' && (' . $p["first"] . ' = false )';
|
$scope["after"][] = $p["first"] . ' && (' . $p["first"] . ' = false )';
|
||||||
}
|
}
|
||||||
if ($p["last"]) {
|
if ($p["last"]) {
|
||||||
$before[] = $p["last"] . ' = false';
|
$before[] = $p["last"] . ' = false';
|
||||||
$body[] = "if($c) {$p['last']} = true";
|
$body[] = "if($c) {$p['last']} = true";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($p["index"]) {
|
if ($p["index"]) {
|
||||||
@ -277,11 +291,11 @@ class Compiler
|
|||||||
$i[1] .= $p["index"] . '++,';
|
$i[1] .= $p["index"] . '++,';
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope["else"] = false;
|
$scope["else"] = false;
|
||||||
$scope["else_cond"] = "$var==$val";
|
$scope["else_cond"] = "$var==$val";
|
||||||
$before = $before ? implode("; ", $before) . ";" : "";
|
$before = $before ? implode("; ", $before) . ";" : "";
|
||||||
$body = $body ? implode("; ", $body) . ";" : "";
|
$body = $body ? implode("; ", $body) . ";" : "";
|
||||||
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
||||||
|
|
||||||
return "$before for({$i[0]} $var=$val; $condition;{$i[1]} $var+={$p['step']}) { $body";
|
return "$before for({$i[0]} $var=$val; $condition;{$i[1]} $var+={$p['step']}) { $body";
|
||||||
}
|
}
|
||||||
@ -295,7 +309,7 @@ class Compiler
|
|||||||
public static function forElse(Tokenizer $tokens, Tag $scope)
|
public static function forElse(Tokenizer $tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
$scope["no-break"] = $scope["no-continue"] = true;
|
$scope["no-break"] = $scope["no-continue"] = true;
|
||||||
$scope["else"] = true;
|
$scope["else"] = true;
|
||||||
return " } if({$scope['else_cond']}) {";
|
return " } if({$scope['else_cond']}) {";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,12 +349,12 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function switchOpen(Tokenizer $tokens, Tag $scope)
|
public static function switchOpen(Tokenizer $tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
$expr = $scope->tpl->parseExpr($tokens);
|
$expr = $scope->tpl->parseExpr($tokens);
|
||||||
$scope["case"] = array();
|
$scope["case"] = array();
|
||||||
$scope["last"] = array();
|
$scope["last"] = array();
|
||||||
$scope["default"] = '';
|
$scope["default"] = '';
|
||||||
$scope["var"] = $scope->tpl->tmpVar();
|
$scope["var"] = $scope->tpl->tmpVar();
|
||||||
$scope["expr"] = $scope["var"] . ' = strval(' . $expr . ')';
|
$scope["expr"] = $scope["var"] . ' = strval(' . $expr . ')';
|
||||||
// lazy init
|
// lazy init
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@ -414,8 +428,8 @@ class Compiler
|
|||||||
public static function switchClose(Tokenizer $tokens, Tag $scope)
|
public static function switchClose(Tokenizer $tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
self::_caseResort($scope);
|
self::_caseResort($scope);
|
||||||
$expr = $scope["var"];
|
$expr = $scope["var"];
|
||||||
$code = $scope["expr"] . ";\n";
|
$code = $scope["expr"] . ";\n";
|
||||||
$default = $scope["default"];
|
$default = $scope["default"];
|
||||||
foreach ($scope["case"] as $case => $content) {
|
foreach ($scope["case"] as $case => $content) {
|
||||||
if (is_numeric($case)) {
|
if (is_numeric($case)) {
|
||||||
@ -505,12 +519,12 @@ class Compiler
|
|||||||
$stack[] = "'$t'";
|
$stack[] = "'$t'";
|
||||||
}
|
}
|
||||||
$stack[] = $tpl->dynamic_extends;
|
$stack[] = $tpl->dynamic_extends;
|
||||||
$body = '<?php $tpl->getStorage()->display(array(' . implode(', ', $stack) . '), $var); ?>';
|
$body = '<?php $tpl->getStorage()->display(array(' . implode(', ', $stack) . '), $var); ?>';
|
||||||
} else {
|
} else {
|
||||||
$child = $tpl;
|
$child = $tpl;
|
||||||
while ($child && $child->extends) {
|
while ($child && $child->extends) {
|
||||||
$parent = $tpl->extend($child->extends);
|
$parent = $tpl->extend($child->extends);
|
||||||
$child = $parent->extends ? $parent : false;
|
$child = $parent->extends ? $parent : false;
|
||||||
}
|
}
|
||||||
$tpl->extends = false;
|
$tpl->extends = false;
|
||||||
}
|
}
|
||||||
@ -554,7 +568,7 @@ class Compiler
|
|||||||
if (!$name) {
|
if (!$name) {
|
||||||
throw new \RuntimeException("Invalid block name");
|
throw new \RuntimeException("Invalid block name");
|
||||||
}
|
}
|
||||||
$scope["name"] = $name;
|
$scope["name"] = $name;
|
||||||
$scope["use_parent"] = false;
|
$scope["use_parent"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +578,7 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function tagBlockClose($tokens, Tag $scope)
|
public static function tagBlockClose($tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
$tpl = $scope->tpl;
|
$tpl = $scope->tpl;
|
||||||
$name = $scope["name"];
|
$name = $scope["name"];
|
||||||
|
|
||||||
if (isset($tpl->blocks[$name])) { // block defined
|
if (isset($tpl->blocks[$name])) { // block defined
|
||||||
@ -584,10 +598,10 @@ class Compiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
$tpl->blocks[$scope["name"]] = array(
|
$tpl->blocks[$scope["name"]] = array(
|
||||||
"from" => $tpl->getName(),
|
"from" => $tpl->getName(),
|
||||||
"import" => false,
|
"import" => false,
|
||||||
"use_parent" => $scope["use_parent"],
|
"use_parent" => $scope["use_parent"],
|
||||||
"block" => $scope->getContent()
|
"block" => $scope->getContent()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,7 +661,7 @@ class Compiler
|
|||||||
} else {
|
} else {
|
||||||
$ref = new \ReflectionFunction($tag->callback);
|
$ref = new \ReflectionFunction($tag->callback);
|
||||||
}
|
}
|
||||||
$args = array();
|
$args = array();
|
||||||
$params = $tag->tpl->parseParams($tokens);
|
$params = $tag->tpl->parseParams($tokens);
|
||||||
foreach ($ref->getParameters() as $param) {
|
foreach ($ref->getParameters() as $param) {
|
||||||
if (isset($params[$param->getName()])) {
|
if (isset($params[$param->getName()])) {
|
||||||
@ -815,7 +829,7 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function tagImport(Tokenizer $tokens, Tag $tag)
|
public static function tagImport(Tokenizer $tokens, Tag $tag)
|
||||||
{
|
{
|
||||||
$tpl = $tag->tpl;
|
$tpl = $tag->tpl;
|
||||||
$import = array();
|
$import = array();
|
||||||
if ($tokens->is('[')) {
|
if ($tokens->is('[')) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
@ -880,10 +894,10 @@ class Compiler
|
|||||||
*/
|
*/
|
||||||
public static function macroOpen(Tokenizer $tokens, Tag $scope)
|
public static function macroOpen(Tokenizer $tokens, Tag $scope)
|
||||||
{
|
{
|
||||||
$scope["name"] = $tokens->get(Tokenizer::MACRO_STRING);
|
$scope["name"] = $tokens->get(Tokenizer::MACRO_STRING);
|
||||||
$scope["recursive"] = false;
|
$scope["recursive"] = false;
|
||||||
$args = array();
|
$args = array();
|
||||||
$defaults = array();
|
$defaults = array();
|
||||||
if (!$tokens->valid()) {
|
if (!$tokens->valid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -910,10 +924,10 @@ class Compiler
|
|||||||
}
|
}
|
||||||
$tokens->skipIf(')');
|
$tokens->skipIf(')');
|
||||||
$scope["macro"] = array(
|
$scope["macro"] = array(
|
||||||
"name" => $scope["name"],
|
"name" => $scope["name"],
|
||||||
"args" => $args,
|
"args" => $args,
|
||||||
"defaults" => $defaults,
|
"defaults" => $defaults,
|
||||||
"body" => "",
|
"body" => "",
|
||||||
"recursive" => false
|
"recursive" => false
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -928,7 +942,7 @@ class Compiler
|
|||||||
if ($scope["recursive"]) {
|
if ($scope["recursive"]) {
|
||||||
$scope["macro"]["recursive"] = true;
|
$scope["macro"]["recursive"] = true;
|
||||||
}
|
}
|
||||||
$scope["macro"]["body"] = $scope->cutContent();
|
$scope["macro"]["body"] = $scope->cutContent();
|
||||||
$scope->tpl->macros[$scope["name"]] = $scope["macro"];
|
$scope->tpl->macros[$scope["name"]] = $scope["macro"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,6 +973,8 @@ class Compiler
|
|||||||
* @param Tokenizer $tokens
|
* @param Tokenizer $tokens
|
||||||
* @param Tag $tag
|
* @param Tag $tag
|
||||||
*/
|
*/
|
||||||
public static function autoescapeClose(Tokenizer $tokens, Tag $tag) { }
|
public static function autoescapeClose(Tokenizer $tokens, Tag $tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,9 @@ class Modifier
|
|||||||
{
|
{
|
||||||
if (!is_numeric($date)) {
|
if (!is_numeric($date)) {
|
||||||
$date = strtotime($date);
|
$date = strtotime($date);
|
||||||
if (!$date) $date = time();
|
if (!$date) {
|
||||||
|
$date = time();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strftime($format, $date);
|
return strftime($format, $date);
|
||||||
}
|
}
|
||||||
@ -41,7 +43,9 @@ class Modifier
|
|||||||
{
|
{
|
||||||
if (!is_numeric($date)) {
|
if (!is_numeric($date)) {
|
||||||
$date = strtotime($date);
|
$date = strtotime($date);
|
||||||
if (!$date) $date = time();
|
if (!$date) {
|
||||||
|
$date = time();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return date($format, $date);
|
return date($format, $date);
|
||||||
}
|
}
|
||||||
@ -103,7 +107,11 @@ class Modifier
|
|||||||
if (preg_match('#^(.{' . $length . '}).*?(.{' . $length . '})?$#usS', $string, $match)) {
|
if (preg_match('#^(.{' . $length . '}).*?(.{' . $length . '})?$#usS', $string, $match)) {
|
||||||
if (count($match) == 3) {
|
if (count($match) == 3) {
|
||||||
if ($by_words) {
|
if ($by_words) {
|
||||||
return preg_replace('#\s.*$#usS', "", $match[1]) . $etc . preg_replace('#.*\s#usS', "", $match[2]);
|
return preg_replace('#\s.*$#usS', "", $match[1]) . $etc . preg_replace(
|
||||||
|
'#.*\s#usS',
|
||||||
|
"",
|
||||||
|
$match[2]
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return $match[1] . $etc . $match[2];
|
return $match[1] . $etc . $match[2];
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ class Provider implements ProviderInterface
|
|||||||
*/
|
*/
|
||||||
public function getList($extension = "tpl")
|
public function getList($extension = "tpl")
|
||||||
{
|
{
|
||||||
$list = array();
|
$list = array();
|
||||||
$iterator = new \RecursiveIteratorIterator(
|
$iterator = new \RecursiveIteratorIterator(
|
||||||
new \RecursiveDirectoryIterator($this->_path,
|
new \RecursiveDirectoryIterator($this->_path,
|
||||||
\FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS),
|
\FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS),
|
||||||
|
@ -18,12 +18,12 @@ use Fenom;
|
|||||||
class Render extends \ArrayObject
|
class Render extends \ArrayObject
|
||||||
{
|
{
|
||||||
private static $_props = array(
|
private static $_props = array(
|
||||||
"name" => "runtime",
|
"name" => "runtime",
|
||||||
"base_name" => "",
|
"base_name" => "",
|
||||||
"scm" => false,
|
"scm" => false,
|
||||||
"time" => 0,
|
"time" => 0,
|
||||||
"depends" => array(),
|
"depends" => array(),
|
||||||
"macros" => array()
|
"macros" => array()
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
* @var \Closure
|
* @var \Closure
|
||||||
@ -84,12 +84,12 @@ class Render extends \ArrayObject
|
|||||||
{
|
{
|
||||||
$this->_fenom = $fenom;
|
$this->_fenom = $fenom;
|
||||||
$props += self::$_props;
|
$props += self::$_props;
|
||||||
$this->_name = $props["name"];
|
$this->_name = $props["name"];
|
||||||
$this->_base_name = $props["base_name"];
|
$this->_base_name = $props["base_name"];
|
||||||
$this->_scm = $props["scm"];
|
$this->_scm = $props["scm"];
|
||||||
$this->_time = $props["time"];
|
$this->_time = $props["time"];
|
||||||
$this->_depends = $props["depends"];
|
$this->_depends = $props["depends"];
|
||||||
$this->_macros = $props["macros"];
|
$this->_macros = $props["macros"];
|
||||||
// $this->_blocks = $props["blocks"];
|
// $this->_blocks = $props["blocks"];
|
||||||
$this->_code = $code;
|
$this->_code = $code;
|
||||||
}
|
}
|
||||||
@ -251,9 +251,9 @@ class Render extends \ArrayObject
|
|||||||
{
|
{
|
||||||
if ($name == 'info') {
|
if ($name == 'info') {
|
||||||
return array(
|
return array(
|
||||||
'name' => $this->_name,
|
'name' => $this->_name,
|
||||||
'schema' => $this->_scm,
|
'schema' => $this->_scm,
|
||||||
'time' => $this->_time
|
'time' => $this->_time
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -13,8 +13,8 @@ namespace Fenom;
|
|||||||
class Tag extends \ArrayObject
|
class Tag extends \ArrayObject
|
||||||
{
|
{
|
||||||
const COMPILER = 1;
|
const COMPILER = 1;
|
||||||
const FUNC = 2;
|
const FUNC = 2;
|
||||||
const BLOCK = 4;
|
const BLOCK = 4;
|
||||||
|
|
||||||
|
|
||||||
const LTRIM = 1;
|
const LTRIM = 1;
|
||||||
@ -50,19 +50,19 @@ class Tag extends \ArrayObject
|
|||||||
*/
|
*/
|
||||||
public function __construct($name, Template $tpl, $info, &$body)
|
public function __construct($name, Template $tpl, $info, &$body)
|
||||||
{
|
{
|
||||||
$this->tpl = $tpl;
|
$this->tpl = $tpl;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->line = $tpl->getLine();
|
$this->line = $tpl->getLine();
|
||||||
$this->level = $tpl->getStackSize();
|
$this->level = $tpl->getStackSize();
|
||||||
$this->_body = & $body;
|
$this->_body = & $body;
|
||||||
$this->_offset = strlen($body);
|
$this->_offset = strlen($body);
|
||||||
$this->_type = $info["type"];
|
$this->_type = $info["type"];
|
||||||
$this->escape = $tpl->getOptions() & \Fenom::AUTO_ESCAPE;
|
$this->escape = $tpl->getOptions() & \Fenom::AUTO_ESCAPE;
|
||||||
|
|
||||||
if ($this->_type & self::BLOCK) {
|
if ($this->_type & self::BLOCK) {
|
||||||
$this->_open = $info["open"];
|
$this->_open = $info["open"];
|
||||||
$this->_close = $info["close"];
|
$this->_close = $info["close"];
|
||||||
$this->_tags = isset($info["tags"]) ? $info["tags"] : array();
|
$this->_tags = isset($info["tags"]) ? $info["tags"] : array();
|
||||||
$this->_floats = isset($info["float_tags"]) ? $info["float_tags"] : array();
|
$this->_floats = isset($info["float_tags"]) ? $info["float_tags"] : array();
|
||||||
$this->_closed = false;
|
$this->_closed = false;
|
||||||
} else {
|
} else {
|
||||||
@ -81,7 +81,7 @@ class Tag extends \ArrayObject
|
|||||||
*/
|
*/
|
||||||
public function tagOption($option)
|
public function tagOption($option)
|
||||||
{
|
{
|
||||||
if(method_exists($this, 'opt'.$option)) {
|
if (method_exists($this, 'opt' . $option)) {
|
||||||
$this->options[] = $option;
|
$this->options[] = $option;
|
||||||
} else {
|
} else {
|
||||||
throw new \RuntimeException("Unknown tag option $option");
|
throw new \RuntimeException("Unknown tag option $option");
|
||||||
@ -93,9 +93,10 @@ class Tag extends \ArrayObject
|
|||||||
* @param int $option option constant
|
* @param int $option option constant
|
||||||
* @param bool $value true — add option, false — remove option
|
* @param bool $value true — add option, false — remove option
|
||||||
*/
|
*/
|
||||||
public function setOption($option, $value) {
|
public function setOption($option, $value)
|
||||||
|
{
|
||||||
$actual = (bool)($this->tpl->getOptions() & $option);
|
$actual = (bool)($this->tpl->getOptions() & $option);
|
||||||
if($actual != $value) {
|
if ($actual != $value) {
|
||||||
$this->_changed[$option] = $actual;
|
$this->_changed[$option] = $actual;
|
||||||
$this->tpl->setOption(\Fenom::AUTO_ESCAPE, $value);
|
$this->tpl->setOption(\Fenom::AUTO_ESCAPE, $value);
|
||||||
}
|
}
|
||||||
@ -107,7 +108,7 @@ class Tag extends \ArrayObject
|
|||||||
*/
|
*/
|
||||||
public function restore($option)
|
public function restore($option)
|
||||||
{
|
{
|
||||||
if(isset($this->_changed[$option])) {
|
if (isset($this->_changed[$option])) {
|
||||||
$this->tpl->setOption($option, $this->_changed[$option]);
|
$this->tpl->setOption($option, $this->_changed[$option]);
|
||||||
unset($this->_changed[$option]);
|
unset($this->_changed[$option]);
|
||||||
}
|
}
|
||||||
@ -115,7 +116,7 @@ class Tag extends \ArrayObject
|
|||||||
|
|
||||||
public function restoreAll()
|
public function restoreAll()
|
||||||
{
|
{
|
||||||
foreach($this->_changed as $option => $value) {
|
foreach ($this->_changed as $option => $value) {
|
||||||
$this->tpl->setOption($option, $this->_changed[$option]);
|
$this->tpl->setOption($option, $this->_changed[$option]);
|
||||||
unset($this->_changed[$option]);
|
unset($this->_changed[$option]);
|
||||||
}
|
}
|
||||||
@ -138,8 +139,8 @@ class Tag extends \ArrayObject
|
|||||||
*/
|
*/
|
||||||
public function start($tokenizer)
|
public function start($tokenizer)
|
||||||
{
|
{
|
||||||
foreach($this->options as $option) {
|
foreach ($this->options as $option) {
|
||||||
$option = 'opt'.$option;
|
$option = 'opt' . $option;
|
||||||
$this->$option();
|
$this->$option();
|
||||||
}
|
}
|
||||||
return call_user_func($this->_open, $tokenizer, $this);
|
return call_user_func($this->_open, $tokenizer, $this);
|
||||||
@ -195,9 +196,9 @@ class Tag extends \ArrayObject
|
|||||||
throw new \LogicException("Tag {$this->name} already closed");
|
throw new \LogicException("Tag {$this->name} already closed");
|
||||||
}
|
}
|
||||||
if ($this->_close) {
|
if ($this->_close) {
|
||||||
foreach($this->options as $option) {
|
foreach ($this->options as $option) {
|
||||||
$option = 'opt'.$option.'end';
|
$option = 'opt' . $option . 'end';
|
||||||
if(method_exists($this, $option)) {
|
if (method_exists($this, $option)) {
|
||||||
$this->$option();
|
$this->$option();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +237,7 @@ class Tag extends \ArrayObject
|
|||||||
*/
|
*/
|
||||||
public function cutContent()
|
public function cutContent()
|
||||||
{
|
{
|
||||||
$content = substr($this->_body, $this->_offset + 1);
|
$content = substr($this->_body, $this->_offset + 1);
|
||||||
$this->_body = substr($this->_body, 0, $this->_offset);
|
$this->_body = substr($this->_body, 0, $this->_offset);
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
@ -116,9 +116,9 @@ class Template extends Render
|
|||||||
*/
|
*/
|
||||||
public function __construct(Fenom $fenom, $options)
|
public function __construct(Fenom $fenom, $options)
|
||||||
{
|
{
|
||||||
$this->_fenom = $fenom;
|
$this->_fenom = $fenom;
|
||||||
$this->_options = $options;
|
$this->_options = $options;
|
||||||
$this->_filters = $this->_fenom->getFilters();
|
$this->_filters = $this->_fenom->getFilters();
|
||||||
$this->_tag_filters = $this->_fenom->getTagFilters();
|
$this->_tag_filters = $this->_fenom->getTagFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,15 +155,15 @@ class Template extends Render
|
|||||||
public function load($name, $compile = true)
|
public function load($name, $compile = true)
|
||||||
{
|
{
|
||||||
$this->_name = $name;
|
$this->_name = $name;
|
||||||
$this->_crc = crc32($this->_name);
|
$this->_crc = crc32($this->_name);
|
||||||
if ($provider = strstr($name, ':', true)) {
|
if ($provider = strstr($name, ':', true)) {
|
||||||
$this->_scm = $provider;
|
$this->_scm = $provider;
|
||||||
$this->_base_name = substr($name, strlen($provider) + 1);
|
$this->_base_name = substr($name, strlen($provider) + 1);
|
||||||
} else {
|
} else {
|
||||||
$this->_base_name = $name;
|
$this->_base_name = $name;
|
||||||
}
|
}
|
||||||
$this->_provider = $this->_fenom->getProvider($provider);
|
$this->_provider = $this->_fenom->getProvider($provider);
|
||||||
$this->_src = $this->_provider->getSource($this->_base_name, $this->_time);
|
$this->_src = $this->_provider->getSource($this->_base_name, $this->_time);
|
||||||
if ($compile) {
|
if ($compile) {
|
||||||
$this->compile();
|
$this->compile();
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ class Template extends Render
|
|||||||
public function source($name, $src, $compile = true)
|
public function source($name, $src, $compile = true)
|
||||||
{
|
{
|
||||||
$this->_name = $name;
|
$this->_name = $name;
|
||||||
$this->_src = $src;
|
$this->_src = $src;
|
||||||
if ($compile) {
|
if ($compile) {
|
||||||
$this->compile();
|
$this->compile();
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ class Template extends Render
|
|||||||
*/
|
*/
|
||||||
public function compile()
|
public function compile()
|
||||||
{
|
{
|
||||||
$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) {
|
foreach ($this->_fenom->getPreFilters() as $filter) {
|
||||||
$this->_src = call_user_func($filter, $this, $this->_src);
|
$this->_src = call_user_func($filter, $this, $this->_src);
|
||||||
@ -226,11 +226,15 @@ class Template extends Render
|
|||||||
$end = $start + 1;
|
$end = $start + 1;
|
||||||
do {
|
do {
|
||||||
$need_more = false;
|
$need_more = false;
|
||||||
$end = strpos($this->_src, '}', $end + 1); // search close-symbol of the tag
|
$end = strpos($this->_src, '}', $end + 1); // search close-symbol of the tag
|
||||||
if ($end === false) { // if unexpected end of template
|
if ($end === false) { // if unexpected end of template
|
||||||
throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line);
|
throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line);
|
||||||
}
|
}
|
||||||
$tag = substr($this->_src, $start, $end - $start + 1); // variable $tag contains fenom tag '{...}'
|
$tag = substr(
|
||||||
|
$this->_src,
|
||||||
|
$start,
|
||||||
|
$end - $start + 1
|
||||||
|
); // variable $tag contains fenom tag '{...}'
|
||||||
|
|
||||||
$_tag = substr($tag, 1, -1); // strip delimiters '{' and '}'
|
$_tag = substr($tag, 1, -1); // strip delimiters '{' and '}'
|
||||||
|
|
||||||
@ -252,7 +256,10 @@ class Template extends Render
|
|||||||
} else {
|
} else {
|
||||||
$this->_appendCode($this->parseTag($tokens), $tag); // start the tag lexer
|
$this->_appendCode($this->parseTag($tokens), $tag); // start the tag lexer
|
||||||
if ($tokens->key()) { // if tokenizer have tokens - throws exceptions
|
if ($tokens->key()) { // if tokenizer have tokens - throws exceptions
|
||||||
throw new CompileException("Unexpected token '" . $tokens->current() . "' in {$this} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there", 0, E_ERROR, $this->_name, $this->_line);
|
throw new CompileException("Unexpected token '" . $tokens->current() . "' in {$this} line {$this->_line}, near '{" . $tokens->getSnippetAsString(
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
) . "' <- there", 0, E_ERROR, $this->_name, $this->_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,14 +274,17 @@ class Template extends Render
|
|||||||
$this->_appendText(substr($this->_src, $end ? $end + 1 : 0)); // append tail of the template
|
$this->_appendText(substr($this->_src, $end ? $end + 1 : 0)); // append tail of the template
|
||||||
if ($this->_stack) {
|
if ($this->_stack) {
|
||||||
$_names = array();
|
$_names = array();
|
||||||
$_line = 0;
|
$_line = 0;
|
||||||
foreach ($this->_stack as $scope) {
|
foreach ($this->_stack as $scope) {
|
||||||
if (!$_line) {
|
if (!$_line) {
|
||||||
$_line = $scope->line;
|
$_line = $scope->line;
|
||||||
}
|
}
|
||||||
$_names[] = '{' . $scope->name . '} opened on line ' . $scope->line;
|
$_names[] = '{' . $scope->name . '} opened on line ' . $scope->line;
|
||||||
}
|
}
|
||||||
throw new CompileException("Unclosed tag" . (count($_names) == 1 ? "" : "s") . ": " . implode(", ", $_names), 0, 1, $this->_name, $_line);
|
throw new CompileException("Unclosed tag" . (count($_names) == 1 ? "" : "s") . ": " . implode(
|
||||||
|
", ",
|
||||||
|
$_names
|
||||||
|
), 0, 1, $this->_name, $_line);
|
||||||
}
|
}
|
||||||
$this->_src = ""; // cleanup
|
$this->_src = ""; // cleanup
|
||||||
if ($this->_post) {
|
if ($this->_post) {
|
||||||
@ -293,8 +303,9 @@ class Template extends Render
|
|||||||
* @param int $option
|
* @param int $option
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setOption($option, $value) {
|
public function setOption($option, $value)
|
||||||
if($value) {
|
{
|
||||||
|
if ($value) {
|
||||||
$this->_options |= $option;
|
$this->_options |= $option;
|
||||||
} else {
|
} else {
|
||||||
$this->_options &= ~$option;
|
$this->_options &= ~$option;
|
||||||
@ -472,7 +483,7 @@ class Template extends Render
|
|||||||
*/
|
*/
|
||||||
public function out($data, $escape = null)
|
public function out($data, $escape = null)
|
||||||
{
|
{
|
||||||
if($escape === null) {
|
if ($escape === null) {
|
||||||
$escape = $this->_options & Fenom::AUTO_ESCAPE;
|
$escape = $this->_options & Fenom::AUTO_ESCAPE;
|
||||||
}
|
}
|
||||||
if ($escape) {
|
if ($escape) {
|
||||||
@ -491,7 +502,7 @@ class Template extends Render
|
|||||||
$donor = $this->_fenom->compile($tpl, false);
|
$donor = $this->_fenom->compile($tpl, false);
|
||||||
foreach ($donor->blocks as $name => $block) {
|
foreach ($donor->blocks as $name => $block) {
|
||||||
if (!isset($this->blocks[$name])) {
|
if (!isset($this->blocks[$name])) {
|
||||||
$block['import'] = $this->getName();
|
$block['import'] = $this->getName();
|
||||||
$this->blocks[$name] = $block;
|
$this->blocks[$name] = $block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,19 +519,19 @@ class Template extends Render
|
|||||||
if (!$this->_body) {
|
if (!$this->_body) {
|
||||||
$this->compile();
|
$this->compile();
|
||||||
}
|
}
|
||||||
$parent = $this->_fenom->getRawTemplate()->load($tpl, false);
|
$parent = $this->_fenom->getRawTemplate()->load($tpl, false);
|
||||||
$parent->blocks = & $this->blocks;
|
$parent->blocks = & $this->blocks;
|
||||||
$parent->macros = & $this->macros;
|
$parent->macros = & $this->macros;
|
||||||
$parent->extended = $this->getName();
|
$parent->extended = $this->getName();
|
||||||
if (!$this->ext_stack) {
|
if (!$this->ext_stack) {
|
||||||
$this->ext_stack[] = $this->getName();
|
$this->ext_stack[] = $this->getName();
|
||||||
}
|
}
|
||||||
$this->ext_stack[] = $parent->getName();
|
$this->ext_stack[] = $parent->getName();
|
||||||
$parent->_options = $this->_options;
|
$parent->_options = $this->_options;
|
||||||
$parent->ext_stack = $this->ext_stack;
|
$parent->ext_stack = $this->ext_stack;
|
||||||
$parent->compile();
|
$parent->compile();
|
||||||
$this->_body = $parent->_body;
|
$this->_body = $parent->_body;
|
||||||
$this->_src = $parent->_src;
|
$this->_src = $parent->_src;
|
||||||
$this->addDepend($parent);
|
$this->addDepend($parent);
|
||||||
return $parent;
|
return $parent;
|
||||||
}
|
}
|
||||||
@ -552,9 +563,15 @@ class Template extends Render
|
|||||||
} catch (InvalidUsageException $e) {
|
} catch (InvalidUsageException $e) {
|
||||||
throw new CompileException($e->getMessage() . " in {$this->_name} line {$this->_line}", 0, E_ERROR, $this->_name, $this->_line, $e);
|
throw new CompileException($e->getMessage() . " in {$this->_name} line {$this->_line}", 0, E_ERROR, $this->_name, $this->_line, $e);
|
||||||
} catch (\LogicException $e) {
|
} catch (\LogicException $e) {
|
||||||
throw new SecurityException($e->getMessage() . " in {$this->_name} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there", 0, E_ERROR, $this->_name, $this->_line, $e);
|
throw new SecurityException($e->getMessage() . " in {$this->_name} line {$this->_line}, near '{" . $tokens->getSnippetAsString(
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
) . "' <- there", 0, E_ERROR, $this->_name, $this->_line, $e);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
throw new CompileException($e->getMessage() . " in {$this->_name} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there", 0, E_ERROR, $this->_name, $this->_line, $e);
|
throw new CompileException($e->getMessage() . " in {$this->_name} line {$this->_line}, near '{" . $tokens->getSnippetAsString(
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
) . "' <- there", 0, E_ERROR, $this->_name, $this->_line, $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +611,8 @@ class Template extends Render
|
|||||||
{
|
{
|
||||||
$action = $tokens->get(Tokenizer::MACRO_STRING);
|
$action = $tokens->get(Tokenizer::MACRO_STRING);
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
if ($tokens->is("(", T_DOUBLE_COLON, T_NS_SEPARATOR) && !$tokens->isWhiteSpaced()) { // just invoke function or static method
|
if ($tokens->is("(", T_DOUBLE_COLON, T_NS_SEPARATOR) && !$tokens->isWhiteSpaced()
|
||||||
|
) { // just invoke function or static method
|
||||||
$tokens->back();
|
$tokens->back();
|
||||||
return $this->out($this->parseExpr($tokens));
|
return $this->out($this->parseExpr($tokens));
|
||||||
} elseif ($tokens->is('.')) {
|
} elseif ($tokens->is('.')) {
|
||||||
@ -626,7 +644,10 @@ class Template extends Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($tags = $this->_fenom->getTagOwners($action)) { // unknown template tag
|
if ($tags = $this->_fenom->getTagOwners($action)) { // unknown template tag
|
||||||
throw new TokenizeException("Unexpected tag '$action' (this tag can be used with '" . implode("', '", $tags) . "')");
|
throw new TokenizeException("Unexpected tag '$action' (this tag can be used with '" . implode(
|
||||||
|
"', '",
|
||||||
|
$tags
|
||||||
|
) . "')");
|
||||||
} else {
|
} else {
|
||||||
throw new TokenizeException("Unexpected tag '$action'");
|
throw new TokenizeException("Unexpected tag '$action'");
|
||||||
}
|
}
|
||||||
@ -650,9 +671,9 @@ class Template extends Render
|
|||||||
*/
|
*/
|
||||||
public function parseExpr(Tokenizer $tokens)
|
public function parseExpr(Tokenizer $tokens)
|
||||||
{
|
{
|
||||||
$exp = array();
|
$exp = array();
|
||||||
$var = false; // last term was: true - variable, false - mixed
|
$var = false; // last term was: true - variable, false - mixed
|
||||||
$op = false; // last exp was operator
|
$op = false; // last exp was operator
|
||||||
$cond = false; // was comparison operator
|
$cond = false; // was comparison operator
|
||||||
while ($tokens->valid()) {
|
while ($tokens->valid()) {
|
||||||
// parse term
|
// parse term
|
||||||
@ -660,18 +681,18 @@ class Template extends Render
|
|||||||
if ($term !== false) {
|
if ($term !== false) {
|
||||||
if ($this->_options & Fenom::FORCE_VERIFY) {
|
if ($this->_options & Fenom::FORCE_VERIFY) {
|
||||||
$term = '(isset(' . $term . ') ? ' . $term . ' : null)';
|
$term = '(isset(' . $term . ') ? ' . $term . ' : null)';
|
||||||
$var = false;
|
$var = false;
|
||||||
}
|
}
|
||||||
if ($tokens->is('|')) {
|
if ($tokens->is('|')) {
|
||||||
$term = $this->parseModifier($tokens, $term);
|
$term = $this->parseModifier($tokens, $term);
|
||||||
$var = false;
|
$var = false;
|
||||||
}
|
}
|
||||||
if ($tokens->is('?', '!')) {
|
if ($tokens->is('?', '!')) {
|
||||||
$term = $this->parseTernary($tokens, $term, $var);
|
$term = $this->parseTernary($tokens, $term, $var);
|
||||||
$var = false;
|
$var = false;
|
||||||
}
|
}
|
||||||
$exp[] = $term;
|
$exp[] = $term;
|
||||||
$op = false;
|
$op = false;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -700,10 +721,10 @@ class Template extends Render
|
|||||||
}
|
}
|
||||||
$operator = $tokens->current();
|
$operator = $tokens->current();
|
||||||
if ($operator == "is") {
|
if ($operator == "is") {
|
||||||
$item = array_pop($exp);
|
$item = array_pop($exp);
|
||||||
$exp[] = $this->parseIs($tokens, $item, $var);
|
$exp[] = $this->parseIs($tokens, $item, $var);
|
||||||
} elseif ($operator == "in" || ($operator == "not" && $tokens->isNextToken("in"))) {
|
} elseif ($operator == "in" || ($operator == "not" && $tokens->isNextToken("in"))) {
|
||||||
$item = array_pop($exp);
|
$item = array_pop($exp);
|
||||||
$exp[] = $this->parseIn($tokens, $item, $var);
|
$exp[] = $this->parseIn($tokens, $item, $var);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -778,7 +799,7 @@ class Template extends Render
|
|||||||
$is_var = true;
|
$is_var = true;
|
||||||
}
|
}
|
||||||
} elseif ($tokens->is('$')) {
|
} elseif ($tokens->is('$')) {
|
||||||
$var = $this->parseAccessor($tokens, $is_var);
|
$var = $this->parseAccessor($tokens, $is_var);
|
||||||
$code = $unary . $var;
|
$code = $unary . $var;
|
||||||
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
|
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
|
||||||
$code = $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
|
$code = $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
|
||||||
@ -797,8 +818,8 @@ class Template extends Render
|
|||||||
$code = $unary . $func . $this->parseArgs($tokens->next());
|
$code = $unary . $func . $this->parseArgs($tokens->next());
|
||||||
} elseif ($tokens->isNext(T_NS_SEPARATOR, T_DOUBLE_COLON)) {
|
} elseif ($tokens->isNext(T_NS_SEPARATOR, T_DOUBLE_COLON)) {
|
||||||
$method = $this->parseStatic($tokens);
|
$method = $this->parseStatic($tokens);
|
||||||
$args = $this->parseArgs($tokens);
|
$args = $this->parseArgs($tokens);
|
||||||
$code = $unary . $method . $args;
|
$code = $unary . $method . $args;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -885,17 +906,17 @@ class Template extends Render
|
|||||||
public function parseAccessor(Tokenizer $tokens, &$is_var)
|
public function parseAccessor(Tokenizer $tokens, &$is_var)
|
||||||
{
|
{
|
||||||
$is_var = false;
|
$is_var = false;
|
||||||
$vars = array(
|
$vars = array(
|
||||||
'get' => '$_GET',
|
'get' => '$_GET',
|
||||||
'post' => '$_POST',
|
'post' => '$_POST',
|
||||||
'session' => '$_SESSION',
|
'session' => '$_SESSION',
|
||||||
'cookie' => '$_COOKIE',
|
'cookie' => '$_COOKIE',
|
||||||
'request' => '$_REQUEST',
|
'request' => '$_REQUEST',
|
||||||
'files' => '$_FILES',
|
'files' => '$_FILES',
|
||||||
'globals' => '$GLOBALS',
|
'globals' => '$GLOBALS',
|
||||||
'server' => '$_SERVER',
|
'server' => '$_SERVER',
|
||||||
'env' => '$_ENV',
|
'env' => '$_ENV',
|
||||||
'tpl' => '$tpl->info'
|
'tpl' => '$tpl->info'
|
||||||
);
|
);
|
||||||
if ($this->_options & Fenom::DENY_ACCESSOR) {
|
if ($this->_options & Fenom::DENY_ACCESSOR) {
|
||||||
throw new \LogicException("Accessor are disabled");
|
throw new \LogicException("Accessor are disabled");
|
||||||
@ -952,7 +973,12 @@ class Template extends Render
|
|||||||
return '((' . $var . ' !== null) ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))';
|
return '((' . $var . ' !== null) ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($tokens->is(Tokenizer::MACRO_BINARY, Tokenizer::MACRO_BOOLEAN, Tokenizer::MACRO_MATH) || !$tokens->valid()) {
|
} elseif ($tokens->is(
|
||||||
|
Tokenizer::MACRO_BINARY,
|
||||||
|
Tokenizer::MACRO_BOOLEAN,
|
||||||
|
Tokenizer::MACRO_MATH
|
||||||
|
) || !$tokens->valid()
|
||||||
|
) {
|
||||||
if ($empty) {
|
if ($empty) {
|
||||||
if ($is_var) {
|
if ($is_var) {
|
||||||
return '!empty(' . $var . ')';
|
return '!empty(' . $var . ')';
|
||||||
@ -1000,11 +1026,11 @@ class Template extends Render
|
|||||||
$tokens->next();
|
$tokens->next();
|
||||||
if ($tokens->current() == 'not') {
|
if ($tokens->current() == 'not') {
|
||||||
$invert = '!';
|
$invert = '!';
|
||||||
$equal = '!=';
|
$equal = '!=';
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
} else {
|
} else {
|
||||||
$invert = '';
|
$invert = '';
|
||||||
$equal = '==';
|
$equal = '==';
|
||||||
}
|
}
|
||||||
if ($tokens->is(Tokenizer::MACRO_STRING)) {
|
if ($tokens->is(Tokenizer::MACRO_STRING)) {
|
||||||
$action = $tokens->current();
|
$action = $tokens->current();
|
||||||
@ -1041,12 +1067,12 @@ class Template extends Render
|
|||||||
{
|
{
|
||||||
$checkers = array(
|
$checkers = array(
|
||||||
"string" => 'is_int(strpos(%2$s, %1$s))',
|
"string" => 'is_int(strpos(%2$s, %1$s))',
|
||||||
"list" => "in_array(%s, %s)",
|
"list" => "in_array(%s, %s)",
|
||||||
"keys" => "array_key_exists(%s, %s)",
|
"keys" => "array_key_exists(%s, %s)",
|
||||||
"auto" => '\Fenom\Modifier::in(%s, %s)'
|
"auto" => '\Fenom\Modifier::in(%s, %s)'
|
||||||
);
|
);
|
||||||
$checker = null;
|
$checker = null;
|
||||||
$invert = '';
|
$invert = '';
|
||||||
if ($tokens->current() == 'not') {
|
if ($tokens->current() == 'not') {
|
||||||
$invert = '!';
|
$invert = '!';
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
@ -1256,14 +1282,23 @@ class Template extends Render
|
|||||||
{
|
{
|
||||||
if ($tokens->is("[")) {
|
if ($tokens->is("[")) {
|
||||||
$_arr = "array(";
|
$_arr = "array(";
|
||||||
$key = $val = false;
|
$key = $val = false;
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
while ($tokens->valid()) {
|
while ($tokens->valid()) {
|
||||||
if ($tokens->is(',') && $val) {
|
if ($tokens->is(',') && $val) {
|
||||||
$key = true;
|
$key = true;
|
||||||
$val = false;
|
$val = false;
|
||||||
$_arr .= $tokens->getAndNext() . ' ';
|
$_arr .= $tokens->getAndNext() . ' ';
|
||||||
} elseif ($tokens->is(Tokenizer::MACRO_SCALAR, T_VARIABLE, T_STRING, T_EMPTY, T_ISSET, "(", "#") && !$val) {
|
} elseif ($tokens->is(
|
||||||
|
Tokenizer::MACRO_SCALAR,
|
||||||
|
T_VARIABLE,
|
||||||
|
T_STRING,
|
||||||
|
T_EMPTY,
|
||||||
|
T_ISSET,
|
||||||
|
"(",
|
||||||
|
"#"
|
||||||
|
) && !$val
|
||||||
|
) {
|
||||||
$_arr .= $this->parseExpr($tokens);
|
$_arr .= $this->parseExpr($tokens);
|
||||||
$key = false;
|
$key = false;
|
||||||
$val = true;
|
$val = true;
|
||||||
@ -1299,15 +1334,15 @@ class Template extends Render
|
|||||||
public function parseMacroCall(Tokenizer $tokens, $name)
|
public function parseMacroCall(Tokenizer $tokens, $name)
|
||||||
{
|
{
|
||||||
$recursive = false;
|
$recursive = false;
|
||||||
$macro = false;
|
$macro = false;
|
||||||
if (isset($this->macros[$name])) {
|
if (isset($this->macros[$name])) {
|
||||||
$macro = $this->macros[$name];
|
$macro = $this->macros[$name];
|
||||||
$recursive = $macro['recursive'];
|
$recursive = $macro['recursive'];
|
||||||
} else {
|
} else {
|
||||||
foreach ($this->_stack as $scope) {
|
foreach ($this->_stack as $scope) {
|
||||||
if ($scope->name == 'macro' && $scope['name'] == $name) { // invoke recursive
|
if ($scope->name == 'macro' && $scope['name'] == $name) { // invoke recursive
|
||||||
$recursive = $scope;
|
$recursive = $scope;
|
||||||
$macro = $scope['macro'];
|
$macro = $scope['macro'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1316,7 +1351,7 @@ class Template extends Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
$p = $this->parseParams($tokens);
|
$p = $this->parseParams($tokens);
|
||||||
$args = array();
|
$args = array();
|
||||||
foreach ($macro['args'] as $arg) {
|
foreach ($macro['args'] as $arg) {
|
||||||
if (isset($p[$arg])) {
|
if (isset($p[$arg])) {
|
||||||
@ -1381,17 +1416,26 @@ class Template extends Render
|
|||||||
$tokens->next();
|
$tokens->next();
|
||||||
$arg = $colon = false;
|
$arg = $colon = false;
|
||||||
while ($tokens->valid()) {
|
while ($tokens->valid()) {
|
||||||
if (!$arg && $tokens->is(T_VARIABLE, T_STRING, "(", Tokenizer::MACRO_SCALAR, '"', Tokenizer::MACRO_UNARY, Tokenizer::MACRO_INCDEC)) {
|
if (!$arg && $tokens->is(
|
||||||
|
T_VARIABLE,
|
||||||
|
T_STRING,
|
||||||
|
"(",
|
||||||
|
Tokenizer::MACRO_SCALAR,
|
||||||
|
'"',
|
||||||
|
Tokenizer::MACRO_UNARY,
|
||||||
|
Tokenizer::MACRO_INCDEC
|
||||||
|
)
|
||||||
|
) {
|
||||||
$_args .= $this->parseExpr($tokens);
|
$_args .= $this->parseExpr($tokens);
|
||||||
$arg = true;
|
$arg = true;
|
||||||
$colon = false;
|
$colon = false;
|
||||||
} elseif (!$arg && $tokens->is('[')) {
|
} elseif (!$arg && $tokens->is('[')) {
|
||||||
$_args .= $this->parseArray($tokens);
|
$_args .= $this->parseArray($tokens);
|
||||||
$arg = true;
|
$arg = true;
|
||||||
$colon = false;
|
$colon = false;
|
||||||
} elseif ($arg && $tokens->is(',')) {
|
} elseif ($arg && $tokens->is(',')) {
|
||||||
$_args .= $tokens->getAndNext() . ' ';
|
$_args .= $tokens->getAndNext() . ' ';
|
||||||
$arg = false;
|
$arg = false;
|
||||||
$colon = true;
|
$colon = true;
|
||||||
} elseif (!$colon && $tokens->is(')')) {
|
} elseif (!$colon && $tokens->is(')')) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
@ -1417,7 +1461,7 @@ class Template extends Render
|
|||||||
if ($tokens->isNext('|')) {
|
if ($tokens->isNext('|')) {
|
||||||
return $this->parseExpr($tokens);
|
return $this->parseExpr($tokens);
|
||||||
} else {
|
} else {
|
||||||
$str = $tokens->getAndNext();
|
$str = $tokens->getAndNext();
|
||||||
$static = stripslashes(substr($str, 1, -1));
|
$static = stripslashes(substr($str, 1, -1));
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,10 @@ defined('T_YIELD') || define('T_YIELD', 267);
|
|||||||
*/
|
*/
|
||||||
class Tokenizer
|
class Tokenizer
|
||||||
{
|
{
|
||||||
const TOKEN = 0;
|
const TOKEN = 0;
|
||||||
const TEXT = 1;
|
const TEXT = 1;
|
||||||
const WHITESPACE = 2;
|
const WHITESPACE = 2;
|
||||||
const LINE = 3;
|
const LINE = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some text value: foo, bar, new, class ...
|
* Some text value: foo, bar, new, class ...
|
||||||
@ -92,64 +92,174 @@ class Tokenizer
|
|||||||
* @var array groups of tokens
|
* @var array groups of tokens
|
||||||
*/
|
*/
|
||||||
public static $macros = array(
|
public static $macros = array(
|
||||||
self::MACRO_STRING => array(
|
self::MACRO_STRING => array(
|
||||||
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1, \T_BREAK => 1, \T_CASE => 1,
|
\T_ABSTRACT => 1,
|
||||||
\T_CATCH => 1, \T_CLASS => 1, \T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 1,
|
\T_ARRAY => 1,
|
||||||
\T_DECLARE => 1, \T_DEFAULT => 1, \T_DIR => 1, \T_DO => 1, \T_ECHO => 1, \T_ELSE => 1,
|
\T_AS => 1,
|
||||||
\T_ELSEIF => 1, \T_EMPTY => 1, \T_ENDDECLARE => 1, \T_ENDFOR => 1, \T_ENDFOREACH => 1, \T_ENDIF => 1,
|
\T_BREAK => 1,
|
||||||
\T_ENDSWITCH => 1, \T_ENDWHILE => 1, \T_EVAL => 1, \T_EXIT => 1, \T_EXTENDS => 1, \T_FILE => 1,
|
\T_BREAK => 1,
|
||||||
\T_FINAL => 1, \T_FOR => 1, \T_FOREACH => 1, \T_FUNCTION => 1, \T_FUNC_C => 1, \T_GLOBAL => 1,
|
\T_CASE => 1,
|
||||||
\T_GOTO => 1, \T_HALT_COMPILER => 1, \T_IF => 1, \T_IMPLEMENTS => 1, \T_INCLUDE => 1, \T_INCLUDE_ONCE => 1,
|
\T_CATCH => 1,
|
||||||
\T_INSTANCEOF => 1, \T_INSTEADOF => 1, \T_INTERFACE => 1, \T_ISSET => 1, \T_LINE => 1, \T_LIST => 1,
|
\T_CLASS => 1,
|
||||||
\T_LOGICAL_AND => 1, \T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_METHOD_C => 1, \T_NAMESPACE => 1, \T_NS_C => 1,
|
\T_CLASS_C => 1,
|
||||||
\T_NEW => 1, \T_PRINT => 1, \T_PRIVATE => 1, \T_PUBLIC => 1, \T_PROTECTED => 1, \T_REQUIRE => 1,
|
\T_CLONE => 1,
|
||||||
\T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_RETURN => 1, \T_STRING => 1, \T_SWITCH => 1, \T_THROW => 1,
|
\T_CONST => 1,
|
||||||
\T_TRAIT => 1, \T_TRAIT_C => 1, \T_TRY => 1, \T_UNSET => 1, \T_USE => 1, \T_VAR => 1,
|
\T_CONTINUE => 1,
|
||||||
\T_WHILE => 1, \T_YIELD => 1
|
\T_DECLARE => 1,
|
||||||
|
\T_DEFAULT => 1,
|
||||||
|
\T_DIR => 1,
|
||||||
|
\T_DO => 1,
|
||||||
|
\T_ECHO => 1,
|
||||||
|
\T_ELSE => 1,
|
||||||
|
\T_ELSEIF => 1,
|
||||||
|
\T_EMPTY => 1,
|
||||||
|
\T_ENDDECLARE => 1,
|
||||||
|
\T_ENDFOR => 1,
|
||||||
|
\T_ENDFOREACH => 1,
|
||||||
|
\T_ENDIF => 1,
|
||||||
|
\T_ENDSWITCH => 1,
|
||||||
|
\T_ENDWHILE => 1,
|
||||||
|
\T_EVAL => 1,
|
||||||
|
\T_EXIT => 1,
|
||||||
|
\T_EXTENDS => 1,
|
||||||
|
\T_FILE => 1,
|
||||||
|
\T_FINAL => 1,
|
||||||
|
\T_FOR => 1,
|
||||||
|
\T_FOREACH => 1,
|
||||||
|
\T_FUNCTION => 1,
|
||||||
|
\T_FUNC_C => 1,
|
||||||
|
\T_GLOBAL => 1,
|
||||||
|
\T_GOTO => 1,
|
||||||
|
\T_HALT_COMPILER => 1,
|
||||||
|
\T_IF => 1,
|
||||||
|
\T_IMPLEMENTS => 1,
|
||||||
|
\T_INCLUDE => 1,
|
||||||
|
\T_INCLUDE_ONCE => 1,
|
||||||
|
\T_INSTANCEOF => 1,
|
||||||
|
\T_INSTEADOF => 1,
|
||||||
|
\T_INTERFACE => 1,
|
||||||
|
\T_ISSET => 1,
|
||||||
|
\T_LINE => 1,
|
||||||
|
\T_LIST => 1,
|
||||||
|
\T_LOGICAL_AND => 1,
|
||||||
|
\T_LOGICAL_OR => 1,
|
||||||
|
\T_LOGICAL_XOR => 1,
|
||||||
|
\T_METHOD_C => 1,
|
||||||
|
\T_NAMESPACE => 1,
|
||||||
|
\T_NS_C => 1,
|
||||||
|
\T_NEW => 1,
|
||||||
|
\T_PRINT => 1,
|
||||||
|
\T_PRIVATE => 1,
|
||||||
|
\T_PUBLIC => 1,
|
||||||
|
\T_PROTECTED => 1,
|
||||||
|
\T_REQUIRE => 1,
|
||||||
|
\T_REQUIRE_ONCE => 1,
|
||||||
|
\T_RETURN => 1,
|
||||||
|
\T_RETURN => 1,
|
||||||
|
\T_STRING => 1,
|
||||||
|
\T_SWITCH => 1,
|
||||||
|
\T_THROW => 1,
|
||||||
|
\T_TRAIT => 1,
|
||||||
|
\T_TRAIT_C => 1,
|
||||||
|
\T_TRY => 1,
|
||||||
|
\T_UNSET => 1,
|
||||||
|
\T_USE => 1,
|
||||||
|
\T_VAR => 1,
|
||||||
|
\T_WHILE => 1,
|
||||||
|
\T_YIELD => 1
|
||||||
),
|
),
|
||||||
self::MACRO_INCDEC => array(
|
self::MACRO_INCDEC => array(
|
||||||
\T_INC => 1, \T_DEC => 1
|
\T_INC => 1,
|
||||||
|
\T_DEC => 1
|
||||||
),
|
),
|
||||||
self::MACRO_UNARY => array(
|
self::MACRO_UNARY => array(
|
||||||
"!" => 1, "~" => 1, "-" => 1
|
"!" => 1,
|
||||||
|
"~" => 1,
|
||||||
|
"-" => 1
|
||||||
),
|
),
|
||||||
self::MACRO_BINARY => array(
|
self::MACRO_BINARY => array(
|
||||||
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_IS_GREATER_OR_EQUAL => 1, \T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1,
|
\T_BOOLEAN_AND => 1,
|
||||||
\T_IS_NOT_EQUAL => 1, \T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1, \T_LOGICAL_AND => 1,
|
\T_BOOLEAN_OR => 1,
|
||||||
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_SL => 1, \T_SR => 1,
|
\T_IS_GREATER_OR_EQUAL => 1,
|
||||||
"+" => 1, "-" => 1, "*" => 1, "/" => 1, ">" => 1, "<" => 1, "^" => 1, "%" => 1, "&" => 1
|
\T_IS_EQUAL => 1,
|
||||||
|
\T_IS_IDENTICAL => 1,
|
||||||
|
\T_IS_NOT_EQUAL => 1,
|
||||||
|
\T_IS_NOT_IDENTICAL => 1,
|
||||||
|
\T_IS_SMALLER_OR_EQUAL => 1,
|
||||||
|
\T_LOGICAL_AND => 1,
|
||||||
|
\T_LOGICAL_OR => 1,
|
||||||
|
\T_LOGICAL_XOR => 1,
|
||||||
|
\T_SL => 1,
|
||||||
|
\T_SR => 1,
|
||||||
|
"+" => 1,
|
||||||
|
"-" => 1,
|
||||||
|
"*" => 1,
|
||||||
|
"/" => 1,
|
||||||
|
">" => 1,
|
||||||
|
"<" => 1,
|
||||||
|
"^" => 1,
|
||||||
|
"%" => 1,
|
||||||
|
"&" => 1
|
||||||
),
|
),
|
||||||
self::MACRO_BOOLEAN => array(
|
self::MACRO_BOOLEAN => array(
|
||||||
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_LOGICAL_AND => 1
|
\T_LOGICAL_OR => 1,
|
||||||
|
\T_LOGICAL_XOR => 1,
|
||||||
|
\T_BOOLEAN_AND => 1,
|
||||||
|
\T_BOOLEAN_OR => 1,
|
||||||
|
\T_LOGICAL_AND => 1
|
||||||
),
|
),
|
||||||
self::MACRO_MATH => array(
|
self::MACRO_MATH => array(
|
||||||
"+" => 1, "-" => 1, "*" => 1, "/" => 1, "^" => 1, "%" => 1, "&" => 1, "|" => 1
|
"+" => 1,
|
||||||
|
"-" => 1,
|
||||||
|
"*" => 1,
|
||||||
|
"/" => 1,
|
||||||
|
"^" => 1,
|
||||||
|
"%" => 1,
|
||||||
|
"&" => 1,
|
||||||
|
"|" => 1
|
||||||
),
|
),
|
||||||
self::MACRO_COND => array(
|
self::MACRO_COND => array(
|
||||||
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, ">" => 1, "<" => 1, \T_SL => 1, \T_SR => 1,
|
\T_IS_EQUAL => 1,
|
||||||
\T_IS_NOT_EQUAL => 1, \T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1,
|
\T_IS_IDENTICAL => 1,
|
||||||
|
">" => 1,
|
||||||
|
"<" => 1,
|
||||||
|
\T_SL => 1,
|
||||||
|
\T_SR => 1,
|
||||||
|
\T_IS_NOT_EQUAL => 1,
|
||||||
|
\T_IS_NOT_IDENTICAL => 1,
|
||||||
|
\T_IS_SMALLER_OR_EQUAL => 1,
|
||||||
),
|
),
|
||||||
self::MACRO_EQUALS => array(
|
self::MACRO_EQUALS => array(
|
||||||
\T_AND_EQUAL => 1, \T_DIV_EQUAL => 1, \T_MINUS_EQUAL => 1, \T_MOD_EQUAL => 1,
|
\T_AND_EQUAL => 1,
|
||||||
\T_MUL_EQUAL => 1, \T_OR_EQUAL => 1, \T_PLUS_EQUAL => 1, \T_SL_EQUAL => 1, \T_SR_EQUAL => 1,
|
\T_DIV_EQUAL => 1,
|
||||||
\T_XOR_EQUAL => 1, '=' => 1,
|
\T_MINUS_EQUAL => 1,
|
||||||
|
\T_MOD_EQUAL => 1,
|
||||||
|
\T_MUL_EQUAL => 1,
|
||||||
|
\T_OR_EQUAL => 1,
|
||||||
|
\T_PLUS_EQUAL => 1,
|
||||||
|
\T_SL_EQUAL => 1,
|
||||||
|
\T_SR_EQUAL => 1,
|
||||||
|
\T_XOR_EQUAL => 1,
|
||||||
|
'=' => 1,
|
||||||
// \T_CONCAT_EQUAL => 1,
|
// \T_CONCAT_EQUAL => 1,
|
||||||
),
|
),
|
||||||
self::MACRO_SCALAR => array(
|
self::MACRO_SCALAR => array(
|
||||||
\T_LNUMBER => 1, \T_DNUMBER => 1, \T_CONSTANT_ENCAPSED_STRING => 1
|
\T_LNUMBER => 1,
|
||||||
|
\T_DNUMBER => 1,
|
||||||
|
\T_CONSTANT_ENCAPSED_STRING => 1
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $description = array(
|
public static $description = array(
|
||||||
self::MACRO_STRING => 'string',
|
self::MACRO_STRING => 'string',
|
||||||
self::MACRO_INCDEC => 'increment/decrement operator',
|
self::MACRO_INCDEC => 'increment/decrement operator',
|
||||||
self::MACRO_UNARY => 'unary operator',
|
self::MACRO_UNARY => 'unary operator',
|
||||||
self::MACRO_BINARY => 'binary operator',
|
self::MACRO_BINARY => 'binary operator',
|
||||||
self::MACRO_BOOLEAN => 'boolean operator',
|
self::MACRO_BOOLEAN => 'boolean operator',
|
||||||
self::MACRO_MATH => 'math operator',
|
self::MACRO_MATH => 'math operator',
|
||||||
self::MACRO_COND => 'conditional operator',
|
self::MACRO_COND => 'conditional operator',
|
||||||
self::MACRO_EQUALS => 'equal operator',
|
self::MACRO_EQUALS => 'equal operator',
|
||||||
self::MACRO_SCALAR => 'scalar value'
|
self::MACRO_SCALAR => 'scalar value'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,7 +267,12 @@ class Tokenizer
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $spec = array(
|
private static $spec = array(
|
||||||
'true' => 1, 'false' => 1, 'null' => 1, 'TRUE' => 1, 'FALSE' => 1, 'NULL' => 1
|
'true' => 1,
|
||||||
|
'false' => 1,
|
||||||
|
'null' => 1,
|
||||||
|
'TRUE' => 1,
|
||||||
|
'FALSE' => 1,
|
||||||
|
'NULL' => 1
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,9 +280,9 @@ class Tokenizer
|
|||||||
*/
|
*/
|
||||||
public function __construct($query)
|
public function __construct($query)
|
||||||
{
|
{
|
||||||
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
|
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
|
||||||
$_tokens = token_get_all("<?php " . $query);
|
$_tokens = token_get_all("<?php " . $query);
|
||||||
$line = 1;
|
$line = 1;
|
||||||
array_shift($_tokens);
|
array_shift($_tokens);
|
||||||
$i = 0;
|
$i = 0;
|
||||||
foreach ($_tokens as $token) {
|
foreach ($_tokens as $token) {
|
||||||
@ -197,8 +312,8 @@ class Tokenizer
|
|||||||
|
|
||||||
}
|
}
|
||||||
unset($tokens[-1]);
|
unset($tokens[-1]);
|
||||||
$this->tokens = $tokens;
|
$this->tokens = $tokens;
|
||||||
$this->_max = count($this->tokens) - 1;
|
$this->_max = count($this->tokens) - 1;
|
||||||
$this->_last_no = $this->tokens[$this->_max][3];
|
$this->_last_no = $this->tokens[$this->_max][3];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,7 +502,7 @@ class Tokenizer
|
|||||||
public function hasBackList($token1 /*, $token2 ...*/)
|
public function hasBackList($token1 /*, $token2 ...*/)
|
||||||
{
|
{
|
||||||
$tokens = func_get_args();
|
$tokens = func_get_args();
|
||||||
$c = $this->p;
|
$c = $this->p;
|
||||||
foreach ($tokens as $token) {
|
foreach ($tokens as $token) {
|
||||||
$c--;
|
$c--;
|
||||||
if ($c < 0 || $this->tokens[$c][0] !== $token) {
|
if ($c < 0 || $this->tokens[$c][0] !== $token) {
|
||||||
@ -520,7 +635,7 @@ class Tokenizer
|
|||||||
public function getSnippet($before = 0, $after = 0)
|
public function getSnippet($before = 0, $after = 0)
|
||||||
{
|
{
|
||||||
$from = 0;
|
$from = 0;
|
||||||
$to = $this->p;
|
$to = $this->p;
|
||||||
if ($before > 0) {
|
if ($before > 0) {
|
||||||
if ($before > $this->p) {
|
if ($before > $this->p) {
|
||||||
$from = $this->p;
|
$from = $this->p;
|
||||||
|
@ -12,38 +12,38 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
public $fenom;
|
public $fenom;
|
||||||
|
|
||||||
public $values = array(
|
public $values = array(
|
||||||
"zero" => 0,
|
"zero" => 0,
|
||||||
"one" => 1,
|
"one" => 1,
|
||||||
"two" => 2,
|
"two" => 2,
|
||||||
"three" => 3,
|
"three" => 3,
|
||||||
"float" => 4.5,
|
"float" => 4.5,
|
||||||
"bool" => true,
|
"bool" => true,
|
||||||
0 => "empty value",
|
0 => "empty value",
|
||||||
1 => "one value",
|
1 => "one value",
|
||||||
2 => "two value",
|
2 => "two value",
|
||||||
3 => "three value",
|
3 => "three value",
|
||||||
);
|
);
|
||||||
|
|
||||||
public static function getVars()
|
public static function getVars()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
"zero" => 0,
|
"zero" => 0,
|
||||||
"one" => 1,
|
"one" => 1,
|
||||||
"two" => 2,
|
"two" => 2,
|
||||||
"three" => 3,
|
"three" => 3,
|
||||||
"float" => 4.5,
|
"float" => 4.5,
|
||||||
"bool" => true,
|
"bool" => true,
|
||||||
"obj" => new \StdClass,
|
"obj" => new \StdClass,
|
||||||
"list" => array(
|
"list" => array(
|
||||||
"a" => 1,
|
"a" => 1,
|
||||||
"one" => 1,
|
"one" => 1,
|
||||||
"b" => 2,
|
"b" => 2,
|
||||||
"two" => 2
|
"two" => 2
|
||||||
),
|
),
|
||||||
0 => "empty value",
|
0 => "empty value",
|
||||||
1 => "one value",
|
1 => "one value",
|
||||||
2 => "two value",
|
2 => "two value",
|
||||||
3 => "three value",
|
3 => "three value",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +56,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/' . $this->template_path, FENOM_RESOURCES . '/compile');
|
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/' . $this->template_path, FENOM_RESOURCES . '/compile');
|
||||||
|
$this->fenom->addProvider('persist', new Provider(FENOM_RESOURCES . '/provider'));
|
||||||
$this->fenom->addModifier('dots', __CLASS__ . '::dots');
|
$this->fenom->addModifier('dots', __CLASS__ . '::dots');
|
||||||
$this->fenom->addModifier('concat', __CLASS__ . '::concat');
|
$this->fenom->addModifier('concat', __CLASS__ . '::concat');
|
||||||
$this->fenom->addModifier('append', __CLASS__ . '::append');
|
$this->fenom->addModifier('append', __CLASS__ . '::append');
|
||||||
@ -123,7 +124,8 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
$this->fenom->setOptions($options);
|
$this->fenom->setOptions($options);
|
||||||
$tpl = $this->fenom->compileCode($code, "runtime.tpl");
|
$tpl = $this->fenom->compileCode($code, "runtime.tpl");
|
||||||
if ($dump) {
|
if ($dump) {
|
||||||
echo "\n========= DUMP BEGIN ===========\n" . $code . "\n--- to ---\n" . $tpl->getBody() . "\n========= DUMP END =============\n";
|
echo "\n========= DUMP BEGIN ===========\n" . $code . "\n--- to ---\n" . $tpl->getBody(
|
||||||
|
) . "\n========= DUMP END =============\n";
|
||||||
}
|
}
|
||||||
$this->assertSame(Modifier::strip($result, true), Modifier::strip($tpl->fetch($vars), true), "Test $code");
|
$this->assertSame(Modifier::strip($result, true), Modifier::strip($tpl->fetch($vars), true), "Test $code");
|
||||||
return $tpl;
|
return $tpl;
|
||||||
@ -134,7 +136,8 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
$this->tpl($name, $code);
|
$this->tpl($name, $code);
|
||||||
$tpl = $this->fenom->getTemplate($name);
|
$tpl = $this->fenom->getTemplate($name);
|
||||||
if ($dump) {
|
if ($dump) {
|
||||||
echo "\n========= DUMP BEGIN ===========\n" . $code . "\n--- to ---\n" . $tpl->getBody() . "\n========= DUMP END =============\n";
|
echo "\n========= DUMP BEGIN ===========\n" . $code . "\n--- to ---\n" . $tpl->getBody(
|
||||||
|
) . "\n========= DUMP END =============\n";
|
||||||
}
|
}
|
||||||
$this->assertSame(Modifier::strip($result, true), Modifier::strip($tpl->fetch($vars), true), "Test tpl $name");
|
$this->assertSame(Modifier::strip($result, true), Modifier::strip($tpl->fetch($vars), true), "Test tpl $name");
|
||||||
}
|
}
|
||||||
@ -234,7 +237,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
public static function providerArrays()
|
public static function providerArrays()
|
||||||
{
|
{
|
||||||
$scalars = array();
|
$scalars = array();
|
||||||
$data = array(
|
$data = array(
|
||||||
array('[]', array()),
|
array('[]', array()),
|
||||||
array('[[],[]]', array(array(), array())),
|
array('[[],[]]', array(array(), array())),
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ class AutoEscapeTest extends TestCase
|
|||||||
array('{$html}, {$html}', "$html, $html", $vars, 0),
|
array('{$html}, {$html}', "$html, $html", $vars, 0),
|
||||||
array('{$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{raw $html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{raw $html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{raw $html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{raw $html}, {$html}', "$html, $html", $vars, 0),
|
||||||
array('{raw "{$html|up}"}, {$html}', strtoupper($html) . ", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{raw "{$html|up}"}, {$html}', strtoupper($html) . ", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{autoescape true}{$html}{/autoescape}, {$html}', "$escaped, $html", $vars, 0),
|
array('{autoescape true}{$html}{/autoescape}, {$html}', "$escaped, $html", $vars, 0),
|
||||||
array('{autoescape false}{$html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{autoescape false}{$html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
@ -29,34 +29,122 @@ class AutoEscapeTest extends TestCase
|
|||||||
array('{autoescape false}{raw $html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{autoescape false}{raw $html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{autoescape true}{raw $html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{autoescape true}{raw $html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{autoescape false}{raw $html}{/autoescape}, {$html}', "$html, $html", $vars, 0),
|
array('{autoescape false}{raw $html}{/autoescape}, {$html}', "$html, $html", $vars, 0),
|
||||||
|
|
||||||
// inline function
|
// inline function
|
||||||
array('{test_function text=$html}, {$html}', "$html, $html", $vars, 0),
|
array('{test_function text=$html}, {$html}', "$html, $html", $vars, 0),
|
||||||
array('{test_function text=$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{test_function text=$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{test_function:raw text=$html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array('{test_function:raw text=$html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{test_function:raw text="{$html|up}"}, {$html}', strtoupper($html) . ", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array(
|
||||||
array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$escaped, $html", $vars, 0),
|
'{test_function:raw text="{$html|up}"}, {$html}',
|
||||||
array('{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
strtoupper($html) . ", $escaped",
|
||||||
array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
$vars,
|
||||||
array('{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
\Fenom::AUTO_ESCAPE
|
||||||
array('{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
),
|
||||||
array('{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array(
|
||||||
array('{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
'{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
array('{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}', "$html, $html", $vars, 0),
|
"$escaped, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$html, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$escaped, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_function text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$html, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$html, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$html, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$html, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_function:raw text=$html}{/autoescape}, {test_function text=$html}',
|
||||||
|
"$html, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
// block function
|
// block function
|
||||||
array('{test_block_function}{$html}{/test_block_function}', $html, $vars, 0),
|
array('{test_block_function}{$html}{/test_block_function}', $html, $vars, 0),
|
||||||
array('{test_block_function}{$html}{/test_block_function}', $escaped, $vars, \Fenom::AUTO_ESCAPE),
|
array('{test_block_function}{$html}{/test_block_function}', $escaped, $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{test_block_function:raw}{$html}{/test_block_function}', $html, $vars, \Fenom::AUTO_ESCAPE),
|
array('{test_block_function:raw}{$html}{/test_block_function}', $html, $vars, \Fenom::AUTO_ESCAPE),
|
||||||
array('{test_block_function:raw}{"{$html|up}"}{/test_block_function}', strtoupper($html), $vars, \Fenom::AUTO_ESCAPE),
|
array(
|
||||||
array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $html", $vars, 0),
|
'{test_block_function:raw}{"{$html|up}"}{/test_block_function}',
|
||||||
array('{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
strtoupper($html),
|
||||||
array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
$vars,
|
||||||
array('{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
\Fenom::AUTO_ESCAPE
|
||||||
array('{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
),
|
||||||
array('{autoescape false}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
array(
|
||||||
array('{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function:raw}{$html}{/test_block_function}', "$escaped, $html", $vars, \Fenom::AUTO_ESCAPE),
|
'{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}',
|
||||||
array('{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function:raw}{$html}{/test_block_function}', "$html, $html", $vars, 0),
|
"$escaped, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}',
|
||||||
|
"$html, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}',
|
||||||
|
"$escaped, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}',
|
||||||
|
"$html, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}',
|
||||||
|
"$html, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape false}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function}{$html}{/test_block_function}',
|
||||||
|
"$html, $escaped",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_block_function}{$html}{/test_block_function}{/autoescape}, {test_block_function:raw}{$html}{/test_block_function}',
|
||||||
|
"$escaped, $html",
|
||||||
|
$vars,
|
||||||
|
\Fenom::AUTO_ESCAPE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{autoescape true}{test_block_function:raw}{$html}{/test_block_function}{/autoescape}, {test_block_function:raw}{$html}{/test_block_function}',
|
||||||
|
"$html, $html",
|
||||||
|
$vars,
|
||||||
|
0
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,21 @@ class ExtendsTest extends TestCase
|
|||||||
public static function providerExtendsInvalid()
|
public static function providerExtendsInvalid()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('{extends "extends/dynamic/child.3.tpl"} {extends "extends/dynamic/child.3.tpl"}', 'Fenom\Error\CompileException', "Only one {extends} allowed"),
|
array(
|
||||||
array('{if true}{extends "extends/dynamic/child.3.tpl"}{/if}', 'Fenom\Error\CompileException', "Tag {extends} can not be nested"),
|
'{extends "extends/dynamic/child.3.tpl"} {extends "extends/dynamic/child.3.tpl"}',
|
||||||
array('{if true}{use "extends/dynamic/use.tpl"}{/if}', 'Fenom\Error\CompileException', "Tag {use} can not be nested"),
|
'Fenom\Error\CompileException',
|
||||||
|
"Only one {extends} allowed"
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{if true}{extends "extends/dynamic/child.3.tpl"}{/if}',
|
||||||
|
'Fenom\Error\CompileException',
|
||||||
|
"Tag {extends} can not be nested"
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{if true}{use "extends/dynamic/use.tpl"}{/if}',
|
||||||
|
'Fenom\Error\CompileException',
|
||||||
|
"Tag {use} can not be nested"
|
||||||
|
),
|
||||||
array('{use $use_this}', 'Fenom\Error\CompileException', "Invalid template name for tag {use}"),
|
array('{use $use_this}', 'Fenom\Error\CompileException', "Invalid template name for tag {use}"),
|
||||||
array('{block $use_this}{/block}', 'Fenom\Error\CompileException', "Invalid block name"),
|
array('{block $use_this}{/block}', 'Fenom\Error\CompileException', "Invalid block name"),
|
||||||
);
|
);
|
||||||
@ -54,12 +66,18 @@ Before body
|
|||||||
Child 3 content
|
Child 3 content
|
||||||
Before footer
|
Before footer
|
||||||
Footer from use";
|
Footer from use";
|
||||||
$this->assertSame($result, $this->fenom->fetch(array(
|
$this->assertSame(
|
||||||
'extends/auto/child.3.tpl',
|
$result,
|
||||||
'extends/auto/child.2.tpl',
|
$this->fenom->fetch(
|
||||||
'extends/auto/child.1.tpl',
|
array(
|
||||||
'extends/auto/parent.tpl',
|
'extends/auto/child.3.tpl',
|
||||||
), array()));
|
'extends/auto/child.2.tpl',
|
||||||
|
'extends/auto/child.1.tpl',
|
||||||
|
'extends/auto/parent.tpl',
|
||||||
|
),
|
||||||
|
array()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStaticExtendLevel1()
|
public function testStaticExtendLevel1()
|
||||||
@ -92,11 +110,17 @@ Before body
|
|||||||
Child 3 content
|
Child 3 content
|
||||||
Before footer
|
Before footer
|
||||||
Footer from use";
|
Footer from use";
|
||||||
$this->assertSame($result, $this->fenom->fetch(array(
|
$this->assertSame(
|
||||||
'extends/auto/child.3.tpl',
|
$result,
|
||||||
'extends/auto/child.2.tpl',
|
$this->fenom->fetch(
|
||||||
'extends/auto/static/child.1.tpl'
|
array(
|
||||||
), array()));
|
'extends/auto/child.3.tpl',
|
||||||
|
'extends/auto/child.2.tpl',
|
||||||
|
'extends/auto/static/child.1.tpl'
|
||||||
|
),
|
||||||
|
array()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStaticExtendNested()
|
public function testStaticExtendNested()
|
||||||
|
@ -7,56 +7,74 @@ class MacrosTest extends TestCase
|
|||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->tpl("math.tpl", '
|
$this->tpl(
|
||||||
{macro plus(x, y)}
|
"math.tpl",
|
||||||
x + y = {$x + $y}
|
'
|
||||||
{/macro}
|
{macro plus(x, y)}
|
||||||
|
x + y = {$x + $y}
|
||||||
|
{/macro}
|
||||||
|
|
||||||
{macro minus(x, y, z=0)}
|
{macro minus(x, y, z=0)}
|
||||||
x - y - z = {$x - $y - $z}
|
x - y - z = {$x - $y - $z}
|
||||||
{/macro}
|
{/macro}
|
||||||
|
|
||||||
{macro multi(x, y)}
|
{macro multi(x, y)}
|
||||||
x * y = {$x * $y}
|
x * y = {$x * $y}
|
||||||
{/macro}
|
{/macro}
|
||||||
|
|
||||||
Math: {macro.plus x=2 y=3}, {macro.minus x=10 y=4}
|
Math: {macro.plus x=2 y=3}, {macro.minus x=10 y=4}
|
||||||
');
|
'
|
||||||
|
);
|
||||||
|
|
||||||
$this->tpl("import.tpl", '
|
$this->tpl(
|
||||||
{import "math.tpl"}
|
"import.tpl",
|
||||||
{import "math.tpl" as math}
|
'
|
||||||
|
{import "math.tpl"}
|
||||||
|
{import "math.tpl" as math}
|
||||||
|
|
||||||
Imp: {macro.plus x=1 y=2}, {math.minus x=6 y=2 z=1}
|
Imp: {macro.plus x=1 y=2}, {math.minus x=6 y=2 z=1}
|
||||||
');
|
'
|
||||||
|
);
|
||||||
|
|
||||||
$this->tpl("import_custom.tpl", '
|
$this->tpl(
|
||||||
{macro minus($x, $y)}
|
"import_custom.tpl",
|
||||||
new minus macros
|
'
|
||||||
{/macro}
|
{macro minus($x, $y)}
|
||||||
{import [plus, minus] from "math.tpl" as math}
|
new minus macros
|
||||||
|
{/macro}
|
||||||
|
{import [plus, minus] from "math.tpl" as math}
|
||||||
|
|
||||||
a: {math.plus x=1 y=2}, {math.minus x=6 y=2 z=1}, {macro.minus x=5 y=3}.
|
a: {math.plus x=1 y=2}, {math.minus x=6 y=2 z=1}, {macro.minus x=5 y=3}.
|
||||||
');
|
'
|
||||||
|
);
|
||||||
|
|
||||||
$this->tpl("import_miss.tpl", '
|
$this->tpl(
|
||||||
{import [minus] from "math.tpl" as math}
|
"import_miss.tpl",
|
||||||
|
'
|
||||||
|
{import [minus] from "math.tpl" as math}
|
||||||
|
|
||||||
a: {macro.plus x=5 y=3}.
|
a: {macro.plus x=5 y=3}.
|
||||||
');
|
'
|
||||||
|
);
|
||||||
|
|
||||||
$this->tpl("macro_recursive.tpl", '{macro factorial(num)}
|
$this->tpl(
|
||||||
{if $num}
|
"macro_recursive.tpl",
|
||||||
{$num} {macro.factorial num=$num-1} {$num}
|
'{macro factorial(num)}
|
||||||
{/if}
|
{if $num}
|
||||||
{/macro}
|
{$num} {macro.factorial num=$num-1} {$num}
|
||||||
|
{/if}
|
||||||
|
{/macro}
|
||||||
|
|
||||||
{macro.factorial num=10}');
|
{macro.factorial num=10}'
|
||||||
|
);
|
||||||
|
|
||||||
$this->tpl("macro_recursive_import.tpl", '
|
$this->tpl(
|
||||||
{import "macro_recursive.tpl" as math}
|
"macro_recursive_import.tpl",
|
||||||
|
'
|
||||||
|
{import "macro_recursive.tpl" as math}
|
||||||
|
|
||||||
{math.factorial num=10}');
|
{math.factorial num=10}'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function _testSandbox()
|
public function _testSandbox()
|
||||||
@ -65,11 +83,15 @@ class MacrosTest extends TestCase
|
|||||||
// $this->fenom->compile("macro_recursive.tpl")->display([]);
|
// $this->fenom->compile("macro_recursive.tpl")->display([]);
|
||||||
// $this->fenom->flush();
|
// $this->fenom->flush();
|
||||||
// var_dump($this->fenom->fetch("macro_recursive.tpl", []));
|
// var_dump($this->fenom->fetch("macro_recursive.tpl", []));
|
||||||
var_dump($this->fenom->compileCode('{macro factorial(num)}
|
var_dump(
|
||||||
{if $num}
|
$this->fenom->compileCode(
|
||||||
{$num} {macro.factorial num=$num-1} {$num}
|
'{macro factorial(num)}
|
||||||
{/if}
|
{if $num}
|
||||||
{/macro}')->getBody());
|
{$num} {macro.factorial num=$num-1} {$num}
|
||||||
|
{/if}
|
||||||
|
{/macro}'
|
||||||
|
)->getBody()
|
||||||
|
);
|
||||||
// var_dump($this->fenom->display("macro_recursive_import.tpl", array()));
|
// var_dump($this->fenom->display("macro_recursive_import.tpl", array()));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
var_dump($e->getMessage() . ": " . $e->getTraceAsString());
|
var_dump($e->getMessage() . ": " . $e->getTraceAsString());
|
||||||
@ -99,7 +121,10 @@ class MacrosTest extends TestCase
|
|||||||
{
|
{
|
||||||
$tpl = $this->fenom->compile('import_custom.tpl');
|
$tpl = $this->fenom->compile('import_custom.tpl');
|
||||||
|
|
||||||
$this->assertSame('a: x + y = 3 , x - y - z = 3 , new minus macros .', Modifier::strip($tpl->fetch(array()), true));
|
$this->assertSame(
|
||||||
|
'a: x + y = 3 , x - y - z = 3 , new minus macros .',
|
||||||
|
Modifier::strip($tpl->fetch(array()), true)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,7 +135,10 @@ class MacrosTest extends TestCase
|
|||||||
{
|
{
|
||||||
$tpl = $this->fenom->compile('import_miss.tpl');
|
$tpl = $this->fenom->compile('import_miss.tpl');
|
||||||
|
|
||||||
$this->assertSame('a: x + y = 3 , x - y - z = 3 , new minus macros .', Modifier::strip($tpl->fetch(array()), true));
|
$this->assertSame(
|
||||||
|
'a: x + y = 3 , x - y - z = 3 , new minus macros .',
|
||||||
|
Modifier::strip($tpl->fetch(array()), true)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,7 +8,7 @@ class ModifiersTest extends TestCase
|
|||||||
public static function providerTruncate()
|
public static function providerTruncate()
|
||||||
{
|
{
|
||||||
$lorem = 'Lorem ipsum dolor sit amet'; // en
|
$lorem = 'Lorem ipsum dolor sit amet'; // en
|
||||||
$uni = 'Лорем ипсум долор сит амет'; // ru
|
$uni = 'Лорем ипсум долор сит амет'; // ru
|
||||||
return array(
|
return array(
|
||||||
// ascii chars
|
// ascii chars
|
||||||
array($lorem, 'Lorem ip...', 8),
|
array($lorem, 'Lorem ip...', 8),
|
||||||
@ -38,13 +38,18 @@ class ModifiersTest extends TestCase
|
|||||||
public function testTruncate($in, $out, $count, $delim = '...', $by_words = false, $middle = false)
|
public function testTruncate($in, $out, $count, $delim = '...', $by_words = false, $middle = false)
|
||||||
{
|
{
|
||||||
$tpl = $this->fenom->compileCode('{$text|truncate:$count:$delim:$by_words:$middle}');
|
$tpl = $this->fenom->compileCode('{$text|truncate:$count:$delim:$by_words:$middle}');
|
||||||
$this->assertEquals($out, $tpl->fetch(array(
|
$this->assertEquals(
|
||||||
"text" => $in,
|
$out,
|
||||||
"count" => $count,
|
$tpl->fetch(
|
||||||
"delim" => $delim,
|
array(
|
||||||
"by_words" => $by_words,
|
"text" => $in,
|
||||||
"middle" => $middle
|
"count" => $count,
|
||||||
)));
|
"delim" => $delim,
|
||||||
|
"by_words" => $by_words,
|
||||||
|
"middle" => $middle
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function providerUpLow()
|
public static function providerUpLow()
|
||||||
@ -71,9 +76,14 @@ class ModifiersTest extends TestCase
|
|||||||
public function testUpLow($modifier, $in, $out)
|
public function testUpLow($modifier, $in, $out)
|
||||||
{
|
{
|
||||||
$tpl = $this->fenom->compileCode('{$text|' . $modifier . '}');
|
$tpl = $this->fenom->compileCode('{$text|' . $modifier . '}');
|
||||||
$this->assertEquals($out, $tpl->fetch(array(
|
$this->assertEquals(
|
||||||
"text" => $in,
|
$out,
|
||||||
)));
|
$tpl->fetch(
|
||||||
|
array(
|
||||||
|
"text" => $in,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function providerLength()
|
public static function providerLength()
|
||||||
@ -99,9 +109,14 @@ class ModifiersTest extends TestCase
|
|||||||
public function testLength($in, $out)
|
public function testLength($in, $out)
|
||||||
{
|
{
|
||||||
$tpl = $this->fenom->compileCode('{$data|length}');
|
$tpl = $this->fenom->compileCode('{$data|length}');
|
||||||
$this->assertEquals($out, $tpl->fetch(array(
|
$this->assertEquals(
|
||||||
"data" => $in,
|
$out,
|
||||||
)));
|
$tpl->fetch(
|
||||||
|
array(
|
||||||
|
"data" => $in,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -88,7 +88,7 @@ class ProviderTest extends TestCase
|
|||||||
clearstatcache();
|
clearstatcache();
|
||||||
$templates = array(
|
$templates = array(
|
||||||
"template1.tpl" => filemtime(FENOM_RESOURCES . '/template/template1.tpl'),
|
"template1.tpl" => filemtime(FENOM_RESOURCES . '/template/template1.tpl'),
|
||||||
"unexists.tpl" => 1234567890
|
"unexists.tpl" => 1234567890
|
||||||
);
|
);
|
||||||
$this->assertFalse($this->provider->verify($templates));
|
$this->assertFalse($this->provider->verify($templates));
|
||||||
}
|
}
|
||||||
@ -97,11 +97,14 @@ class ProviderTest extends TestCase
|
|||||||
{
|
{
|
||||||
$list = $this->provider->getList();
|
$list = $this->provider->getList();
|
||||||
sort($list);
|
sort($list);
|
||||||
$this->assertSame(array(
|
$this->assertSame(
|
||||||
"sub/template3.tpl",
|
array(
|
||||||
"template1.tpl",
|
"sub/template3.tpl",
|
||||||
"template2.tpl"
|
"template1.tpl",
|
||||||
), $list);
|
"template2.tpl"
|
||||||
|
),
|
||||||
|
$list
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRm()
|
public function testRm()
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
namespace Fenom;
|
namespace Fenom;
|
||||||
|
|
||||||
|
|
||||||
class TagOptionTest extends TestCase {
|
class TagOptionTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
public function testTrim() {
|
public function testTrim()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,7 +37,10 @@ class TagsTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testVarBlockModified($tpl_val, $val)
|
public function testVarBlockModified($tpl_val, $val)
|
||||||
{
|
{
|
||||||
$this->assertRender("{var \$a|low|dots}before {{$tpl_val}} after{/var}\nVar: {\$a}", "Var: " . strtolower("before " . $val . " after") . "...");
|
$this->assertRender(
|
||||||
|
"{var \$a|low|dots}before {{$tpl_val}} after{/var}\nVar: {\$a}",
|
||||||
|
"Var: " . strtolower("before " . $val . " after") . "..."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCycle()
|
public function testCycle()
|
||||||
@ -50,7 +53,10 @@ class TagsTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testCycleIndex()
|
public function testCycleIndex()
|
||||||
{
|
{
|
||||||
$this->assertRender('{var $a=["one", "two"]}{for $i=1 to=5}{cycle $a index=$i}, {/for}', "two, one, two, one, two, ");
|
$this->assertRender(
|
||||||
|
'{var $a=["one", "two"]}{for $i=1 to=5}{cycle $a index=$i}, {/for}',
|
||||||
|
"two, one, two, one, two, "
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@ class TokenizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testTokens()
|
public function testTokens()
|
||||||
{
|
{
|
||||||
$code = 'hello, please resolve this example: sin($x)+tan($x*$t) = {U|[0,1]}';
|
$code = 'hello, please resolve this example: sin($x)+tan($x*$t) = {U|[0,1]}';
|
||||||
$tokens = new Tokenizer($code);
|
$tokens = new Tokenizer($code);
|
||||||
$this->assertSame(27, $tokens->count());
|
$this->assertSame(27, $tokens->count());
|
||||||
$this->assertSame($tokens, $tokens->back());
|
$this->assertSame($tokens, $tokens->back());
|
||||||
@ -38,13 +38,16 @@ class TokenizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertSame(",", $tokens->getNext());
|
$this->assertSame(",", $tokens->getNext());
|
||||||
$this->assertSame(",", $tokens->key());
|
$this->assertSame(",", $tokens->key());
|
||||||
$this->assertSame("please", $tokens->getNext(T_STRING));
|
$this->assertSame("please", $tokens->getNext(T_STRING));
|
||||||
$this->assertSame(array(
|
$this->assertSame(
|
||||||
T_STRING,
|
array(
|
||||||
'please',
|
T_STRING,
|
||||||
' ',
|
'please',
|
||||||
1,
|
' ',
|
||||||
'T_STRING'
|
1,
|
||||||
), $tokens->curr);
|
'T_STRING'
|
||||||
|
),
|
||||||
|
$tokens->curr
|
||||||
|
);
|
||||||
$this->assertSame("resolve", $tokens->getNext($tokens::MACRO_UNARY, T_STRING));
|
$this->assertSame("resolve", $tokens->getNext($tokens::MACRO_UNARY, T_STRING));
|
||||||
|
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
@ -80,7 +83,7 @@ class TokenizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testSkip()
|
public function testSkip()
|
||||||
{
|
{
|
||||||
$text = "1 foo: bar ( 3 + double ) ";
|
$text = "1 foo: bar ( 3 + double ) ";
|
||||||
$tokens = new Tokenizer($text);
|
$tokens = new Tokenizer($text);
|
||||||
|
|
||||||
$tokens->skip()->skip(T_STRING)->skip(':');
|
$tokens->skip()->skip(T_STRING)->skip(':');
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Fenom\Render,
|
|
||||||
Fenom\Provider as FS;
|
|
||||||
|
|
||||||
class FenomTest extends \Fenom\TestCase
|
class FenomTest extends \Fenom\TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -20,9 +17,10 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testCreating()
|
public function testCreating()
|
||||||
{
|
{
|
||||||
$time = $this->tpl('temp.tpl', 'Template 1 a');
|
$time = $this->tpl('temp.tpl', 'Template 1 a');
|
||||||
$fenom = new Fenom($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'));
|
$fenom = new Fenom($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'));
|
||||||
$fenom->setCompileDir(FENOM_RESOURCES . '/compile');
|
$fenom->setCompileDir(FENOM_RESOURCES . '/compile');
|
||||||
$this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
|
$this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
|
||||||
@ -35,8 +33,12 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
|
|
||||||
public function testFactory()
|
public function testFactory()
|
||||||
{
|
{
|
||||||
$time = $this->tpl('temp.tpl', 'Template 1 a');
|
$time = $this->tpl('temp.tpl', 'Template 1 a');
|
||||||
$fenom = Fenom::factory($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'), FENOM_RESOURCES . '/compile', Fenom::AUTO_ESCAPE);
|
$fenom = Fenom::factory(
|
||||||
|
$provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'),
|
||||||
|
FENOM_RESOURCES . '/compile',
|
||||||
|
Fenom::AUTO_ESCAPE
|
||||||
|
);
|
||||||
$this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
|
$this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
|
||||||
$this->assertSame($provider, $tpl->getProvider());
|
$this->assertSame($provider, $tpl->getProvider());
|
||||||
$this->assertSame('temp.tpl', $tpl->getBaseName());
|
$this->assertSame('temp.tpl', $tpl->getBaseName());
|
||||||
@ -45,6 +47,25 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
$fenom->clearAllCompiles();
|
$fenom->clearAllCompiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException LogicException
|
||||||
|
* @expectedExceptionMessage Cache directory /invalid/path is not writable
|
||||||
|
*/
|
||||||
|
public function testFactoryInvalid()
|
||||||
|
{
|
||||||
|
Fenom::factory(FENOM_RESOURCES . '/template', '/invalid/path');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
* @expectedExceptionMessage Source must be a valid path or provider object
|
||||||
|
*/
|
||||||
|
public function testFactoryInvalid2()
|
||||||
|
{
|
||||||
|
Fenom::factory(new StdClass);
|
||||||
|
}
|
||||||
|
|
||||||
public function testCompileFile()
|
public function testCompileFile()
|
||||||
{
|
{
|
||||||
$a = array(
|
$a = array(
|
||||||
@ -97,7 +118,10 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
{
|
{
|
||||||
$this->fenom->addModifier("mymod", "myMod");
|
$this->fenom->addModifier("mymod", "myMod");
|
||||||
$this->tpl('custom.tpl', 'Custom modifier {$a|mymod}');
|
$this->tpl('custom.tpl', 'Custom modifier {$a|mymod}');
|
||||||
$this->assertSame("Custom modifier (myMod)Custom(/myMod)", $this->fenom->fetch('custom.tpl', array("a" => "Custom")));
|
$this->assertSame(
|
||||||
|
"Custom modifier (myMod)Custom(/myMod)",
|
||||||
|
$this->fenom->fetch('custom.tpl', array("a" => "Custom"))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,13 +142,27 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
{
|
{
|
||||||
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
||||||
$this->fenom->addCompiler("mycompiler", 'myCompiler');
|
$this->fenom->addCompiler("mycompiler", 'myCompiler');
|
||||||
$this->fenom->addBlockCompiler("myblockcompiler", 'myBlockCompilerOpen', 'myBlockCompilerClose', array(
|
$this->fenom->addBlockCompiler(
|
||||||
'tag' => 'myBlockCompilerTag'
|
"myblockcompiler",
|
||||||
));
|
'myBlockCompilerOpen',
|
||||||
|
'myBlockCompilerClose',
|
||||||
|
array(
|
||||||
|
'tag' => 'myBlockCompilerTag'
|
||||||
|
)
|
||||||
|
);
|
||||||
$this->tpl('custom.tpl', 'Custom compiler {mycompiler name="bar"}');
|
$this->tpl('custom.tpl', 'Custom compiler {mycompiler name="bar"}');
|
||||||
$this->assertSame("Custom compiler PHP_VERSION: " . PHP_VERSION . " (for bar)", $this->fenom->fetch('custom.tpl', array()));
|
$this->assertSame(
|
||||||
$this->tpl('custom.tpl', 'Custom compiler {myblockcompiler name="bar"} block1 {tag name="baz"} block2 {/myblockcompiler}');
|
"Custom compiler PHP_VERSION: " . PHP_VERSION . " (for bar)",
|
||||||
$this->assertSame("Custom compiler PHP_VERSION: " . PHP_VERSION . " (for bar) block1 Tag baz of compiler block2 End of compiler", $this->fenom->fetch('custom.tpl', array()));
|
$this->fenom->fetch('custom.tpl', array())
|
||||||
|
);
|
||||||
|
$this->tpl(
|
||||||
|
'custom.tpl',
|
||||||
|
'Custom compiler {myblockcompiler name="bar"} block1 {tag name="baz"} block2 {/myblockcompiler}'
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
"Custom compiler PHP_VERSION: " . PHP_VERSION . " (for bar) block1 Tag baz of compiler block2 End of compiler",
|
||||||
|
$this->fenom->fetch('custom.tpl', array())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,23 +184,35 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
public function testFilter()
|
public function testFilter()
|
||||||
{
|
{
|
||||||
$punit = $this;
|
$punit = $this;
|
||||||
$this->fenom->addPreFilter(function ($tpl, $src) use ($punit) {
|
$this->fenom->addPreFilter(
|
||||||
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
function ($tpl, $src) use ($punit) {
|
||||||
return "== $src ==";
|
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
||||||
});
|
return "== $src ==";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$this->fenom->addPostFilter(function ($tpl, $code) use ($punit) {
|
$this->fenom->addPostFilter(
|
||||||
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
function ($tpl, $code) use ($punit) {
|
||||||
return "+++ $code +++";
|
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
||||||
});
|
return "+++ $code +++";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$this->fenom->addFilter(function ($tpl, $text) use ($punit) {
|
$this->fenom->addFilter(
|
||||||
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
function ($tpl, $text) use ($punit) {
|
||||||
return "|--- $text ---|";
|
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
||||||
});
|
return "|--- $text ---|";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} misterio {/var} world')->fetch(array()));
|
$this->assertSame(
|
||||||
$this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} <?php misterio ?> {/var} world')->fetch(array()));
|
'+++ |--- == hello ---||--- world == ---| +++',
|
||||||
|
$this->fenom->compileCode('hello {var $user} misterio {/var} world')->fetch(array())
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
'+++ |--- == hello ---||--- world == ---| +++',
|
||||||
|
$this->fenom->compileCode('hello {var $user} <?php misterio ?> {/var} world')->fetch(array())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,13 +220,15 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
*/
|
*/
|
||||||
public function testTagFilter()
|
public function testTagFilter()
|
||||||
{
|
{
|
||||||
$tags = array();
|
$tags = array();
|
||||||
$punit = $this;
|
$punit = $this;
|
||||||
$this->fenom->addTagFilter(function ($text, $tpl) use (&$tags, $punit) {
|
$this->fenom->addTagFilter(
|
||||||
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
function ($text, $tpl) use (&$tags, $punit) {
|
||||||
$tags[] = $text;
|
$punit->assertInstanceOf('Fenom\Template', $tpl);
|
||||||
return $text;
|
$tags[] = $text;
|
||||||
});
|
return $text;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$this->fenom->compileCode('hello {var $a} misterio {/var} world, {$b}!');
|
$this->fenom->compileCode('hello {var $a} misterio {/var} world, {$b}!');
|
||||||
|
|
||||||
@ -194,8 +246,10 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
{
|
{
|
||||||
$this->fenom->addBlockCompilerSmart('SayBlock', 'TestTags', array('SaySomething'), array('SaySomething'));
|
$this->fenom->addBlockCompilerSmart('SayBlock', 'TestTags', array('SaySomething'), array('SaySomething'));
|
||||||
$this->tpl('block_compiler.tpl', '{SayBlock} and {SaySomething}. It is all, {/SayBlock}');
|
$this->tpl('block_compiler.tpl', '{SayBlock} and {SaySomething}. It is all, {/SayBlock}');
|
||||||
$this->assertSame('Start saying and say blah-blah-blah. It is all, Stop saying',
|
$this->assertSame(
|
||||||
$this->fenom->fetch('block_compiler.tpl', array()));
|
'Start saying and say blah-blah-blah. It is all, Stop saying',
|
||||||
|
$this->fenom->fetch('block_compiler.tpl', array())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddFunctions()
|
public function testAddFunctions()
|
||||||
@ -205,6 +259,35 @@ class FenomTest extends \Fenom\TestCase
|
|||||||
$this->fenom->addAllowedFunctions(array('substr'));
|
$this->fenom->addAllowedFunctions(array('substr'));
|
||||||
$this->assertTrue($this->fenom->isAllowedFunction('substr'));
|
$this->assertTrue($this->fenom->isAllowedFunction('substr'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group pipe
|
||||||
|
*/
|
||||||
|
public function testPipe()
|
||||||
|
{
|
||||||
|
$iteration = 0;
|
||||||
|
$test = $this; // for PHP 5.3
|
||||||
|
$this->fenom->pipe(
|
||||||
|
"persist:pipe.tpl",
|
||||||
|
function ($chunk) use (&$iteration, $test) {
|
||||||
|
if (!$chunk) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$iteration++;
|
||||||
|
// error_log(var_export($chunk, 1));
|
||||||
|
$test->assertSame("key$iteration:value$iteration", $chunk);
|
||||||
|
},
|
||||||
|
array(
|
||||||
|
"items" => array(
|
||||||
|
"key1" => "value1",
|
||||||
|
"key2" => "value2",
|
||||||
|
"key3" => "value3",
|
||||||
|
)
|
||||||
|
),
|
||||||
|
11 // strlen(key1) + strlen(:) + strlen(value1)
|
||||||
|
);
|
||||||
|
$this->assertSame(3, $iteration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1
tests/resources/provider/pipe.tpl
Normal file
1
tests/resources/provider/pipe.tpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{foreach $items as $key => $value}{$key}:{$value}{/foreach}
|
Loading…
Reference in New Issue
Block a user