mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
To PSR-x format
This commit is contained in:
parent
4edd0e1708
commit
3674de41cb
310
src/Fenom.php
310
src/Fenom.php
@ -15,55 +15,56 @@ use Fenom\Template,
|
||||
*
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
class Fenom {
|
||||
class Fenom
|
||||
{
|
||||
const VERSION = '1.2';
|
||||
|
||||
/* Actions */
|
||||
const INLINE_COMPILER = 1;
|
||||
const BLOCK_COMPILER = 2;
|
||||
const INLINE_FUNCTION = 3;
|
||||
const BLOCK_FUNCTION = 4;
|
||||
const MODIFIER = 5;
|
||||
const INLINE_COMPILER = 1;
|
||||
const BLOCK_COMPILER = 2;
|
||||
const INLINE_FUNCTION = 3;
|
||||
const BLOCK_FUNCTION = 4;
|
||||
const MODIFIER = 5;
|
||||
|
||||
/* Options */
|
||||
const DENY_METHODS = 0x10;
|
||||
const DENY_NATIVE_FUNCS = 0x20;
|
||||
const FORCE_INCLUDE = 0x40;
|
||||
const AUTO_RELOAD = 0x80;
|
||||
const FORCE_COMPILE = 0x100;
|
||||
const AUTO_ESCAPE = 0x200;
|
||||
const DISABLE_CACHE = 0x400;
|
||||
const FORCE_VERIFY = 0x800; // reserved
|
||||
const AUTO_TRIM = 0x1000; // reserved
|
||||
const DENY_STATICS = 0x2000; // reserved
|
||||
const DENY_METHODS = 0x10;
|
||||
const DENY_NATIVE_FUNCS = 0x20;
|
||||
const FORCE_INCLUDE = 0x40;
|
||||
const AUTO_RELOAD = 0x80;
|
||||
const FORCE_COMPILE = 0x100;
|
||||
const AUTO_ESCAPE = 0x200;
|
||||
const DISABLE_CACHE = 0x400;
|
||||
const FORCE_VERIFY = 0x800; // reserved
|
||||
const AUTO_TRIM = 0x1000; // reserved
|
||||
const DENY_STATICS = 0x2000; // reserved
|
||||
|
||||
/* @deprecated */
|
||||
const DENY_INLINE_FUNCS = 0x20;
|
||||
const DENY_INLINE_FUNCS = 0x20;
|
||||
|
||||
/* Default parsers */
|
||||
const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose';
|
||||
const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser';
|
||||
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
|
||||
const DEFAULT_FUNC_CLOSE = 'Fenom\Compiler::stdFuncClose';
|
||||
const SMART_FUNC_PARSER = 'Fenom\Compiler::smartFuncParser';
|
||||
const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser';
|
||||
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
|
||||
const DEFAULT_FUNC_CLOSE = 'Fenom\Compiler::stdFuncClose';
|
||||
const SMART_FUNC_PARSER = 'Fenom\Compiler::smartFuncParser';
|
||||
|
||||
const MAX_MACRO_RECURSIVE = 32;
|
||||
const MAX_MACRO_RECURSIVE = 32;
|
||||
|
||||
/**
|
||||
* @var int[] of possible options, as associative array
|
||||
* @see setOptions
|
||||
*/
|
||||
private static $_options_list = array(
|
||||
"disable_methods" => self::DENY_METHODS,
|
||||
"disable_methods" => self::DENY_METHODS,
|
||||
"disable_native_funcs" => self::DENY_NATIVE_FUNCS,
|
||||
"disable_cache" => self::DISABLE_CACHE,
|
||||
"force_compile" => self::FORCE_COMPILE,
|
||||
"auto_reload" => self::AUTO_RELOAD,
|
||||
"force_include" => self::FORCE_INCLUDE,
|
||||
"auto_escape" => self::AUTO_ESCAPE,
|
||||
"force_verify" => self::FORCE_VERIFY,
|
||||
"auto_trim" => self::AUTO_TRIM,
|
||||
"disable_statics" => self::DENY_STATICS,
|
||||
"disable_cache" => self::DISABLE_CACHE,
|
||||
"force_compile" => self::FORCE_COMPILE,
|
||||
"auto_reload" => self::AUTO_RELOAD,
|
||||
"force_include" => self::FORCE_INCLUDE,
|
||||
"auto_escape" => self::AUTO_ESCAPE,
|
||||
"force_verify" => self::FORCE_VERIFY,
|
||||
"auto_trim" => self::AUTO_TRIM,
|
||||
"disable_statics" => self::DENY_STATICS,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -97,19 +98,19 @@ class Fenom {
|
||||
* @var string[] list of modifiers [modifier_name => callable]
|
||||
*/
|
||||
protected $_modifiers = array(
|
||||
"upper" => 'strtoupper',
|
||||
"up" => 'strtoupper',
|
||||
"lower" => 'strtolower',
|
||||
"low" => 'strtolower',
|
||||
"upper" => 'strtoupper',
|
||||
"up" => 'strtoupper',
|
||||
"lower" => 'strtolower',
|
||||
"low" => 'strtolower',
|
||||
"date_format" => 'Fenom\Modifier::dateFormat',
|
||||
"date" => 'Fenom\Modifier::date',
|
||||
"truncate" => 'Fenom\Modifier::truncate',
|
||||
"escape" => 'Fenom\Modifier::escape',
|
||||
"e" => 'Fenom\Modifier::escape', // alias of escape
|
||||
"unescape" => 'Fenom\Modifier::unescape',
|
||||
"strip" => 'Fenom\Modifier::strip',
|
||||
"length" => 'Fenom\Modifier::length',
|
||||
"iterable" => 'Fenom\Modifier::isIterable'
|
||||
"date" => 'Fenom\Modifier::date',
|
||||
"truncate" => 'Fenom\Modifier::truncate',
|
||||
"escape" => 'Fenom\Modifier::escape',
|
||||
"e" => 'Fenom\Modifier::escape', // alias of escape
|
||||
"unescape" => 'Fenom\Modifier::unescape',
|
||||
"strip" => 'Fenom\Modifier::strip',
|
||||
"length" => 'Fenom\Modifier::length',
|
||||
"iterable" => 'Fenom\Modifier::isIterable'
|
||||
);
|
||||
|
||||
/**
|
||||
@ -136,7 +137,7 @@ class Fenom {
|
||||
),
|
||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||
),
|
||||
'if' => array( // {if ...} {elseif ...} {else} {/if}
|
||||
'if' => array( // {if ...} {elseif ...} {else} {/if}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::ifOpen',
|
||||
'close' => 'Fenom\Compiler::stdClose',
|
||||
@ -145,7 +146,7 @@ class Fenom {
|
||||
'else' => 'Fenom\Compiler::tagElse',
|
||||
)
|
||||
),
|
||||
'switch' => array( // {switch ...} {case ...} {break} {default} {/switch}
|
||||
'switch' => array( // {switch ...} {case ...} {break} {default} {/switch}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::switchOpen',
|
||||
'close' => 'Fenom\Compiler::stdClose',
|
||||
@ -156,7 +157,7 @@ class Fenom {
|
||||
),
|
||||
'float_tags' => array('break' => 1)
|
||||
),
|
||||
'for' => array( // {for ...} {break} {continue} {/for}
|
||||
'for' => array( // {for ...} {break} {continue} {/for}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::forOpen',
|
||||
'close' => 'Fenom\Compiler::forClose',
|
||||
@ -167,7 +168,7 @@ class Fenom {
|
||||
),
|
||||
'float_tags' => array('break' => 1, 'continue' => 1)
|
||||
),
|
||||
'while' => array( // {while ...} {break} {continue} {/while}
|
||||
'while' => array( // {while ...} {break} {continue} {/while}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::whileOpen',
|
||||
'close' => 'Fenom\Compiler::stdClose',
|
||||
@ -181,12 +182,12 @@ class Fenom {
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagInclude'
|
||||
),
|
||||
'var' => array( // {var ...}
|
||||
'var' => array( // {var ...}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::varOpen',
|
||||
'close' => 'Fenom\Compiler::varClose'
|
||||
),
|
||||
'block' => array( // {block ...} {parent} {/block}
|
||||
'block' => array( // {block ...} {parent} {/block}
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => 'Fenom\Compiler::tagBlockOpen',
|
||||
'close' => 'Fenom\Compiler::tagBlockClose',
|
||||
@ -226,7 +227,7 @@ class Fenom {
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagCycle'
|
||||
),
|
||||
'raw' => array(
|
||||
'raw' => array(
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => 'Fenom\Compiler::tagRaw'
|
||||
),
|
||||
@ -250,10 +251,11 @@ class Fenom {
|
||||
* @throws InvalidArgumentException
|
||||
* @return Fenom
|
||||
*/
|
||||
public static function factory($source, $compile_dir = '/tmp', $options = 0) {
|
||||
if(is_string($source)) {
|
||||
public static function factory($source, $compile_dir = '/tmp', $options = 0)
|
||||
{
|
||||
if (is_string($source)) {
|
||||
$provider = new Fenom\Provider($source);
|
||||
} elseif($source instanceof ProviderInterface) {
|
||||
} elseif ($source instanceof ProviderInterface) {
|
||||
$provider = $source;
|
||||
} else {
|
||||
throw new InvalidArgumentException("Source must be a valid path or provider object");
|
||||
@ -261,7 +263,7 @@ class Fenom {
|
||||
$fenom = new static($provider);
|
||||
/* @var Fenom $fenom */
|
||||
$fenom->setCompileDir($compile_dir);
|
||||
if($options) {
|
||||
if ($options) {
|
||||
$fenom->setOptions($options);
|
||||
}
|
||||
return $fenom;
|
||||
@ -270,7 +272,8 @@ class Fenom {
|
||||
/**
|
||||
* @param Fenom\ProviderInterface $provider
|
||||
*/
|
||||
public function __construct(Fenom\ProviderInterface $provider) {
|
||||
public function __construct(Fenom\ProviderInterface $provider)
|
||||
{
|
||||
$this->_provider = $provider;
|
||||
}
|
||||
|
||||
@ -280,7 +283,8 @@ class Fenom {
|
||||
* @param string $dir directory to store compiled templates in
|
||||
* @return Fenom
|
||||
*/
|
||||
public function setCompileDir($dir) {
|
||||
public function setCompileDir($dir)
|
||||
{
|
||||
$this->_compile_dir = $dir;
|
||||
return $this;
|
||||
}
|
||||
@ -289,7 +293,8 @@ class Fenom {
|
||||
*
|
||||
* @param callable $cb
|
||||
*/
|
||||
public function addPreCompileFilter($cb) {
|
||||
public function addPreCompileFilter($cb)
|
||||
{
|
||||
$this->_on_pre_cmp[] = $cb;
|
||||
}
|
||||
|
||||
@ -297,14 +302,16 @@ class Fenom {
|
||||
*
|
||||
* @param callable $cb
|
||||
*/
|
||||
public function addPostCompileFilter($cb) {
|
||||
public function addPostCompileFilter($cb)
|
||||
{
|
||||
$this->_on_post_cmp[] = $cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $cb
|
||||
*/
|
||||
public function addCompileFilter($cb) {
|
||||
public function addCompileFilter($cb)
|
||||
{
|
||||
$this->_on_cmp[] = $cb;
|
||||
}
|
||||
|
||||
@ -315,7 +322,8 @@ class Fenom {
|
||||
* @param string $callback the modifier callback
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addModifier($modifier, $callback) {
|
||||
public function addModifier($modifier, $callback)
|
||||
{
|
||||
$this->_modifiers[$modifier] = $callback;
|
||||
return $this;
|
||||
}
|
||||
@ -327,7 +335,8 @@ class Fenom {
|
||||
* @param callable $parser
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addCompiler($compiler, $parser) {
|
||||
public function addCompiler($compiler, $parser)
|
||||
{
|
||||
$this->_actions[$compiler] = array(
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => $parser
|
||||
@ -340,11 +349,12 @@ class Fenom {
|
||||
* @param string|object $storage
|
||||
* @return $this
|
||||
*/
|
||||
public function addCompilerSmart($compiler, $storage) {
|
||||
if(method_exists($storage, "tag".$compiler)) {
|
||||
public function addCompilerSmart($compiler, $storage)
|
||||
{
|
||||
if (method_exists($storage, "tag" . $compiler)) {
|
||||
$this->_actions[$compiler] = array(
|
||||
'type' => self::INLINE_COMPILER,
|
||||
'parser' => array($storage, "tag".$compiler)
|
||||
'parser' => array($storage, "tag" . $compiler)
|
||||
);
|
||||
}
|
||||
return $this;
|
||||
@ -359,11 +369,12 @@ class Fenom {
|
||||
* @param array $tags
|
||||
* @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(
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
'open' => $open_parser,
|
||||
'close' => $close_parser ?: self::DEFAULT_CLOSE_COMPILER,
|
||||
'close' => $close_parser ? : self::DEFAULT_CLOSE_COMPILER,
|
||||
'tags' => $tags,
|
||||
);
|
||||
return $this;
|
||||
@ -377,27 +388,28 @@ class Fenom {
|
||||
* @throws LogicException
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array()) {
|
||||
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array())
|
||||
{
|
||||
$c = array(
|
||||
'type' => self::BLOCK_COMPILER,
|
||||
"tags" => array(),
|
||||
"float_tags" => array()
|
||||
);
|
||||
if(method_exists($storage, $compiler."Open")) {
|
||||
$c["open"] = $compiler."Open";
|
||||
if (method_exists($storage, $compiler . "Open")) {
|
||||
$c["open"] = $compiler . "Open";
|
||||
} else {
|
||||
throw new \LogicException("Open compiler {$compiler}Open not found");
|
||||
}
|
||||
if(method_exists($storage, $compiler."Close")) {
|
||||
$c["close"] = $compiler."Close";
|
||||
if (method_exists($storage, $compiler . "Close")) {
|
||||
$c["close"] = $compiler . "Close";
|
||||
} else {
|
||||
throw new \LogicException("Close compiler {$compiler}Close not found");
|
||||
}
|
||||
foreach($tags as $tag) {
|
||||
if(method_exists($storage, "tag".$tag)) {
|
||||
$c["tags"][ $tag ] = "tag".$tag;
|
||||
if($floats && in_array($tag, $floats)) {
|
||||
$c['float_tags'][ $tag ] = 1;
|
||||
foreach ($tags as $tag) {
|
||||
if (method_exists($storage, "tag" . $tag)) {
|
||||
$c["tags"][$tag] = "tag" . $tag;
|
||||
if ($floats && in_array($tag, $floats)) {
|
||||
$c['float_tags'][$tag] = 1;
|
||||
}
|
||||
} else {
|
||||
throw new \LogicException("Tag compiler $tag (tag{$compiler}) not found");
|
||||
@ -413,7 +425,8 @@ class Fenom {
|
||||
* @param callable|string $parser
|
||||
* @return 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(
|
||||
'type' => self::INLINE_FUNCTION,
|
||||
'parser' => $parser,
|
||||
@ -427,7 +440,8 @@ class Fenom {
|
||||
* @param callable $callback
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addFunctionSmart($function, $callback) {
|
||||
public function addFunctionSmart($function, $callback)
|
||||
{
|
||||
$this->_actions[$function] = array(
|
||||
'type' => self::INLINE_FUNCTION,
|
||||
'parser' => self::SMART_FUNC_PARSER,
|
||||
@ -443,12 +457,13 @@ class Fenom {
|
||||
* @param callable|string $parser_close
|
||||
* @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(
|
||||
'type' => self::BLOCK_FUNCTION,
|
||||
'open' => $parser_open,
|
||||
'close' => $parser_close,
|
||||
'function' => $callback,
|
||||
'type' => self::BLOCK_FUNCTION,
|
||||
'open' => $parser_open,
|
||||
'close' => $parser_close,
|
||||
'function' => $callback,
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
@ -457,7 +472,8 @@ class Fenom {
|
||||
* @param array $funcs
|
||||
* @return Fenom
|
||||
*/
|
||||
public function addAllowedFunctions(array $funcs) {
|
||||
public function addAllowedFunctions(array $funcs)
|
||||
{
|
||||
$this->_allowed_funcs = $this->_allowed_funcs + array_flip($funcs);
|
||||
return $this;
|
||||
}
|
||||
@ -469,10 +485,11 @@ class Fenom {
|
||||
* @param Fenom\Template $template
|
||||
* @return mixed
|
||||
*/
|
||||
public function getModifier($modifier, Template $template = null) {
|
||||
if(isset($this->_modifiers[$modifier])) {
|
||||
public function getModifier($modifier, Template $template = null)
|
||||
{
|
||||
if (isset($this->_modifiers[$modifier])) {
|
||||
return $this->_modifiers[$modifier];
|
||||
} elseif($this->isAllowedFunction($modifier)) {
|
||||
} elseif ($this->isAllowedFunction($modifier)) {
|
||||
return $modifier;
|
||||
} else {
|
||||
return $this->_loadModifier($modifier, $template);
|
||||
@ -484,7 +501,8 @@ class Fenom {
|
||||
* @param Fenom\Template $template
|
||||
* @return bool
|
||||
*/
|
||||
protected function _loadModifier($modifier, $template) {
|
||||
protected function _loadModifier($modifier, $template)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -494,7 +512,8 @@ class Fenom {
|
||||
* @return bool|string
|
||||
* @deprecated
|
||||
*/
|
||||
public function getFunction($function, Template $template = null) {
|
||||
public function getFunction($function, Template $template = null)
|
||||
{
|
||||
return $this->getTag($function, $template);
|
||||
}
|
||||
|
||||
@ -505,8 +524,9 @@ class Fenom {
|
||||
* @param Fenom\Template $template
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getTag($tag, Template $template = null) {
|
||||
if(isset($this->_actions[$tag])) {
|
||||
public function getTag($tag, Template $template = null)
|
||||
{
|
||||
if (isset($this->_actions[$tag])) {
|
||||
return $this->_actions[$tag];
|
||||
} else {
|
||||
return $this->_loadTag($tag, $template);
|
||||
@ -518,7 +538,8 @@ class Fenom {
|
||||
* @param Fenom\Template $template
|
||||
* @return bool
|
||||
*/
|
||||
protected function _loadTag($tag, $template) {
|
||||
protected function _loadTag($tag, $template)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -526,8 +547,9 @@ class Fenom {
|
||||
* @param string $function
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedFunction($function) {
|
||||
if($this->_options & self::DENY_NATIVE_FUNCS) {
|
||||
public function isAllowedFunction($function)
|
||||
{
|
||||
if ($this->_options & self::DENY_NATIVE_FUNCS) {
|
||||
return isset($this->_allowed_funcs[$function]);
|
||||
} else {
|
||||
return is_callable($function);
|
||||
@ -538,10 +560,11 @@ class Fenom {
|
||||
* @param string $tag
|
||||
* @return array
|
||||
*/
|
||||
public function getTagOwners($tag) {
|
||||
public function getTagOwners($tag)
|
||||
{
|
||||
$tags = array();
|
||||
foreach($this->_actions as $owner => $params) {
|
||||
if(isset($params["tags"][$tag])) {
|
||||
foreach ($this->_actions as $owner => $params) {
|
||||
if (isset($params["tags"][$tag])) {
|
||||
$tags[] = $owner;
|
||||
}
|
||||
}
|
||||
@ -554,7 +577,8 @@ class Fenom {
|
||||
* @param string $scm scheme name
|
||||
* @param Fenom\ProviderInterface $provider provider object
|
||||
*/
|
||||
public function addProvider($scm, \Fenom\ProviderInterface $provider) {
|
||||
public function addProvider($scm, \Fenom\ProviderInterface $provider)
|
||||
{
|
||||
$this->_providers[$scm] = $provider;
|
||||
}
|
||||
|
||||
@ -562,8 +586,9 @@ class Fenom {
|
||||
* Set options
|
||||
* @param int|array $options
|
||||
*/
|
||||
public function setOptions($options) {
|
||||
if(is_array($options)) {
|
||||
public function setOptions($options)
|
||||
{
|
||||
if (is_array($options)) {
|
||||
$options = self::_makeMask($options, self::$_options_list, $this->_options);
|
||||
}
|
||||
$this->_storage = array();
|
||||
@ -574,7 +599,8 @@ class Fenom {
|
||||
* Get options as bits
|
||||
* @return int
|
||||
*/
|
||||
public function getOptions() {
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->_options;
|
||||
}
|
||||
|
||||
@ -583,9 +609,10 @@ class Fenom {
|
||||
* @return Fenom\ProviderInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getProvider($scm = false) {
|
||||
if($scm) {
|
||||
if(isset($this->_providers[$scm])) {
|
||||
public function getProvider($scm = false)
|
||||
{
|
||||
if ($scm) {
|
||||
if (isset($this->_providers[$scm])) {
|
||||
return $this->_providers[$scm];
|
||||
} else {
|
||||
throw new InvalidArgumentException("Provider for '$scm' not found");
|
||||
@ -600,7 +627,8 @@ class Fenom {
|
||||
*
|
||||
* @return Fenom\Template
|
||||
*/
|
||||
public function getRawTemplate() {
|
||||
public function getRawTemplate()
|
||||
{
|
||||
return new Template($this, $this->_options);
|
||||
}
|
||||
|
||||
@ -611,7 +639,8 @@ class Fenom {
|
||||
* @param array $vars array of data for template
|
||||
* @return Fenom\Render
|
||||
*/
|
||||
public function display($template, array $vars = array()) {
|
||||
public function display($template, array $vars = array())
|
||||
{
|
||||
return $this->getTemplate($template)->display($vars);
|
||||
}
|
||||
|
||||
@ -621,7 +650,8 @@ class Fenom {
|
||||
* @param array $vars array of data for template
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetch($template, array $vars = array()) {
|
||||
public function fetch($template, array $vars = array())
|
||||
{
|
||||
return $this->getTemplate($template)->fetch($vars);
|
||||
}
|
||||
|
||||
@ -634,7 +664,8 @@ class Fenom {
|
||||
* @param float $chunk
|
||||
* @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);
|
||||
$data = $this->getTemplate($template)->display($vars);
|
||||
ob_end_flush();
|
||||
@ -648,21 +679,22 @@ class Fenom {
|
||||
* @param int $options additional options and flags
|
||||
* @return Fenom\Template
|
||||
*/
|
||||
public function getTemplate($template, $options = 0) {
|
||||
public function getTemplate($template, $options = 0)
|
||||
{
|
||||
$options |= $this->_options;
|
||||
$key = dechex($options)."@".$template;
|
||||
if(isset($this->_storage[ $key ])) {
|
||||
/** @var Fenom\Template $tpl */
|
||||
$tpl = $this->_storage[ $key ];
|
||||
if(($this->_options & self::AUTO_RELOAD) && !$tpl->isValid()) {
|
||||
return $this->_storage[ $key ] = $this->compile($template, true, $options);
|
||||
$key = dechex($options) . "@" . $template;
|
||||
if (isset($this->_storage[$key])) {
|
||||
/** @var Fenom\Template $tpl */
|
||||
$tpl = $this->_storage[$key];
|
||||
if (($this->_options & self::AUTO_RELOAD) && !$tpl->isValid()) {
|
||||
return $this->_storage[$key] = $this->compile($template, true, $options);
|
||||
} else {
|
||||
return $tpl;
|
||||
}
|
||||
} elseif($this->_options & self::FORCE_COMPILE) {
|
||||
} elseif ($this->_options & self::FORCE_COMPILE) {
|
||||
return $this->compile($template, $this->_options & self::DISABLE_CACHE & ~self::FORCE_COMPILE, $options);
|
||||
} else {
|
||||
return $this->_storage[ $key ] = $this->_load($template, $options);
|
||||
return $this->_storage[$key] = $this->_load($template, $options);
|
||||
}
|
||||
}
|
||||
|
||||
@ -671,9 +703,10 @@ class Fenom {
|
||||
* @param string $template
|
||||
* @return bool
|
||||
*/
|
||||
public function templateExists($template) {
|
||||
if($provider = strstr($template, ":", true)) {
|
||||
if(isset($this->_providers[$provider])) {
|
||||
public function templateExists($template)
|
||||
{
|
||||
if ($provider = strstr($template, ":", true)) {
|
||||
if (isset($this->_providers[$provider])) {
|
||||
return $this->_providers[$provider]->templateExists(substr($template, strlen($provider) + 1));
|
||||
}
|
||||
} else {
|
||||
@ -689,13 +722,14 @@ class Fenom {
|
||||
* @param int $opts
|
||||
* @return Fenom\Render
|
||||
*/
|
||||
protected function _load($tpl, $opts) {
|
||||
protected function _load($tpl, $opts)
|
||||
{
|
||||
$file_name = $this->_getCacheName($tpl, $opts);
|
||||
if(!is_file($this->_compile_dir."/".$file_name)) {
|
||||
if (!is_file($this->_compile_dir . "/" . $file_name)) {
|
||||
return $this->compile($tpl, true, $opts);
|
||||
} else {
|
||||
$fenom = $this;
|
||||
return include($this->_compile_dir."/".$file_name);
|
||||
return include($this->_compile_dir . "/" . $file_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,8 +740,9 @@ class Fenom {
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
private function _getCacheName($tpl, $options) {
|
||||
$hash = $tpl.":".$options;
|
||||
private function _getCacheName($tpl, $options)
|
||||
{
|
||||
$hash = $tpl . ":" . $options;
|
||||
return sprintf("%s.%x.%x.php", str_replace(":", "_", basename($tpl)), crc32($hash), strlen($hash));
|
||||
}
|
||||
|
||||
@ -720,20 +755,21 @@ class Fenom {
|
||||
* @throws RuntimeException
|
||||
* @return \Fenom\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true, $options = 0) {
|
||||
public function compile($tpl, $store = true, $options = 0)
|
||||
{
|
||||
$options = $this->_options | $options;
|
||||
$template = $this->getRawTemplate()->load($tpl);
|
||||
if($store) {
|
||||
if ($store) {
|
||||
$cache = $this->_getCacheName($tpl, $options);
|
||||
$tpl_tmp = tempnam($this->_compile_dir, $cache);
|
||||
$tpl_fp = fopen($tpl_tmp, "w");
|
||||
if(!$tpl_fp) {
|
||||
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory ".$this->_compile_dir." is writable?");
|
||||
if (!$tpl_fp) {
|
||||
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory " . $this->_compile_dir . " is writable?");
|
||||
}
|
||||
fwrite($tpl_fp, $template->getTemplateCode());
|
||||
fclose($tpl_fp);
|
||||
$file_name = $this->_compile_dir."/".$cache;
|
||||
if(!rename($tpl_tmp, $file_name)) {
|
||||
$file_name = $this->_compile_dir . "/" . $cache;
|
||||
if (!rename($tpl_tmp, $file_name)) {
|
||||
throw new \RuntimeException("Can't to move $tpl_tmp to $tpl");
|
||||
}
|
||||
}
|
||||
@ -743,14 +779,16 @@ class Fenom {
|
||||
/**
|
||||
* Flush internal memory template cache
|
||||
*/
|
||||
public function flush() {
|
||||
public function flush()
|
||||
{
|
||||
$this->_storage = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all compiled templates
|
||||
*/
|
||||
public function clearAllCompiles() {
|
||||
public function clearAllCompiles()
|
||||
{
|
||||
\Fenom\Provider::clean($this->_compile_dir);
|
||||
}
|
||||
|
||||
@ -761,7 +799,8 @@ class Fenom {
|
||||
* @param string $name
|
||||
* @return Fenom\Template
|
||||
*/
|
||||
public function compileCode($code, $name = 'Runtime compile') {
|
||||
public function compileCode($code, $name = 'Runtime compile')
|
||||
{
|
||||
return $this->getRawTemplate()->source($name, $code);
|
||||
}
|
||||
|
||||
@ -775,7 +814,8 @@ class Fenom {
|
||||
* @return int result, ( $mask | a ) & ~b
|
||||
* @throws \RuntimeException if key from custom assoc doesn't exists into possible values
|
||||
*/
|
||||
private static function _makeMask(array $values, array $options, $mask = 0) {
|
||||
private static function _makeMask(array $values, array $options, $mask = 0)
|
||||
{
|
||||
foreach ($values as $key => $value) {
|
||||
if (isset($options[$key])) {
|
||||
if ($options[$key]) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,8 @@ namespace Fenom;
|
||||
* Collection of modifiers
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
class Modifier {
|
||||
class Modifier
|
||||
{
|
||||
|
||||
/**
|
||||
* Date format
|
||||
@ -22,10 +23,11 @@ class Modifier {
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
public static function dateFormat($date, $format = "%b %e, %Y") {
|
||||
if(is_string($date) && !is_numeric($date)) {
|
||||
public static function dateFormat($date, $format = "%b %e, %Y")
|
||||
{
|
||||
if (is_string($date) && !is_numeric($date)) {
|
||||
$date = strtotime($date);
|
||||
if(!$date) $date = time();
|
||||
if (!$date) $date = time();
|
||||
}
|
||||
return strftime($format, $date);
|
||||
}
|
||||
@ -35,10 +37,11 @@ class Modifier {
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
public static function date($date, $format = "Y m d") {
|
||||
if(is_string($date) && !is_numeric($date)) {
|
||||
public static function date($date, $format = "Y m d")
|
||||
{
|
||||
if (is_string($date) && !is_numeric($date)) {
|
||||
$date = strtotime($date);
|
||||
if(!$date) $date = time();
|
||||
if (!$date) $date = time();
|
||||
}
|
||||
return date($format, $date);
|
||||
}
|
||||
@ -50,8 +53,9 @@ class Modifier {
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function escape($text, $type = 'html') {
|
||||
switch(strtolower($type)) {
|
||||
public static function escape($text, $type = 'html')
|
||||
{
|
||||
switch (strtolower($type)) {
|
||||
case "url":
|
||||
return urlencode($text);
|
||||
case "html";
|
||||
@ -68,8 +72,9 @@ class Modifier {
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function unescape($text, $type = 'html') {
|
||||
switch(strtolower($type)) {
|
||||
public static function unescape($text, $type = 'html')
|
||||
{
|
||||
switch (strtolower($type)) {
|
||||
case "url":
|
||||
return urldecode($text);
|
||||
case "html";
|
||||
@ -89,23 +94,24 @@ class Modifier {
|
||||
* @param bool $middle
|
||||
* @return string
|
||||
*/
|
||||
public static function truncate($string, $length = 80, $etc = '...', $by_words = false, $middle = false) {
|
||||
if($middle) {
|
||||
if(preg_match('#^(.{'.$length.'}).*?(.{'.$length.'})?$#usS', $string, $match)) {
|
||||
if(count($match) == 3) {
|
||||
if($by_words) {
|
||||
return preg_replace('#\s.*$#usS', "", $match[1]).$etc.preg_replace('#^.*\s#usS', "", $match[2]);
|
||||
public static function truncate($string, $length = 80, $etc = '...', $by_words = false, $middle = false)
|
||||
{
|
||||
if ($middle) {
|
||||
if (preg_match('#^(.{' . $length . '}).*?(.{' . $length . '})?$#usS', $string, $match)) {
|
||||
if (count($match) == 3) {
|
||||
if ($by_words) {
|
||||
return preg_replace('#\s.*$#usS', "", $match[1]) . $etc . preg_replace('#^.*\s#usS', "", $match[2]);
|
||||
} else {
|
||||
return $match[1].$etc.$match[2];
|
||||
return $match[1] . $etc . $match[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(preg_match('#^(.{'.$length.'})#usS', $string, $match)) {
|
||||
if($by_words) {
|
||||
return preg_replace('#\s.*$#usS', "", $match[1]).$etc;
|
||||
if (preg_match('#^(.{' . $length . '})#usS', $string, $match)) {
|
||||
if ($by_words) {
|
||||
return preg_replace('#\s.*$#usS', "", $match[1]) . $etc;
|
||||
} else {
|
||||
return $match[1].$etc;
|
||||
return $match[1] . $etc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,9 +125,10 @@ class Modifier {
|
||||
* @param bool $to_line strip line ends
|
||||
* @return string
|
||||
*/
|
||||
public static function strip($str, $to_line = false) {
|
||||
public static function strip($str, $to_line = false)
|
||||
{
|
||||
$str = trim($str);
|
||||
if($to_line) {
|
||||
if ($to_line) {
|
||||
return preg_replace('#[\s]+#ms', ' ', $str);
|
||||
} else {
|
||||
return preg_replace('#[ \t]{2,}#', ' ', $str);
|
||||
@ -133,12 +140,13 @@ class Modifier {
|
||||
* @param mixed $item
|
||||
* @return int
|
||||
*/
|
||||
public static function length($item) {
|
||||
if(is_string($item)) {
|
||||
public static function length($item)
|
||||
{
|
||||
if (is_string($item)) {
|
||||
return strlen(preg_replace('#[\x00-\x7F]|[\x80-\xDF][\x00-\xBF]|[\xE0-\xEF][\x00-\xBF]{2}#s', ' ', $item));
|
||||
} elseif (is_array($item)) {
|
||||
return count($item);
|
||||
} elseif($item instanceof \Countable) {
|
||||
} elseif ($item instanceof \Countable) {
|
||||
return count($item);
|
||||
} else {
|
||||
return 0;
|
||||
@ -151,10 +159,11 @@ class Modifier {
|
||||
* @param mixed $haystack
|
||||
* @return bool
|
||||
*/
|
||||
public static function in($value, $haystack) {
|
||||
if(is_array($haystack)) {
|
||||
public static function in($value, $haystack)
|
||||
{
|
||||
if (is_array($haystack)) {
|
||||
return in_array($value, $haystack) || array_key_exists($value, $haystack);
|
||||
} elseif(is_string($haystack)) {
|
||||
} elseif (is_string($haystack)) {
|
||||
return strpos($haystack, $value) !== false;
|
||||
}
|
||||
return false;
|
||||
@ -164,7 +173,8 @@ class Modifier {
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function isIterable($value) {
|
||||
public static function isIterable($value)
|
||||
{
|
||||
return is_array($value) || ($value instanceof \Iterator);
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,13 @@
|
||||
namespace Fenom;
|
||||
|
||||
use Fenom\ProviderInterface;
|
||||
|
||||
/**
|
||||
* Base template provider
|
||||
* @author Ivan Shalganov
|
||||
*/
|
||||
class Provider implements ProviderInterface {
|
||||
class Provider implements ProviderInterface
|
||||
{
|
||||
private $_path;
|
||||
|
||||
/**
|
||||
@ -22,10 +24,11 @@ class Provider implements ProviderInterface {
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public static function clean($path) {
|
||||
if(is_file($path)) {
|
||||
public static function clean($path)
|
||||
{
|
||||
if (is_file($path)) {
|
||||
unlink($path);
|
||||
} elseif(is_dir($path)) {
|
||||
} elseif (is_dir($path)) {
|
||||
$iterator = iterator_to_array(
|
||||
new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($path,
|
||||
@ -33,13 +36,13 @@ class Provider implements ProviderInterface {
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
)
|
||||
);
|
||||
foreach($iterator as $file) {
|
||||
/* @var \splFileInfo $file*/
|
||||
if($file->isFile()) {
|
||||
if(strpos($file->getBasename(), ".") !== 0) {
|
||||
foreach ($iterator as $file) {
|
||||
/* @var \splFileInfo $file */
|
||||
if ($file->isFile()) {
|
||||
if (strpos($file->getBasename(), ".") !== 0) {
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
} elseif($file->isDir()) {
|
||||
} elseif ($file->isDir()) {
|
||||
rmdir($file->getRealPath());
|
||||
}
|
||||
}
|
||||
@ -51,9 +54,10 @@ class Provider implements ProviderInterface {
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public static function rm($path) {
|
||||
public static function rm($path)
|
||||
{
|
||||
self::clean($path);
|
||||
if(is_dir($path)) {
|
||||
if (is_dir($path)) {
|
||||
rmdir($path);
|
||||
}
|
||||
}
|
||||
@ -62,8 +66,9 @@ class Provider implements ProviderInterface {
|
||||
* @param string $template_dir directory of templates
|
||||
* @throws \LogicException if directory doesn't exists
|
||||
*/
|
||||
public function __construct($template_dir) {
|
||||
if($_dir = realpath($template_dir)) {
|
||||
public function __construct($template_dir)
|
||||
{
|
||||
if ($_dir = realpath($template_dir)) {
|
||||
$this->_path = $_dir;
|
||||
} else {
|
||||
throw new \LogicException("Template directory {$template_dir} doesn't exists");
|
||||
@ -76,7 +81,8 @@ class Provider implements ProviderInterface {
|
||||
* @param int $time load last modified time
|
||||
* @return string
|
||||
*/
|
||||
public function getSource($tpl, &$time) {
|
||||
public function getSource($tpl, &$time)
|
||||
{
|
||||
$tpl = $this->_getTemplatePath($tpl);
|
||||
clearstatcache(null, $tpl);
|
||||
$time = filemtime($tpl);
|
||||
@ -88,7 +94,8 @@ class Provider implements ProviderInterface {
|
||||
* @param string $tpl
|
||||
* @return int
|
||||
*/
|
||||
public function getLastModified($tpl) {
|
||||
public function getLastModified($tpl)
|
||||
{
|
||||
clearstatcache(null, $tpl = $this->_getTemplatePath($tpl));
|
||||
return filemtime($tpl);
|
||||
}
|
||||
@ -99,7 +106,8 @@ class Provider implements ProviderInterface {
|
||||
* @param string $extension all templates must have this extension, default .tpl
|
||||
* @return array|\Iterator
|
||||
*/
|
||||
public function getList($extension = "tpl") {
|
||||
public function getList($extension = "tpl")
|
||||
{
|
||||
$list = array();
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($this->_path,
|
||||
@ -107,9 +115,9 @@ class Provider implements ProviderInterface {
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
$path_len = strlen($this->_path);
|
||||
foreach($iterator as $file) {
|
||||
foreach ($iterator as $file) {
|
||||
/* @var \SplFileInfo $file */
|
||||
if($file->isFile() && $file->getExtension() == $extension) {
|
||||
if ($file->isFile() && $file->getExtension() == $extension) {
|
||||
$list[] = substr($file->getPathname(), $path_len + 1);
|
||||
}
|
||||
}
|
||||
@ -122,8 +130,9 @@ class Provider implements ProviderInterface {
|
||||
* @return string
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function _getTemplatePath($tpl) {
|
||||
if(($path = realpath($this->_path."/".$tpl)) && strpos($path, $this->_path) === 0) {
|
||||
protected function _getTemplatePath($tpl)
|
||||
{
|
||||
if (($path = realpath($this->_path . "/" . $tpl)) && strpos($path, $this->_path) === 0) {
|
||||
return $path;
|
||||
} else {
|
||||
throw new \RuntimeException("Template $tpl not found");
|
||||
@ -134,8 +143,9 @@ class Provider implements ProviderInterface {
|
||||
* @param string $tpl
|
||||
* @return bool
|
||||
*/
|
||||
public function templateExists($tpl) {
|
||||
return file_exists($this->_path."/".$tpl);
|
||||
public function templateExists($tpl)
|
||||
{
|
||||
return file_exists($this->_path . "/" . $tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,10 +154,11 @@ class Provider implements ProviderInterface {
|
||||
* @param array $templates [template_name => modified, ...] By conversation, you may trust the template's name
|
||||
* @return bool
|
||||
*/
|
||||
public function verify(array $templates) {
|
||||
foreach($templates as $template => $mtime) {
|
||||
clearstatcache(null, $template = $this->_path.'/'.$template);
|
||||
if(@filemtime($template) !== $mtime) {
|
||||
public function verify(array $templates)
|
||||
{
|
||||
foreach ($templates as $template => $mtime) {
|
||||
clearstatcache(null, $template = $this->_path . '/' . $template);
|
||||
if (@filemtime($template) !== $mtime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,8 @@ namespace Fenom;
|
||||
* @package Fenom
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
interface ProviderInterface {
|
||||
interface ProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param string $tpl
|
||||
* @return bool
|
||||
|
@ -14,7 +14,8 @@ use Fenom;
|
||||
* Primitive template
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
class Render extends \ArrayObject {
|
||||
class Render extends \ArrayObject
|
||||
{
|
||||
private static $_props = array(
|
||||
"name" => "runtime",
|
||||
"base_name" => "",
|
||||
@ -72,7 +73,8 @@ class Render extends \ArrayObject {
|
||||
* @param callable $code template body
|
||||
* @param array $props
|
||||
*/
|
||||
public function __construct(Fenom $fenom, \Closure $code, array $props = array()) {
|
||||
public function __construct(Fenom $fenom, \Closure $code, array $props = array())
|
||||
{
|
||||
$this->_fenom = $fenom;
|
||||
$props += self::$_props;
|
||||
$this->_name = $props["name"];
|
||||
@ -86,7 +88,8 @@ class Render extends \ArrayObject {
|
||||
* Get template storage
|
||||
* @return \Fenom
|
||||
*/
|
||||
public function getStorage() {
|
||||
public function getStorage()
|
||||
{
|
||||
return $this->_fenom;
|
||||
}
|
||||
|
||||
@ -94,7 +97,8 @@ class Render extends \ArrayObject {
|
||||
* Get depends list
|
||||
* @return array
|
||||
*/
|
||||
public function getDepends() {
|
||||
public function getDepends()
|
||||
{
|
||||
return $this->_depends;
|
||||
}
|
||||
|
||||
@ -102,7 +106,8 @@ class Render extends \ArrayObject {
|
||||
* Get schema name
|
||||
* @return string
|
||||
*/
|
||||
public function getScm() {
|
||||
public function getScm()
|
||||
{
|
||||
return $this->_scm;
|
||||
}
|
||||
|
||||
@ -110,7 +115,8 @@ class Render extends \ArrayObject {
|
||||
* Get provider of template source
|
||||
* @return ProviderInterface
|
||||
*/
|
||||
public function getProvider() {
|
||||
public function getProvider()
|
||||
{
|
||||
return $this->_fenom->getProvider($this->_scm);
|
||||
}
|
||||
|
||||
@ -118,7 +124,8 @@ class Render extends \ArrayObject {
|
||||
* Get name without schema
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseName() {
|
||||
public function getBaseName()
|
||||
{
|
||||
return $this->_base_name;
|
||||
}
|
||||
|
||||
@ -126,14 +133,16 @@ class Render extends \ArrayObject {
|
||||
* Get parse options
|
||||
* @return int
|
||||
*/
|
||||
public function getOptions() {
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
@ -141,11 +150,13 @@ class Render extends \ArrayObject {
|
||||
* Get template name
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
public function getName()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
public function getTime() {
|
||||
public function getTime()
|
||||
{
|
||||
return $this->_time;
|
||||
}
|
||||
|
||||
@ -154,16 +165,17 @@ class Render extends \ArrayObject {
|
||||
* Validate template
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid() {
|
||||
if(count($this->_depends) === 1) { // if no external dependencies, only self
|
||||
public function isValid()
|
||||
{
|
||||
if (count($this->_depends) === 1) { // if no external dependencies, only self
|
||||
$provider = $this->_fenom->getProvider($this->_scm);
|
||||
if($provider->getLastModified($this->_name) !== $this->_time) {
|
||||
if ($provider->getLastModified($this->_name) !== $this->_time) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
foreach($this->_depends as $scm => $templates) {
|
||||
foreach ($this->_depends as $scm => $templates) {
|
||||
$provider = $this->_fenom->getProvider($scm);
|
||||
if(!$provider->verify($templates)) {
|
||||
if (!$provider->verify($templates)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -176,7 +188,8 @@ class Render extends \ArrayObject {
|
||||
* @param array $values for template
|
||||
* @return Render
|
||||
*/
|
||||
public function display(array $values) {
|
||||
public function display(array $values)
|
||||
{
|
||||
$this->exchangeArray($values);
|
||||
$this->_code->__invoke($this);
|
||||
return $this->exchangeArray(array());
|
||||
@ -188,7 +201,8 @@ class Render extends \ArrayObject {
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function fetch(array $values) {
|
||||
public function fetch(array $values)
|
||||
{
|
||||
ob_start();
|
||||
try {
|
||||
$this->display($values);
|
||||
@ -205,7 +219,8 @@ class Render extends \ArrayObject {
|
||||
* @param $args
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __call($method, $args) {
|
||||
throw new \BadMethodCallException("Unknown method ".$method);
|
||||
public function __call($method, $args)
|
||||
{
|
||||
throw new \BadMethodCallException("Unknown method " . $method);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ namespace Fenom;
|
||||
*
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
class Scope extends \ArrayObject {
|
||||
class Scope extends \ArrayObject
|
||||
{
|
||||
|
||||
public $line = 0;
|
||||
public $name;
|
||||
@ -33,20 +34,21 @@ class Scope extends \ArrayObject {
|
||||
/**
|
||||
* Creating cope
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $name
|
||||
* @param Template $tpl
|
||||
* @param int $line
|
||||
* @param array $action
|
||||
* @param int $level
|
||||
* @param int $line
|
||||
* @param array $action
|
||||
* @param int $level
|
||||
* @param $body
|
||||
*/
|
||||
public function __construct($name, $tpl, $line, $action, $level, &$body) {
|
||||
public function __construct($name, $tpl, $line, $action, $level, &$body)
|
||||
{
|
||||
$this->line = $line;
|
||||
$this->name = $name;
|
||||
$this->tpl = $tpl;
|
||||
$this->_action = $action;
|
||||
$this->level = $level;
|
||||
$this->_body = &$body;
|
||||
$this->_body = & $body;
|
||||
$this->_offset = strlen($body);
|
||||
}
|
||||
|
||||
@ -54,7 +56,8 @@ class Scope extends \ArrayObject {
|
||||
*
|
||||
* @param string $function
|
||||
*/
|
||||
public function setFuncName($function) {
|
||||
public function setFuncName($function)
|
||||
{
|
||||
$this["function"] = $function;
|
||||
$this->is_compiler = false;
|
||||
$this->escape = $this->tpl->escape;
|
||||
@ -66,7 +69,8 @@ class Scope extends \ArrayObject {
|
||||
* @param Tokenizer $tokenizer
|
||||
* @return mixed
|
||||
*/
|
||||
public function open($tokenizer) {
|
||||
public function open($tokenizer)
|
||||
{
|
||||
return call_user_func($this->_action["open"], $tokenizer, $this);
|
||||
}
|
||||
|
||||
@ -77,9 +81,10 @@ class Scope extends \ArrayObject {
|
||||
* @param int $level
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTag($tag, $level) {
|
||||
if(isset($this->_action["tags"][$tag])) {
|
||||
if($level) {
|
||||
public function hasTag($tag, $level)
|
||||
{
|
||||
if (isset($this->_action["tags"][$tag])) {
|
||||
if ($level) {
|
||||
return isset($this->_action["float_tags"][$tag]);
|
||||
} else {
|
||||
return true;
|
||||
@ -95,7 +100,8 @@ class Scope extends \ArrayObject {
|
||||
* @param Tokenizer $tokenizer
|
||||
* @return string
|
||||
*/
|
||||
public function tag($tag, $tokenizer) {
|
||||
public function tag($tag, $tokenizer)
|
||||
{
|
||||
return call_user_func($this->_action["tags"][$tag], $tokenizer, $this);
|
||||
}
|
||||
|
||||
@ -105,7 +111,8 @@ class Scope extends \ArrayObject {
|
||||
* @param Tokenizer $tokenizer
|
||||
* @return string
|
||||
*/
|
||||
public function close($tokenizer) {
|
||||
public function close($tokenizer)
|
||||
{
|
||||
return call_user_func($this->_action["close"], $tokenizer, $this);
|
||||
}
|
||||
|
||||
@ -115,7 +122,8 @@ class Scope extends \ArrayObject {
|
||||
* @throws \LogicException
|
||||
* @return string
|
||||
*/
|
||||
public function getContent() {
|
||||
public function getContent()
|
||||
{
|
||||
return substr($this->_body, $this->_offset);
|
||||
}
|
||||
|
||||
@ -125,7 +133,8 @@ class Scope extends \ArrayObject {
|
||||
* @return string
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function cutContent() {
|
||||
public function cutContent()
|
||||
{
|
||||
$content = substr($this->_body, $this->_offset + 1);
|
||||
$this->_body = substr($this->_body, 0, $this->_offset);
|
||||
return $content;
|
||||
@ -136,12 +145,14 @@ class Scope extends \ArrayObject {
|
||||
*
|
||||
* @param $new_content
|
||||
*/
|
||||
public function replaceContent($new_content) {
|
||||
public function replaceContent($new_content)
|
||||
{
|
||||
$this->cutContent();
|
||||
$this->_body .= $new_content;
|
||||
}
|
||||
|
||||
public function unEscapeContent() {
|
||||
public function unEscapeContent()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -12,13 +12,13 @@ namespace Fenom;
|
||||
/**
|
||||
* for <PHP 5.4 compatible
|
||||
*/
|
||||
defined('T_INSTEADOF') || define('T_INSTEADOF', 341);
|
||||
defined('T_TRAIT') || define('T_TRAIT', 355);
|
||||
defined('T_TRAIT_C') || define('T_TRAIT_C', 365);
|
||||
defined('T_INSTEADOF') || define('T_INSTEADOF', 341);
|
||||
defined('T_TRAIT') || define('T_TRAIT', 355);
|
||||
defined('T_TRAIT_C') || define('T_TRAIT_C', 365);
|
||||
/**
|
||||
* for PHP <5.5
|
||||
*/
|
||||
defined('T_YIELD') || define('T_YIELD', 370);
|
||||
defined('T_YIELD') || define('T_YIELD', 370);
|
||||
|
||||
/**
|
||||
* Each token have structure
|
||||
@ -35,7 +35,8 @@ defined('T_YIELD') || define('T_YIELD', 370);
|
||||
* @package Fenom
|
||||
* @author Ivan Shalganov <a.cobest@gmail.com>
|
||||
*/
|
||||
class Tokenizer {
|
||||
class Tokenizer
|
||||
{
|
||||
const TOKEN = 0;
|
||||
const TEXT = 1;
|
||||
const WHITESPACE = 2;
|
||||
@ -90,19 +91,19 @@ class Tokenizer {
|
||||
*/
|
||||
private static $_macros = array(
|
||||
self::MACRO_STRING => array(
|
||||
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1, \T_BREAK => 1, \T_CASE => 1,
|
||||
\T_CATCH => 1, \T_CLASS => 1, \T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 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_VAR => 1,
|
||||
\T_WHILE => 1, \T_YIELD => 1, \T_USE => 1
|
||||
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1, \T_BREAK => 1, \T_CASE => 1,
|
||||
\T_CATCH => 1, \T_CLASS => 1, \T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 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_VAR => 1,
|
||||
\T_WHILE => 1, \T_YIELD => 1, \T_USE => 1
|
||||
),
|
||||
self::MACRO_INCDEC => array(
|
||||
\T_INC => 1, \T_DEC => 1
|
||||
@ -111,41 +112,41 @@ class Tokenizer {
|
||||
"!" => 1, "~" => 1, "-" => 1
|
||||
),
|
||||
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_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,
|
||||
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_IS_GREATER_OR_EQUAL => 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(
|
||||
\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(
|
||||
"+" => 1, "-" => 1, "*" => 1, "/" => 1, "^" => 1, "%" => 1, "&" => 1, "|" => 1
|
||||
),
|
||||
self::MACRO_COND => array(
|
||||
\T_IS_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,
|
||||
\T_IS_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(
|
||||
\T_AND_EQUAL => 1, \T_CONCAT_EQUAL => 1,\T_DIV_EQUAL => 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_AND_EQUAL => 1, \T_CONCAT_EQUAL => 1, \T_DIV_EQUAL => 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
|
||||
),
|
||||
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(
|
||||
self::MACRO_STRING => 'string',
|
||||
self::MACRO_INCDEC => 'increment/decrement operator',
|
||||
self::MACRO_UNARY => 'unary operator',
|
||||
self::MACRO_BINARY => 'binary operator',
|
||||
self::MACRO_STRING => 'string',
|
||||
self::MACRO_INCDEC => 'increment/decrement operator',
|
||||
self::MACRO_UNARY => 'unary operator',
|
||||
self::MACRO_BINARY => 'binary operator',
|
||||
self::MACRO_BOOLEAN => 'boolean operator',
|
||||
self::MACRO_MATH => 'math operator',
|
||||
self::MACRO_COND => 'conditional operator',
|
||||
self::MACRO_EQUALS => 'equal operator',
|
||||
self::MACRO_SCALAR => 'scalar value'
|
||||
self::MACRO_MATH => 'math operator',
|
||||
self::MACRO_COND => 'conditional operator',
|
||||
self::MACRO_EQUALS => 'equal operator',
|
||||
self::MACRO_SCALAR => 'scalar value'
|
||||
);
|
||||
|
||||
/**
|
||||
@ -159,15 +160,16 @@ class Tokenizer {
|
||||
/**
|
||||
* @param $query
|
||||
*/
|
||||
public function __construct($query) {
|
||||
public function __construct($query)
|
||||
{
|
||||
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
|
||||
$_tokens = token_get_all("<?php ".$query);
|
||||
$_tokens = token_get_all("<?php " . $query);
|
||||
$line = 1;
|
||||
array_shift($_tokens);
|
||||
$i = 0;
|
||||
foreach($_tokens as $token) {
|
||||
if(is_string($token)) {
|
||||
if($token === '"' || $token === "'" || $token === "`") {
|
||||
foreach ($_tokens as $token) {
|
||||
if (is_string($token)) {
|
||||
if ($token === '"' || $token === "'" || $token === "`") {
|
||||
$this->quotes++;
|
||||
}
|
||||
$tokens[] = array(
|
||||
@ -178,13 +180,13 @@ class Tokenizer {
|
||||
);
|
||||
$i++;
|
||||
} elseif ($token[0] === \T_WHITESPACE) {
|
||||
$tokens[$i-1][2] = $token[1];
|
||||
$tokens[$i - 1][2] = $token[1];
|
||||
} else {
|
||||
$tokens[] = array(
|
||||
$token[0],
|
||||
$token[1],
|
||||
"",
|
||||
$line = $token[2],
|
||||
$line = $token[2],
|
||||
token_name($token[0]) // debug
|
||||
);
|
||||
$i++;
|
||||
@ -202,7 +204,8 @@ class Tokenizer {
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function isIncomplete() {
|
||||
public function isIncomplete()
|
||||
{
|
||||
return ($this->quotes % 2) || ($this->tokens[$this->_max][0] === T_ENCAPSED_AND_WHITESPACE);
|
||||
}
|
||||
|
||||
@ -212,7 +215,8 @@ class Tokenizer {
|
||||
* @link http://php.net/manual/en/iterator.current.php
|
||||
* @return mixed Can return any type.
|
||||
*/
|
||||
public function current() {
|
||||
public function current()
|
||||
{
|
||||
return $this->curr[1];
|
||||
}
|
||||
|
||||
@ -222,8 +226,9 @@ class Tokenizer {
|
||||
* @link http://php.net/manual/en/iterator.next.php
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function next() {
|
||||
if($this->p > $this->_max) {
|
||||
public function next()
|
||||
{
|
||||
if ($this->p > $this->_max) {
|
||||
return $this;
|
||||
}
|
||||
$this->p++;
|
||||
@ -238,15 +243,16 @@ class Tokenizer {
|
||||
* @param string|int $token
|
||||
* @return bool
|
||||
*/
|
||||
private function _valid($expects, $token) {
|
||||
foreach($expects as $expect) {
|
||||
if(is_string($expect) || $expect < 1000) {
|
||||
if($expect === $token) {
|
||||
private function _valid($expects, $token)
|
||||
{
|
||||
foreach ($expects as $expect) {
|
||||
if (is_string($expect) || $expect < 1000) {
|
||||
if ($expect === $token) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
if(isset(self::$_macros[ $expect ][ $token ])) {
|
||||
if (isset(self::$_macros[$expect][$token])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -260,13 +266,14 @@ class Tokenizer {
|
||||
* @throws UnexpectedTokenException
|
||||
* @return mixed
|
||||
*/
|
||||
public function _next($tokens) {
|
||||
public function _next($tokens)
|
||||
{
|
||||
$this->next();
|
||||
if(!$this->curr) {
|
||||
if (!$this->curr) {
|
||||
throw new UnexpectedTokenException($this, $tokens);
|
||||
}
|
||||
if($tokens) {
|
||||
if($this->_valid($tokens, $this->key())) {
|
||||
if ($tokens) {
|
||||
if ($this->_valid($tokens, $this->key())) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -279,7 +286,8 @@ class Tokenizer {
|
||||
* Fetch next specified token or throw an exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function getNext(/*int|string $token1, int|string $token2, ... */) {
|
||||
public function getNext( /*int|string $token1, int|string $token2, ... */)
|
||||
{
|
||||
$this->_next(func_get_args());
|
||||
return $this->current();
|
||||
}
|
||||
@ -288,7 +296,8 @@ class Tokenizer {
|
||||
* @param $token
|
||||
* @return bool
|
||||
*/
|
||||
public function isNextToken($token) {
|
||||
public function isNextToken($token)
|
||||
{
|
||||
return $this->next ? $this->next[1] == $token : false;
|
||||
}
|
||||
|
||||
@ -298,15 +307,16 @@ class Tokenizer {
|
||||
* @param int $limit
|
||||
* @return string
|
||||
*/
|
||||
public function getSubstr($offset, $limit = 0) {
|
||||
public function getSubstr($offset, $limit = 0)
|
||||
{
|
||||
$str = '';
|
||||
if(!$limit) {
|
||||
if (!$limit) {
|
||||
$limit = $this->_max;
|
||||
} else {
|
||||
$limit += $offset;
|
||||
}
|
||||
for($i = $offset; $i <= $limit; $i++){
|
||||
$str .= $this->tokens[$i][1].$this->tokens[$i][2];
|
||||
for ($i = $offset; $i <= $limit; $i++) {
|
||||
$str .= $this->tokens[$i][1] . $this->tokens[$i][2];
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
@ -316,8 +326,9 @@ class Tokenizer {
|
||||
* @return mixed
|
||||
* @throws UnexpectedTokenException
|
||||
*/
|
||||
public function getAndNext() {
|
||||
if($this->curr) {
|
||||
public function getAndNext()
|
||||
{
|
||||
if ($this->curr) {
|
||||
$cur = $this->curr[1];
|
||||
$this->next();
|
||||
return $cur;
|
||||
@ -331,7 +342,8 @@ class Tokenizer {
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function isNext($token1/*, ...*/) {
|
||||
public function isNext($token1 /*, ...*/)
|
||||
{
|
||||
return $this->next && $this->_valid(func_get_args(), $this->next[0]);
|
||||
}
|
||||
|
||||
@ -340,7 +352,8 @@ class Tokenizer {
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function is($token1/*, ...*/) {
|
||||
public function is($token1 /*, ...*/)
|
||||
{
|
||||
return $this->curr && $this->_valid(func_get_args(), $this->curr[0]);
|
||||
}
|
||||
|
||||
@ -349,7 +362,8 @@ class Tokenizer {
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function isPrev($token1/*, ...*/) {
|
||||
public function isPrev($token1 /*, ...*/)
|
||||
{
|
||||
return $this->prev && $this->_valid(func_get_args(), $this->prev[0]);
|
||||
}
|
||||
|
||||
@ -360,8 +374,9 @@ class Tokenizer {
|
||||
* @throws UnexpectedTokenException
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($token1 /*, $token2 ...*/) {
|
||||
if($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
|
||||
public function get($token1 /*, $token2 ...*/)
|
||||
{
|
||||
if ($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
|
||||
return $this->curr[1];
|
||||
} else {
|
||||
throw new UnexpectedTokenException($this, func_get_args());
|
||||
@ -372,8 +387,9 @@ class Tokenizer {
|
||||
* Step back
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function back() {
|
||||
if($this->p === 0) {
|
||||
public function back()
|
||||
{
|
||||
if ($this->p === 0) {
|
||||
return $this;
|
||||
}
|
||||
$this->p--;
|
||||
@ -385,12 +401,13 @@ class Tokenizer {
|
||||
* @param $token1
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBackList($token1 /*, $token2 ...*/) {
|
||||
public function hasBackList($token1 /*, $token2 ...*/)
|
||||
{
|
||||
$tokens = func_get_args();
|
||||
$c = $this->p;
|
||||
foreach($tokens as $token) {
|
||||
foreach ($tokens as $token) {
|
||||
$c--;
|
||||
if($c < 0 || $this->tokens[$c][0] !== $token) {
|
||||
if ($c < 0 || $this->tokens[$c][0] !== $token) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -403,8 +420,9 @@ class Tokenizer {
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key) {
|
||||
switch($key) {
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'curr':
|
||||
return $this->curr = ($this->p <= $this->_max) ? $this->tokens[$this->p] : null;
|
||||
case 'next':
|
||||
@ -416,7 +434,8 @@ class Tokenizer {
|
||||
}
|
||||
}
|
||||
|
||||
public function count() {
|
||||
public function count()
|
||||
{
|
||||
return $this->_max;
|
||||
}
|
||||
|
||||
@ -424,7 +443,8 @@ class Tokenizer {
|
||||
* Return the key of the current element
|
||||
* @return mixed scalar on success, or null on failure.
|
||||
*/
|
||||
public function key() {
|
||||
public function key()
|
||||
{
|
||||
return $this->curr ? $this->curr[0] : null;
|
||||
}
|
||||
|
||||
@ -433,7 +453,8 @@ class Tokenizer {
|
||||
* @return boolean The return value will be casted to boolean and then evaluated.
|
||||
* Returns true on success or false on failure.
|
||||
*/
|
||||
public function valid() {
|
||||
public function valid()
|
||||
{
|
||||
return (bool)$this->curr;
|
||||
}
|
||||
|
||||
@ -443,12 +464,13 @@ class Tokenizer {
|
||||
* @param int|string $token
|
||||
* @return string
|
||||
*/
|
||||
public static function getName($token) {
|
||||
if(is_string($token)) {
|
||||
public static function getName($token)
|
||||
{
|
||||
if (is_string($token)) {
|
||||
return $token;
|
||||
} elseif(is_integer($token)) {
|
||||
} elseif (is_integer($token)) {
|
||||
return token_name($token);
|
||||
} elseif(is_array($token)) {
|
||||
} elseif (is_array($token)) {
|
||||
return token_name($token[0]);
|
||||
} else {
|
||||
return null;
|
||||
@ -461,9 +483,10 @@ class Tokenizer {
|
||||
* @throws UnexpectedTokenException
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function skip(/*$token1, $token2, ...*/) {
|
||||
if(func_num_args()) {
|
||||
if($this->_valid(func_get_args(), $this->curr[0])) {
|
||||
public function skip( /*$token1, $token2, ...*/)
|
||||
{
|
||||
if (func_num_args()) {
|
||||
if ($this->_valid(func_get_args(), $this->curr[0])) {
|
||||
$this->next();
|
||||
return $this;
|
||||
} else {
|
||||
@ -481,8 +504,9 @@ class Tokenizer {
|
||||
* @param int|string $token1
|
||||
* @return Tokenizer
|
||||
*/
|
||||
public function skipIf($token1/*, $token2, ...*/) {
|
||||
if($this->_valid(func_get_args(), $this->curr[0])) {
|
||||
public function skipIf($token1 /*, $token2, ...*/)
|
||||
{
|
||||
if ($this->_valid(func_get_args(), $this->curr[0])) {
|
||||
$this->next();
|
||||
}
|
||||
return $this;
|
||||
@ -495,8 +519,9 @@ class Tokenizer {
|
||||
* @return Tokenizer
|
||||
* @throws UnexpectedTokenException
|
||||
*/
|
||||
public function need($token1/*, $token2, ...*/) {
|
||||
if($this->_valid(func_get_args(), $this->curr[0])) {
|
||||
public function need($token1 /*, $token2, ...*/)
|
||||
{
|
||||
if ($this->_valid(func_get_args(), $this->curr[0])) {
|
||||
return $this;
|
||||
} else {
|
||||
throw new UnexpectedTokenException($this, func_get_args());
|
||||
@ -509,37 +534,38 @@ class Tokenizer {
|
||||
* @param int $after count tokens after current token
|
||||
* @return array
|
||||
*/
|
||||
public function getSnippet($before = 0, $after = 0) {
|
||||
public function getSnippet($before = 0, $after = 0)
|
||||
{
|
||||
$from = 0;
|
||||
$to = $this->p;
|
||||
if($before > 0) {
|
||||
if($before > $this->p) {
|
||||
if ($before > 0) {
|
||||
if ($before > $this->p) {
|
||||
$from = $this->p;
|
||||
} else {
|
||||
$from = $before;
|
||||
}
|
||||
} elseif($before < 0) {
|
||||
} elseif ($before < 0) {
|
||||
$from = $this->p + $before;
|
||||
if($from < 0) {
|
||||
if ($from < 0) {
|
||||
$from = 0;
|
||||
}
|
||||
}
|
||||
if($after > 0) {
|
||||
if ($after > 0) {
|
||||
$to = $this->p + $after;
|
||||
if($to > $this->_max) {
|
||||
if ($to > $this->_max) {
|
||||
$to = $this->_max;
|
||||
}
|
||||
} elseif($after < 0) {
|
||||
} elseif ($after < 0) {
|
||||
$to = $this->_max + $after;
|
||||
if($to < $this->p) {
|
||||
if ($to < $this->p) {
|
||||
$to = $this->p;
|
||||
}
|
||||
} elseif($this->p > $this->_max) {
|
||||
} elseif ($this->p > $this->_max) {
|
||||
$to = $this->_max;
|
||||
}
|
||||
$code = array();
|
||||
for($i=$from; $i<=$to; $i++) {
|
||||
$code[] = $this->tokens[ $i ];
|
||||
for ($i = $from; $i <= $to; $i++) {
|
||||
$code[] = $this->tokens[$i];
|
||||
}
|
||||
|
||||
return $code;
|
||||
@ -551,10 +577,11 @@ class Tokenizer {
|
||||
* @param int $after
|
||||
* @return string
|
||||
*/
|
||||
public function getSnippetAsString($before = 0, $after = 0) {
|
||||
public function getSnippetAsString($before = 0, $after = 0)
|
||||
{
|
||||
$str = "";
|
||||
foreach($this->getSnippet($before, $after) as $token) {
|
||||
$str .= $token[1].$token[2];
|
||||
foreach ($this->getSnippet($before, $after) as $token) {
|
||||
$str .= $token[1] . $token[2];
|
||||
}
|
||||
return trim(str_replace("\n", '↵', $str));
|
||||
}
|
||||
@ -563,7 +590,8 @@ class Tokenizer {
|
||||
* Check if current is special value: true, TRUE, false, FALSE, null, NULL
|
||||
* @return bool
|
||||
*/
|
||||
public function isSpecialVal() {
|
||||
public function isSpecialVal()
|
||||
{
|
||||
return isset(self::$spec[$this->current()]);
|
||||
}
|
||||
|
||||
@ -571,14 +599,16 @@ class Tokenizer {
|
||||
* Check if the token is last
|
||||
* @return bool
|
||||
*/
|
||||
public function isLast() {
|
||||
public function isLast()
|
||||
{
|
||||
return $this->p === $this->_max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move pointer to the end
|
||||
*/
|
||||
public function end() {
|
||||
public function end()
|
||||
{
|
||||
$this->p = $this->_max;
|
||||
}
|
||||
|
||||
@ -586,7 +616,8 @@ class Tokenizer {
|
||||
* Return line number of the current token
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLine() {
|
||||
public function getLine()
|
||||
{
|
||||
return $this->curr ? $this->curr[3] : $this->_last_no;
|
||||
}
|
||||
|
||||
@ -594,33 +625,13 @@ class Tokenizer {
|
||||
* Is current token whitespaced, means previous token has whitespace characters
|
||||
* @return bool
|
||||
*/
|
||||
public function isWhiteSpaced() {
|
||||
public function isWhiteSpaced()
|
||||
{
|
||||
return $this->prev ? (bool)$this->prev[2] : false;
|
||||
}
|
||||
|
||||
public function getWhitespace() {
|
||||
public function getWhitespace()
|
||||
{
|
||||
return $this->curr ? $this->curr[2] : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unexpected token
|
||||
*/
|
||||
class UnexpectedTokenException extends \RuntimeException {
|
||||
public function __construct(Tokenizer $tokens, $expect = null, $where = null) {
|
||||
if($expect && count($expect) == 1 && is_string($expect[0])) {
|
||||
$expect = ", expect '".$expect[0]."'";
|
||||
} else {
|
||||
$expect = "";
|
||||
}
|
||||
if(!$tokens->curr) {
|
||||
$this->message = "Unexpected end of ".($where?:"expression")."$expect";
|
||||
} elseif($tokens->curr[0] === T_WHITESPACE) {
|
||||
$this->message = "Unexpected whitespace$expect";
|
||||
} elseif($tokens->curr[0] === T_BAD_CHARACTER) {
|
||||
$this->message = "Unexpected bad characters (below ASCII 32 except \\t, \\n and \\r) in ".($where?:"expression")."$expect";
|
||||
} else {
|
||||
$this->message = "Unexpected token '".$tokens->current()."' in ".($where?:"expression")."$expect";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
29
src/Fenom/UnexpectedTokenException.php
Normal file
29
src/Fenom/UnexpectedTokenException.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
/**
|
||||
* Unexpected token
|
||||
*/
|
||||
class UnexpectedTokenException extends \RuntimeException
|
||||
{
|
||||
public function __construct(Tokenizer $tokens, $expect = null, $where = null)
|
||||
{
|
||||
if ($expect && count($expect) == 1 && is_string($expect[0])) {
|
||||
$expect = ", expect '" . $expect[0] . "'";
|
||||
} else {
|
||||
$expect = "";
|
||||
}
|
||||
if (!$tokens->curr) {
|
||||
$this->message = "Unexpected end of " . ($where ? : "expression") . "$expect";
|
||||
} elseif ($tokens->curr[0] === T_WHITESPACE) {
|
||||
$this->message = "Unexpected whitespace$expect";
|
||||
} elseif ($tokens->curr[0] === T_BAD_CHARACTER) {
|
||||
$this->message = "Unexpected bad characters (below ASCII 32 except \\t, \\n and \\r) in " . ($where ? : "expression") . "$expect";
|
||||
} else {
|
||||
$this->message = "Unexpected token '" . $tokens->current() . "' in " . ($where ? : "expression") . "$expect";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
;
|
@ -2,7 +2,8 @@
|
||||
namespace Fenom;
|
||||
use Fenom, Fenom\Provider as FS;
|
||||
|
||||
class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
class TestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var Fenom
|
||||
*/
|
||||
@ -10,26 +11,27 @@ class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public $values = array(
|
||||
"zero" => 0,
|
||||
"one" => 1,
|
||||
"one" => 1,
|
||||
"two" => 2,
|
||||
"three" => 3,
|
||||
"float" => 4.5,
|
||||
"bool" => true,
|
||||
"bool" => true,
|
||||
0 => "empty value",
|
||||
1 => "one value",
|
||||
2 => "two value",
|
||||
3 => "three value",
|
||||
);
|
||||
|
||||
public static function getVars() {
|
||||
public static function getVars()
|
||||
{
|
||||
return array(
|
||||
"zero" => 0,
|
||||
"one" => 1,
|
||||
"one" => 1,
|
||||
"two" => 2,
|
||||
"three" => 3,
|
||||
"float" => 4.5,
|
||||
"bool" => true,
|
||||
"obj" => new \StdClass,
|
||||
"bool" => true,
|
||||
"obj" => new \StdClass,
|
||||
"list" => array(
|
||||
"a" => 1,
|
||||
"b" => 2
|
||||
@ -41,50 +43,57 @@ class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
if(!file_exists(FENOM_RESOURCES.'/compile')) {
|
||||
mkdir(FENOM_RESOURCES.'/compile', 0777, true);
|
||||
public function setUp()
|
||||
{
|
||||
if (!file_exists(FENOM_RESOURCES . '/compile')) {
|
||||
mkdir(FENOM_RESOURCES . '/compile', 0777, true);
|
||||
} else {
|
||||
FS::clean(FENOM_RESOURCES.'/compile/');
|
||||
FS::clean(FENOM_RESOURCES . '/compile/');
|
||||
}
|
||||
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES.'/template', FENOM_RESOURCES.'/compile');
|
||||
$this->fenom->addModifier('dots', __CLASS__.'::dots');
|
||||
$this->fenom->addModifier('concat', __CLASS__.'::concat');
|
||||
$this->fenom->addFunction('test_function', __CLASS__.'::inlineFunction');
|
||||
$this->fenom->addBlockFunction('test_block_function', __CLASS__.'::blockFunction');
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile');
|
||||
$this->fenom->addModifier('dots', __CLASS__ . '::dots');
|
||||
$this->fenom->addModifier('concat', __CLASS__ . '::concat');
|
||||
$this->fenom->addFunction('test_function', __CLASS__ . '::inlineFunction');
|
||||
$this->fenom->addBlockFunction('test_block_function', __CLASS__ . '::blockFunction');
|
||||
}
|
||||
|
||||
public static function dots($value) {
|
||||
return $value."...";
|
||||
public static function dots($value)
|
||||
{
|
||||
return $value . "...";
|
||||
}
|
||||
|
||||
public static function concat() {
|
||||
return call_user_func_array('var_export', func_get_args());
|
||||
}
|
||||
public static function concat()
|
||||
{
|
||||
return call_user_func_array('var_export', func_get_args());
|
||||
}
|
||||
|
||||
public static function inlineFunction($params) {
|
||||
public static function inlineFunction($params)
|
||||
{
|
||||
return isset($params["text"]) ? $params["text"] : "";
|
||||
}
|
||||
|
||||
public static function blockFunction($params, $text) {
|
||||
public static function blockFunction($params, $text)
|
||||
{
|
||||
return $text;
|
||||
}
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
if(!file_exists(FENOM_RESOURCES.'/template')) {
|
||||
mkdir(FENOM_RESOURCES.'/template', 0777, true);
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
if (!file_exists(FENOM_RESOURCES . '/template')) {
|
||||
mkdir(FENOM_RESOURCES . '/template', 0777, true);
|
||||
} else {
|
||||
FS::clean(FENOM_RESOURCES.'/template/');
|
||||
FS::clean(FENOM_RESOURCES . '/template/');
|
||||
}
|
||||
}
|
||||
|
||||
public function tpl($name, $code) {
|
||||
public function tpl($name, $code)
|
||||
{
|
||||
$dir = dirname($name);
|
||||
if($dir != "." && !is_dir(FENOM_RESOURCES.'/template/'.$dir)) {
|
||||
mkdir(FENOM_RESOURCES.'/template/'.$dir, 0777, true);
|
||||
if ($dir != "." && !is_dir(FENOM_RESOURCES . '/template/' . $dir)) {
|
||||
mkdir(FENOM_RESOURCES . '/template/' . $dir, 0777, true);
|
||||
}
|
||||
file_put_contents(FENOM_RESOURCES.'/template/'.$name, $code);
|
||||
file_put_contents(FENOM_RESOURCES . '/template/' . $name, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,20 +105,22 @@ class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
* @param int $options
|
||||
* @param bool $dump dump source and result code (for debug)
|
||||
*/
|
||||
public function exec($code, $vars, $result, $options = 0, $dump = false) {
|
||||
public function exec($code, $vars, $result, $options = 0, $dump = false)
|
||||
{
|
||||
$this->fenom->setOptions($options);
|
||||
$tpl = $this->fenom->compileCode($code, "runtime.tpl");
|
||||
if($dump) {
|
||||
echo "\n========= DUMP BEGIN ===========\n".$code."\n--- to ---\n".$tpl->getBody()."\n========= DUMP END =============\n";
|
||||
if ($dump) {
|
||||
echo "\n========= DUMP BEGIN ===========\n" . $code . "\n--- to ---\n" . $tpl->getBody() . "\n========= DUMP END =============\n";
|
||||
}
|
||||
$this->assertSame(Modifier::strip($result), Modifier::strip($tpl->fetch($vars), true), "Test $code");
|
||||
}
|
||||
|
||||
public function execTpl($name, $code, $vars, $result, $dump = false) {
|
||||
public function execTpl($name, $code, $vars, $result, $dump = false)
|
||||
{
|
||||
$this->tpl($name, $code);
|
||||
$tpl = $this->fenom->getTemplate($name);
|
||||
if($dump) {
|
||||
echo "\n========= DUMP BEGIN ===========\n".$code."\n--- to ---\n".$tpl->getBody()."\n========= DUMP END =============\n";
|
||||
if ($dump) {
|
||||
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");
|
||||
}
|
||||
@ -121,12 +132,13 @@ class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
* @param string $message exception message
|
||||
* @param int $options Fenom's options
|
||||
*/
|
||||
public function execError($code, $exception, $message, $options = 0) {
|
||||
public function execError($code, $exception, $message, $options = 0)
|
||||
{
|
||||
$opt = $this->fenom->getOptions();
|
||||
$this->fenom->setOptions($options);
|
||||
try {
|
||||
$this->fenom->compileCode($code, "inline.tpl");
|
||||
} catch(\Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
$this->assertSame($exception, get_class($e), "Exception $code");
|
||||
$this->assertStringStartsWith($message, $e->getMessage());
|
||||
$this->fenom->setOptions($opt);
|
||||
@ -136,28 +148,31 @@ class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
$this->fail("Code $code must be invalid");
|
||||
}
|
||||
|
||||
public function assertRender($tpl, $result, $debug = false) {
|
||||
public function assertRender($tpl, $result, $debug = false)
|
||||
{
|
||||
$template = $this->fenom->compileCode($tpl);
|
||||
if($debug) {
|
||||
print_r("$tpl:\n".$template->getBody());
|
||||
if ($debug) {
|
||||
print_r("$tpl:\n" . $template->getBody());
|
||||
}
|
||||
$this->assertSame($result, $template->fetch($this->values));
|
||||
}
|
||||
|
||||
|
||||
public static function providerNumbers() {
|
||||
return array(
|
||||
array('0', 0),
|
||||
array('77', 77),
|
||||
array('-33', -33),
|
||||
array('0.2', 0.2),
|
||||
array('-0.3', -0.3),
|
||||
array('1e6', 1e6),
|
||||
array('-2e6', -2e6),
|
||||
);
|
||||
}
|
||||
public static function providerNumbers()
|
||||
{
|
||||
return array(
|
||||
array('0', 0),
|
||||
array('77', 77),
|
||||
array('-33', -33),
|
||||
array('0.2', 0.2),
|
||||
array('-0.3', -0.3),
|
||||
array('1e6', 1e6),
|
||||
array('-2e6', -2e6),
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerStrings() {
|
||||
public static function providerStrings()
|
||||
{
|
||||
return array(
|
||||
array('"str"', 'str'),
|
||||
array('"str\nand\nmany\nlines"', "str\nand\nmany\nlines"),
|
||||
@ -187,81 +202,92 @@ class TestCase extends \PHPUnit_Framework_TestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public function providerVariables() {
|
||||
return array();
|
||||
}
|
||||
public function providerVariables()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public static function providerObjects() {
|
||||
return array();
|
||||
}
|
||||
public static function providerObjects()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public static function providerArrays() {
|
||||
$scalars = array();
|
||||
$data = array(
|
||||
array('[]', array()),
|
||||
array('[[],[]]', array(array(), array())),
|
||||
);
|
||||
foreach(self::providerScalars() as $scalar) {
|
||||
$scalars[0][] = $scalar[0];
|
||||
$scalars[1][] = $scalar[1];
|
||||
public static function providerArrays()
|
||||
{
|
||||
$scalars = array();
|
||||
$data = array(
|
||||
array('[]', array()),
|
||||
array('[[],[]]', array(array(), array())),
|
||||
);
|
||||
foreach (self::providerScalars() as $scalar) {
|
||||
$scalars[0][] = $scalar[0];
|
||||
$scalars[1][] = $scalar[1];
|
||||
|
||||
$data[] = array(
|
||||
"[".$scalar[0]."]",
|
||||
array($scalar[1])
|
||||
);
|
||||
$data[] = array(
|
||||
"['some_key' =>".$scalar[0]."]",
|
||||
array('some_key' => $scalar[1])
|
||||
);
|
||||
}
|
||||
$data[] = array(
|
||||
"[".implode(", ", $scalars[0])."]",
|
||||
$scalars[1]
|
||||
);
|
||||
return $data;
|
||||
}
|
||||
$data[] = array(
|
||||
"[" . $scalar[0] . "]",
|
||||
array($scalar[1])
|
||||
);
|
||||
$data[] = array(
|
||||
"['some_key' =>" . $scalar[0] . "]",
|
||||
array('some_key' => $scalar[1])
|
||||
);
|
||||
}
|
||||
$data[] = array(
|
||||
"[" . implode(", ", $scalars[0]) . "]",
|
||||
$scalars[1]
|
||||
);
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function providerScalars() {
|
||||
return array_merge(
|
||||
self::providerNumbers(),
|
||||
self::providerStrings()
|
||||
);
|
||||
}
|
||||
public static function providerScalars()
|
||||
{
|
||||
return array_merge(
|
||||
self::providerNumbers(),
|
||||
self::providerStrings()
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerValues() {
|
||||
return array_merge(
|
||||
self::providerScalars(),
|
||||
self::providerArrays(),
|
||||
self::providerVariables(),
|
||||
self::providerObjects()
|
||||
);
|
||||
}
|
||||
public static function providerValues()
|
||||
{
|
||||
return array_merge(
|
||||
self::providerScalars(),
|
||||
self::providerArrays(),
|
||||
self::providerVariables(),
|
||||
self::providerObjects()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Fake implements \ArrayAccess {
|
||||
class Fake implements \ArrayAccess
|
||||
{
|
||||
public $vars;
|
||||
|
||||
public function offsetExists($offset) {
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function offsetGet($offset) {
|
||||
if($offset == "object") {
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ($offset == "object") {
|
||||
return new self();
|
||||
} else {
|
||||
return new self($offset);
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value) {
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->vars[$offset] = $value;
|
||||
}
|
||||
|
||||
public function offsetUnset($offset) {
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->vars[$offset]);
|
||||
}
|
||||
|
||||
public function proxy() {
|
||||
return implode(", ", func_get_args());
|
||||
}
|
||||
public function proxy()
|
||||
{
|
||||
return implode(", ", func_get_args());
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,27 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__."/../vendor/autoload.php";
|
||||
require_once __DIR__ . "/../vendor/autoload.php";
|
||||
|
||||
|
||||
define('FENOM_RESOURCES', __DIR__ . "/resources");
|
||||
|
||||
define('FENOM_RESOURCES', __DIR__."/resources");
|
||||
|
||||
require_once FENOM_RESOURCES."/actions.php";
|
||||
require_once __DIR__."/TestCase.php";
|
||||
require_once FENOM_RESOURCES . "/actions.php";
|
||||
require_once __DIR__ . "/TestCase.php";
|
||||
|
||||
ini_set('date.timezone', 'Europe/Moscow');
|
||||
|
||||
function drop() {
|
||||
function drop()
|
||||
{
|
||||
call_user_func_array("var_dump", func_get_args());
|
||||
$e = new Exception();
|
||||
echo "-------\nDump trace: \n".$e->getTraceAsString()."\n";
|
||||
echo "-------\nDump trace: \n" . $e->getTraceAsString() . "\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
function dump() {
|
||||
foreach(func_get_args() as $arg) {
|
||||
fwrite(STDERR, "DUMP: ".call_user_func("print_r", $arg, true)."\n");
|
||||
function dump()
|
||||
{
|
||||
foreach (func_get_args() as $arg) {
|
||||
fwrite(STDERR, "DUMP: " . call_user_func("print_r", $arg, true) . "\n");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -3,9 +3,11 @@
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class AutoEscapeTest extends TestCase {
|
||||
class AutoEscapeTest extends TestCase
|
||||
{
|
||||
|
||||
public static function providerHTML() {
|
||||
public static function providerHTML()
|
||||
{
|
||||
$html = "<script>alert('injection');</script>";
|
||||
$escaped = htmlspecialchars($html, ENT_COMPAT, 'UTF-8');
|
||||
$vars = array(
|
||||
@ -17,7 +19,7 @@ class AutoEscapeTest extends TestCase {
|
||||
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|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 false}{$html}{/autoescape}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{$html}{/autoescape}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
@ -31,7 +33,7 @@ class AutoEscapeTest extends TestCase {
|
||||
array('{test_function text=$html}, {$html}', "$html, $html", $vars, 0),
|
||||
array('{test_function text=$html}, {$html}', "$escaped, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{raw:test_function text=$html}, {$html}', "$html, $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{raw:test_function text="{$html|up}"}, {$html}', strtoupper($html).", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{raw:test_function text="{$html|up}"}, {$html}', strtoupper($html) . ", $escaped", $vars, \Fenom::AUTO_ESCAPE),
|
||||
array('{autoescape true}{test_function text=$html}{/autoescape}, {test_function text=$html}', "$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),
|
||||
@ -56,7 +58,8 @@ class AutoEscapeTest extends TestCase {
|
||||
/**
|
||||
* @dataProvider providerHTML
|
||||
*/
|
||||
public function testEscaping($tpl, $result, $vars, $options) {
|
||||
public function testEscaping($tpl, $result, $vars, $options)
|
||||
{
|
||||
$this->values = $vars;
|
||||
$this->fenom->setOptions($options);
|
||||
$this->assertRender($tpl, $result);
|
||||
|
@ -3,29 +3,33 @@
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class CommentTest extends TestCase {
|
||||
class CommentTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testInline($tpl_val) {
|
||||
public function testInline($tpl_val)
|
||||
{
|
||||
$this->assertRender("before {* $tpl_val *} after", "before after");
|
||||
$this->assertRender("before {* {{$tpl_val}} {{$tpl_val}} *} after", "before after");
|
||||
$this->assertRender("before {*{{$tpl_val}}*} after", "before after");
|
||||
}
|
||||
|
||||
public function testError() {
|
||||
public function testError()
|
||||
{
|
||||
$this->execError('{* ', 'Fenom\CompileException', "Unclosed comment block in line");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testMultiLine($tpl_val) {
|
||||
$this->assertRender(
|
||||
"before-1\nbefore-2 {* before-3\nbefore-4 $tpl_val after-1\nafter-2 *} after-3\nafter-4{* dummy *}\nafter-5",
|
||||
"before-1\nbefore-2 after-3\nafter-4\nafter-5"
|
||||
);
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testMultiLine($tpl_val)
|
||||
{
|
||||
$this->assertRender(
|
||||
"before-1\nbefore-2 {* before-3\nbefore-4 $tpl_val after-1\nafter-2 *} after-3\nafter-4{* dummy *}\nafter-5",
|
||||
"before-1\nbefore-2 after-3\nafter-4\nafter-5"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -3,14 +3,17 @@
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class CustomProviderTest extends TestCase {
|
||||
class CustomProviderTest extends TestCase
|
||||
{
|
||||
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->fenom->addProvider("my", new Provider(FENOM_RESOURCES.'/provider'));
|
||||
$this->fenom->addProvider("my", new Provider(FENOM_RESOURCES . '/provider'));
|
||||
}
|
||||
|
||||
public function testCustom() {
|
||||
public function testCustom()
|
||||
{
|
||||
$this->assertRender("start: {include 'my:include.tpl'}", 'start: include template');
|
||||
//$this->assertRender("start: {import 'my:macros.tpl' as ops} {ops.add a=3 b=6}");
|
||||
}
|
||||
|
@ -2,41 +2,44 @@
|
||||
namespace Fenom;
|
||||
use Fenom, Fenom\TestCase;
|
||||
|
||||
class ExtendsTemplateTest extends TestCase {
|
||||
class ExtendsTemplateTest extends TestCase
|
||||
{
|
||||
|
||||
public function _testSandbox() {
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES.'/provider', FENOM_RESOURCES.'/compile');
|
||||
try {
|
||||
print_r($this->fenom->getTemplate('use/child.tpl')->getBody());
|
||||
} catch (\Exception $e) {
|
||||
echo "$e";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
public function _testSandbox()
|
||||
{
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/provider', FENOM_RESOURCES . '/compile');
|
||||
try {
|
||||
print_r($this->fenom->getTemplate('use/child.tpl')->getBody());
|
||||
} catch (\Exception $e) {
|
||||
echo "$e";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Templates skeletons
|
||||
* @param array $vars
|
||||
* @return array
|
||||
*/
|
||||
public static function templates(array $vars) {
|
||||
/**
|
||||
* Templates skeletons
|
||||
* @param array $vars
|
||||
* @return array
|
||||
*/
|
||||
public static function templates(array $vars)
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
"name" => "level.0.tpl",
|
||||
"name" => "level.0.tpl",
|
||||
"level" => 0,
|
||||
"blocks" => array(
|
||||
"b1" => "default {\$default}",
|
||||
"b2" => "empty 0"
|
||||
),
|
||||
"result" => array(
|
||||
"b1" => "default ".$vars["default"],
|
||||
"b1" => "default " . $vars["default"],
|
||||
"b2" => "empty 0"
|
||||
),
|
||||
),
|
||||
array(
|
||||
"name" => "level.1.tpl",
|
||||
"name" => "level.1.tpl",
|
||||
"level" => 1,
|
||||
"use" => false,
|
||||
"use" => false,
|
||||
"blocks" => array(
|
||||
"b1" => "from level 1"
|
||||
),
|
||||
@ -46,9 +49,9 @@ class ExtendsTemplateTest extends TestCase {
|
||||
),
|
||||
),
|
||||
array(
|
||||
"name" => "level.2.tpl",
|
||||
"name" => "level.2.tpl",
|
||||
"level" => 2,
|
||||
"use" => false,
|
||||
"use" => false,
|
||||
"blocks" => array(
|
||||
"b2" => "from level 2",
|
||||
"b4" => "unused block"
|
||||
@ -59,9 +62,9 @@ class ExtendsTemplateTest extends TestCase {
|
||||
),
|
||||
),
|
||||
array(
|
||||
"name" => "level.3.tpl",
|
||||
"name" => "level.3.tpl",
|
||||
"level" => 3,
|
||||
"use" => false,
|
||||
"use" => false,
|
||||
"blocks" => array(
|
||||
"b1" => "from level 3",
|
||||
"b2" => "also from level 3"
|
||||
@ -74,35 +77,37 @@ class ExtendsTemplateTest extends TestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate templates by skeletons
|
||||
*
|
||||
* @param $block_mask
|
||||
* @param $extend_mask
|
||||
* @param array $skels
|
||||
* @return array
|
||||
*/
|
||||
public static function generate($block_mask, $extend_mask, $skels) {
|
||||
/**
|
||||
* Generate templates by skeletons
|
||||
*
|
||||
* @param $block_mask
|
||||
* @param $extend_mask
|
||||
* @param array $skels
|
||||
* @return array
|
||||
*/
|
||||
public static function generate($block_mask, $extend_mask, $skels)
|
||||
{
|
||||
$t = array();
|
||||
foreach($skels as $level => $tpl) {
|
||||
$src = 'level#'.$level.' ';
|
||||
foreach ($skels as $level => $tpl) {
|
||||
$src = 'level#' . $level . ' ';
|
||||
|
||||
foreach($tpl["blocks"] as $bname => &$bcode) {
|
||||
$src .= sprintf($block_mask, $bname, $bname.': '.$bcode)." level#$level ";
|
||||
foreach ($tpl["blocks"] as $bname => &$bcode) {
|
||||
$src .= sprintf($block_mask, $bname, $bname . ': ' . $bcode) . " level#$level ";
|
||||
}
|
||||
$dst = "level#0 ";
|
||||
foreach($tpl["result"] as $bname => &$bcode) {
|
||||
$dst .= $bname.': '.$bcode.' level#0 ';
|
||||
foreach ($tpl["result"] as $bname => &$bcode) {
|
||||
$dst .= $bname . ': ' . $bcode . ' level#0 ';
|
||||
}
|
||||
if($level) {
|
||||
$src = sprintf($extend_mask, $level-1).' '.$src;
|
||||
if ($level) {
|
||||
$src = sprintf($extend_mask, $level - 1) . ' ' . $src;
|
||||
}
|
||||
$t[ $tpl["name"] ] = array("src" => $src, "dst" => $dst);
|
||||
$t[$tpl["name"]] = array("src" => $src, "dst" => $dst);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
|
||||
public function _testTemplateExtends() {
|
||||
public function _testTemplateExtends()
|
||||
{
|
||||
$vars = array(
|
||||
"b1" => "b1",
|
||||
"b2" => "b2",
|
||||
@ -112,39 +117,41 @@ class ExtendsTemplateTest extends TestCase {
|
||||
"default" => 5
|
||||
);
|
||||
$tpls = self::generate('{block "%s"}%s{/block}', '{extends "level.%d.tpl"}', self::templates($vars));
|
||||
foreach($tpls as $name => $tpl) {
|
||||
foreach ($tpls as $name => $tpl) {
|
||||
$this->tpl($name, $tpl["src"]);
|
||||
$this->assertSame($this->fenom->fetch($name, $vars), $tpl["dst"]);
|
||||
}
|
||||
return;
|
||||
return;
|
||||
$vars["default"]++;
|
||||
$this->fenom->flush();
|
||||
$tpls = self::generate('{block "{$%s}"}%s{/block}', '{extends "level.%d.tpl"}', self::templates($vars));
|
||||
arsort($tpls);
|
||||
foreach($tpls as $name => $tpl) {
|
||||
$this->tpl("d.".$name, $tpl["src"]);
|
||||
$this->assertSame($this->fenom->fetch("d.".$name, $vars), $tpl["dst"]);
|
||||
foreach ($tpls as $name => $tpl) {
|
||||
$this->tpl("d." . $name, $tpl["src"]);
|
||||
$this->assertSame($this->fenom->fetch("d." . $name, $vars), $tpl["dst"]);
|
||||
}
|
||||
$vars["default"]++;
|
||||
$this->fenom->flush();
|
||||
$tpls = self::generate('{block "%s"}%s{/block}', '{extends "$level.%d.tpl"}', self::templates($vars));
|
||||
arsort($tpls);
|
||||
foreach($tpls as $name => $tpl) {
|
||||
$this->tpl("x.".$name, $tpl["src"]);
|
||||
$this->assertSame($this->fenom->fetch("x.".$name, $vars), $tpl["dst"]);
|
||||
foreach ($tpls as $name => $tpl) {
|
||||
$this->tpl("x." . $name, $tpl["src"]);
|
||||
$this->assertSame($this->fenom->fetch("x." . $name, $vars), $tpl["dst"]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group use
|
||||
*/
|
||||
public function testUse() {
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES.'/provider', FENOM_RESOURCES.'/compile');
|
||||
$this->assertSame("<html>\n block 1 blocks \n block 2 child \n</html>", $this->fenom->fetch('use/child.tpl'));
|
||||
}
|
||||
/**
|
||||
* @group use
|
||||
*/
|
||||
public function testUse()
|
||||
{
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/provider', FENOM_RESOURCES . '/compile');
|
||||
$this->assertSame("<html>\n block 1 blocks \n block 2 child \n</html>", $this->fenom->fetch('use/child.tpl'));
|
||||
}
|
||||
|
||||
public function _testParent() {
|
||||
public function _testParent()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,70 +1,82 @@
|
||||
<?php
|
||||
namespace Fenom;
|
||||
|
||||
class FunctionsTest extends TestCase {
|
||||
class FunctionsTest extends TestCase
|
||||
{
|
||||
|
||||
const FUNCTION_ARGUMENT_CONSTANT = 1;
|
||||
const FUNCTION_ARGUMENT_CONSTANT = 1;
|
||||
|
||||
public static function functionSum($of = array()) {
|
||||
return array_sum($of);
|
||||
}
|
||||
public static function functionSum($of = array())
|
||||
{
|
||||
return array_sum($of);
|
||||
}
|
||||
|
||||
public static function functionPow($a, $n = 2) {
|
||||
return pow($a, $n);
|
||||
}
|
||||
public static function functionPow($a, $n = 2)
|
||||
{
|
||||
return pow($a, $n);
|
||||
}
|
||||
|
||||
public static function functionInc($a, $i = self::FUNCTION_ARGUMENT_CONSTANT) {
|
||||
return $a + $i;
|
||||
}
|
||||
public static function functionInc($a, $i = self::FUNCTION_ARGUMENT_CONSTANT)
|
||||
{
|
||||
return $a + $i;
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->fenom->addFunctionSmart('sum', __CLASS__ . '::functionSum');
|
||||
$this->fenom->addFunctionSmart('pow', __CLASS__ . '::functionPow');
|
||||
$this->fenom->addFunctionSmart('inc', __CLASS__ . '::functionInc');
|
||||
$this->fenom->addFunctionSmart('sum', __CLASS__ . '::functionSum');
|
||||
$this->fenom->addFunctionSmart('pow', __CLASS__ . '::functionPow');
|
||||
$this->fenom->addFunctionSmart('inc', __CLASS__ . '::functionInc');
|
||||
|
||||
$this->tpl('function_params_scalar.tpl', '{pow a=2 n=3}');
|
||||
$this->tpl('function_params_dynamic.tpl', '{pow a=$a n=$n}');
|
||||
$this->tpl('function_default_param_scalar.tpl', '{pow a=2}');
|
||||
$this->tpl('function_default_param_empty_array.tpl', '{sum}');
|
||||
$this->tpl('function_default_param_const.tpl', '{inc a=1}');
|
||||
$this->tpl('function_array_param.tpl', '{sum of=[1, 2, 3, 4, 5]}');
|
||||
$this->tpl('function_array_param_pos.tpl', '{sum [1, 2, 3, 4, 5]}');
|
||||
}
|
||||
$this->tpl('function_params_scalar.tpl', '{pow a=2 n=3}');
|
||||
$this->tpl('function_params_dynamic.tpl', '{pow a=$a n=$n}');
|
||||
$this->tpl('function_default_param_scalar.tpl', '{pow a=2}');
|
||||
$this->tpl('function_default_param_empty_array.tpl', '{sum}');
|
||||
$this->tpl('function_default_param_const.tpl', '{inc a=1}');
|
||||
$this->tpl('function_array_param.tpl', '{sum of=[1, 2, 3, 4, 5]}');
|
||||
$this->tpl('function_array_param_pos.tpl', '{sum [1, 2, 3, 4, 5]}');
|
||||
}
|
||||
|
||||
public function testFunctionWithParams() {
|
||||
public function testFunctionWithParams()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_params_scalar.tpl');
|
||||
$this->assertEquals('8', $output);
|
||||
$this->assertEquals('8', $output);
|
||||
}
|
||||
|
||||
public function testFunctionWithDynamicParams() {
|
||||
public function testFunctionWithDynamicParams()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_params_dynamic.tpl', array('a' => 3, 'n' => 4));
|
||||
$this->assertEquals('81', $output);
|
||||
$this->assertEquals('81', $output);
|
||||
}
|
||||
|
||||
public function testFunctionWithDefaultParamScalar() {
|
||||
$output = $this->fenom->fetch('function_default_param_scalar.tpl');
|
||||
$this->assertEquals('4', $output);
|
||||
}
|
||||
public function testFunctionWithDefaultParamScalar()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_default_param_scalar.tpl');
|
||||
$this->assertEquals('4', $output);
|
||||
}
|
||||
|
||||
public function testFunctionWithDefaultParamArray() {
|
||||
$output = $this->fenom->fetch('function_default_param_empty_array.tpl');
|
||||
$this->assertEquals('0', $output);
|
||||
}
|
||||
public function testFunctionWithDefaultParamArray()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_default_param_empty_array.tpl');
|
||||
$this->assertEquals('0', $output);
|
||||
}
|
||||
|
||||
public function testFunctionWithDefaultParamConst() {
|
||||
$output = $this->fenom->fetch('function_default_param_const.tpl');
|
||||
$this->assertEquals('2', $output);
|
||||
}
|
||||
public function testFunctionWithDefaultParamConst()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_default_param_const.tpl');
|
||||
$this->assertEquals('2', $output);
|
||||
}
|
||||
|
||||
public function testFunctionWithArrayNamedParam() {
|
||||
$output = $this->fenom->fetch('function_array_param.tpl');
|
||||
$this->assertEquals('15', $output);
|
||||
}
|
||||
public function testFunctionWithArrayNamedParam()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_array_param.tpl');
|
||||
$this->assertEquals('15', $output);
|
||||
}
|
||||
|
||||
public function testFunctionWithArrayPositionalParam() {
|
||||
$output = $this->fenom->fetch('function_array_param_pos.tpl');
|
||||
$this->assertEquals('15', $output);
|
||||
}
|
||||
public function testFunctionWithArrayPositionalParam()
|
||||
{
|
||||
$output = $this->fenom->fetch('function_array_param_pos.tpl');
|
||||
$this->assertEquals('15', $output);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
<?php
|
||||
namespace Fenom;
|
||||
|
||||
class MacrosTest extends TestCase {
|
||||
class MacrosTest extends TestCase
|
||||
{
|
||||
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tpl("math.tpl", '
|
||||
{macro plus(x, y)}
|
||||
@ -52,31 +54,35 @@ class MacrosTest extends TestCase {
|
||||
{macro.factorial num=10}');
|
||||
}
|
||||
|
||||
public function _testSandbox() {
|
||||
public function _testSandbox()
|
||||
{
|
||||
try {
|
||||
$this->fenom->compile("macro_recursive.tpl");
|
||||
$this->fenom->flush();
|
||||
var_dump($this->fenom->fetch("macro_recursive.tpl", []));
|
||||
} catch(\Exception $e) {
|
||||
var_dump($e->getMessage().": ".$e->getTraceAsString());
|
||||
$this->fenom->compile("macro_recursive.tpl");
|
||||
$this->fenom->flush();
|
||||
var_dump($this->fenom->fetch("macro_recursive.tpl", []));
|
||||
} catch (\Exception $e) {
|
||||
var_dump($e->getMessage() . ": " . $e->getTraceAsString());
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
public function testMacros() {
|
||||
public function testMacros()
|
||||
{
|
||||
$tpl = $this->fenom->compile('math.tpl');
|
||||
|
||||
$this->assertStringStartsWith('x + y = ', trim($tpl->macros["plus"]["body"]));
|
||||
$this->assertSame('Math: x + y = 5 , x - y - z = 6', Modifier::strip($tpl->fetch(array()), true));
|
||||
}
|
||||
|
||||
public function testImport() {
|
||||
public function testImport()
|
||||
{
|
||||
$tpl = $this->fenom->compile('import.tpl');
|
||||
|
||||
$this->assertSame('Imp: x + y = 3 , x - y - z = 3', Modifier::strip($tpl->fetch(array()), true));
|
||||
}
|
||||
|
||||
public function testImportCustom() {
|
||||
public function testImportCustom()
|
||||
{
|
||||
$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));
|
||||
@ -86,13 +92,15 @@ class MacrosTest extends TestCase {
|
||||
* @expectedExceptionMessage Undefined macro 'plus'
|
||||
* @expectedException \Fenom\CompileException
|
||||
*/
|
||||
public function testImportMiss() {
|
||||
public function testImportMiss()
|
||||
{
|
||||
$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));
|
||||
}
|
||||
|
||||
public function testRecursive() {
|
||||
public function testRecursive()
|
||||
{
|
||||
$this->fenom->compile('macro_recursive.tpl');
|
||||
$this->fenom->flush();
|
||||
$tpl = $this->fenom->getTemplate('macro_recursive.tpl');
|
||||
|
@ -2,11 +2,13 @@
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class ModifiersTest extends TestCase {
|
||||
class ModifiersTest extends TestCase
|
||||
{
|
||||
|
||||
public static function providerTruncate() {
|
||||
public static function providerTruncate()
|
||||
{
|
||||
$lorem = 'Lorem ipsum dolor sit amet'; // en
|
||||
$uni = 'Лорем ипсум долор сит амет'; // ru
|
||||
$uni = 'Лорем ипсум долор сит амет'; // ru
|
||||
return array(
|
||||
// ascii chars
|
||||
array($lorem, 'Lorem ip...', 8),
|
||||
@ -33,7 +35,8 @@ class ModifiersTest extends TestCase {
|
||||
* @param bool $by_words
|
||||
* @param bool $middle
|
||||
*/
|
||||
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}');
|
||||
$this->assertEquals($out, $tpl->fetch(array(
|
||||
"text" => $in,
|
||||
@ -44,7 +47,8 @@ class ModifiersTest extends TestCase {
|
||||
)));
|
||||
}
|
||||
|
||||
public static function providerUpLow() {
|
||||
public static function providerUpLow()
|
||||
{
|
||||
return array(
|
||||
array("up", "lorem", "LOREM"),
|
||||
array("up", "Lorem", "LOREM"),
|
||||
@ -64,14 +68,16 @@ class ModifiersTest extends TestCase {
|
||||
* @param $in
|
||||
* @param $out
|
||||
*/
|
||||
public function testUpLow($modifier, $in, $out) {
|
||||
$tpl = $this->fenom->compileCode('{$text|'.$modifier.'}');
|
||||
public function testUpLow($modifier, $in, $out)
|
||||
{
|
||||
$tpl = $this->fenom->compileCode('{$text|' . $modifier . '}');
|
||||
$this->assertEquals($out, $tpl->fetch(array(
|
||||
"text" => $in,
|
||||
)));
|
||||
}
|
||||
|
||||
public static function providerLength() {
|
||||
public static function providerLength()
|
||||
{
|
||||
return array(
|
||||
array("length", 6),
|
||||
array("длина", 5),
|
||||
@ -90,7 +96,8 @@ class ModifiersTest extends TestCase {
|
||||
* @param $in
|
||||
* @param $out
|
||||
*/
|
||||
public function testLength($in, $out) {
|
||||
public function testLength($in, $out)
|
||||
{
|
||||
$tpl = $this->fenom->compileCode('{$data|length}');
|
||||
$this->assertEquals($out, $tpl->fetch(array(
|
||||
"data" => $in,
|
||||
|
@ -3,87 +3,97 @@ namespace Fenom;
|
||||
use Fenom;
|
||||
use Fenom\TestCase;
|
||||
|
||||
class ProviderTest extends TestCase {
|
||||
class ProviderTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Provider
|
||||
*/
|
||||
public $provider;
|
||||
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tpl("template1.tpl", 'Template 1 {$a}');
|
||||
$this->tpl("template2.tpl", 'Template 2 {$a}');
|
||||
$this->tpl("sub/template3.tpl", 'Template 3 {$a}');
|
||||
$this->provider = new Provider(FENOM_RESOURCES.'/template');
|
||||
$this->provider = new Provider(FENOM_RESOURCES . '/template');
|
||||
clearstatcache();
|
||||
}
|
||||
|
||||
public function testIsTemplateExists() {
|
||||
public function testIsTemplateExists()
|
||||
{
|
||||
clearstatcache();
|
||||
$this->assertTrue($this->provider->templateExists("template1.tpl"));
|
||||
$this->assertFalse($this->provider->templateExists("unexists.tpl"));
|
||||
}
|
||||
|
||||
public function testGetSource() {
|
||||
public function testGetSource()
|
||||
{
|
||||
clearstatcache();
|
||||
$src = $this->provider->getSource("template1.tpl", $time);
|
||||
clearstatcache();
|
||||
$this->assertEquals(file_get_contents(FENOM_RESOURCES.'/template/template1.tpl'), $src);
|
||||
$this->assertEquals(filemtime(FENOM_RESOURCES.'/template/template1.tpl'), $time);
|
||||
$this->assertEquals(file_get_contents(FENOM_RESOURCES . '/template/template1.tpl'), $src);
|
||||
$this->assertEquals(filemtime(FENOM_RESOURCES . '/template/template1.tpl'), $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testGetSourceInvalid() {
|
||||
public function testGetSourceInvalid()
|
||||
{
|
||||
$this->provider->getSource("unexists.tpl", $time);
|
||||
}
|
||||
|
||||
public function testGetLastModified() {
|
||||
public function testGetLastModified()
|
||||
{
|
||||
$time = $this->provider->getLastModified("template1.tpl");
|
||||
clearstatcache();
|
||||
$this->assertEquals(filemtime(FENOM_RESOURCES.'/template/template1.tpl'), $time);
|
||||
$this->assertEquals(filemtime(FENOM_RESOURCES . '/template/template1.tpl'), $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testGetLastModifiedInvalid() {
|
||||
public function testGetLastModifiedInvalid()
|
||||
{
|
||||
$this->provider->getLastModified("unexists.tpl");
|
||||
}
|
||||
|
||||
public function testVerify() {
|
||||
public function testVerify()
|
||||
{
|
||||
$templates = array(
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl'),
|
||||
"template2.tpl" => filemtime(FENOM_RESOURCES.'/template/template2.tpl')
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES . '/template/template1.tpl'),
|
||||
"template2.tpl" => filemtime(FENOM_RESOURCES . '/template/template2.tpl')
|
||||
);
|
||||
clearstatcache();
|
||||
$this->assertTrue($this->provider->verify($templates));
|
||||
clearstatcache();
|
||||
$templates = array(
|
||||
"template2.tpl" => filemtime(FENOM_RESOURCES.'/template/template2.tpl'),
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl')
|
||||
"template2.tpl" => filemtime(FENOM_RESOURCES . '/template/template2.tpl'),
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES . '/template/template1.tpl')
|
||||
);
|
||||
clearstatcache();
|
||||
$this->assertTrue($this->provider->verify($templates));
|
||||
}
|
||||
|
||||
public function testVerifyInvalid() {
|
||||
public function testVerifyInvalid()
|
||||
{
|
||||
$templates = array(
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl'),
|
||||
"template2.tpl" => filemtime(FENOM_RESOURCES.'/template/template2.tpl') + 1
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES . '/template/template1.tpl'),
|
||||
"template2.tpl" => filemtime(FENOM_RESOURCES . '/template/template2.tpl') + 1
|
||||
);
|
||||
clearstatcache();
|
||||
$this->assertFalse($this->provider->verify($templates));
|
||||
clearstatcache();
|
||||
$templates = array(
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl'),
|
||||
"template1.tpl" => filemtime(FENOM_RESOURCES . '/template/template1.tpl'),
|
||||
"unexists.tpl" => 1234567890
|
||||
);
|
||||
$this->assertFalse($this->provider->verify($templates));
|
||||
}
|
||||
|
||||
public function testGetAll() {
|
||||
public function testGetAll()
|
||||
{
|
||||
$list = $this->provider->getList();
|
||||
sort($list);
|
||||
$this->assertSame(array(
|
||||
|
@ -3,22 +3,25 @@ namespace Fenom;
|
||||
use Fenom,
|
||||
Fenom\Render;
|
||||
|
||||
class RenderTest extends \PHPUnit_Framework_TestCase {
|
||||
class RenderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Render
|
||||
*/
|
||||
public static $render;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
self::$render = new Render(Fenom::factory("."), function ($tpl) {
|
||||
echo "It is render's function ".$tpl["render"];
|
||||
echo "It is render's function " . $tpl["render"];
|
||||
}, array(
|
||||
"name" => "render.tpl"
|
||||
));
|
||||
}
|
||||
|
||||
public function testCreate() {
|
||||
public function testCreate()
|
||||
{
|
||||
$r = new Render(Fenom::factory("."), function () {
|
||||
echo "Test render";
|
||||
}, array(
|
||||
@ -27,14 +30,16 @@ class RenderTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertSame("Test render", $r->fetch(array()));
|
||||
}
|
||||
|
||||
public function testDisplay() {
|
||||
public function testDisplay()
|
||||
{
|
||||
ob_start();
|
||||
self::$render->display(array("render" => "display"));
|
||||
$out = ob_get_clean();
|
||||
$this->assertSame("It is render's function display", $out);
|
||||
}
|
||||
|
||||
public function testFetch() {
|
||||
public function testFetch()
|
||||
{
|
||||
$this->assertSame("It is render's function fetch", self::$render->fetch(array("render" => "fetch")));
|
||||
}
|
||||
|
||||
@ -42,7 +47,8 @@ class RenderTest extends \PHPUnit_Framework_TestCase {
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage template error
|
||||
*/
|
||||
public function testFetchException() {
|
||||
public function testFetchException()
|
||||
{
|
||||
$render = new Render(Fenom::factory("."), function () {
|
||||
echo "error";
|
||||
throw new \RuntimeException("template error");
|
||||
|
@ -1,22 +1,26 @@
|
||||
<?php
|
||||
namespace Fenom;
|
||||
|
||||
class ScopeTest extends TestCase {
|
||||
public function openTag($tokenizer, $scope) {
|
||||
class ScopeTest extends TestCase
|
||||
{
|
||||
public function openTag($tokenizer, $scope)
|
||||
{
|
||||
$this->assertInstanceOf('Fenom\Tokenizer', $tokenizer);
|
||||
$this->assertInstanceOf('Fenom\Scope', $scope);
|
||||
$scope["value"] = true;
|
||||
return "open-tag";
|
||||
}
|
||||
|
||||
public function closeTag($tokenizer, $scope) {
|
||||
public function closeTag($tokenizer, $scope)
|
||||
{
|
||||
$this->assertInstanceOf('Fenom\Tokenizer', $tokenizer);
|
||||
$this->assertInstanceOf('Fenom\Scope', $scope);
|
||||
$this->assertTrue($scope["value"]);
|
||||
return "close-tag";
|
||||
}
|
||||
|
||||
public function testBlock() {
|
||||
public function testBlock()
|
||||
{
|
||||
/*$scope = new Scope($this->fenom, new Template($this->fenom), 1, array(
|
||||
"open" => array($this, "openTag"),
|
||||
"close" => array($this, "closeTag")
|
||||
@ -28,5 +32,5 @@ class ScopeTest extends TestCase {
|
||||
$content = " some ?> content\n\nwith /*#9999999#* / many\n\tlines";
|
||||
$scope->tpl->_body = "start <?php ".$scope->open($tokenizer)." ?>".$content;
|
||||
$this->assertSame($content, $scope->getContent());*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,54 +3,62 @@
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class TagsTest extends TestCase {
|
||||
class TagsTest extends TestCase
|
||||
{
|
||||
|
||||
public function _testSandbox() {
|
||||
try {
|
||||
var_dump($this->fenom->compileCode('{var $a=Fenom\TestCase::dots("asd")}')->getBody());
|
||||
} catch(\Exception $e) {
|
||||
echo "$e";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testVar($tpl_val, $val) {
|
||||
$this->assertRender("{var \$a=$tpl_val}\nVar: {\$a}", "\nVar: ".$val);
|
||||
public function _testSandbox()
|
||||
{
|
||||
try {
|
||||
var_dump($this->fenom->compileCode('{var $a=Fenom\TestCase::dots("asd")}')->getBody());
|
||||
} catch (\Exception $e) {
|
||||
echo "$e";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testVarBlock($tpl_val, $val) {
|
||||
$this->assertRender("{var \$a}before {{$tpl_val}} after{/var}\nVar: {\$a}", "\nVar: before ".$val." after");
|
||||
public function testVar($tpl_val, $val)
|
||||
{
|
||||
$this->assertRender("{var \$a=$tpl_val}\nVar: {\$a}", "\nVar: " . $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testVarBlockModified($tpl_val, $val) {
|
||||
$this->assertRender("{var \$a|low|dots}before {{$tpl_val}} after{/var}\nVar: {\$a}", "\nVar: ".strtolower("before ".$val." after")."...");
|
||||
public function testVarBlock($tpl_val, $val)
|
||||
{
|
||||
$this->assertRender("{var \$a}before {{$tpl_val}} after{/var}\nVar: {\$a}", "\nVar: before " . $val . " after");
|
||||
}
|
||||
|
||||
public function testCycle() {
|
||||
$this->assertRender('{for $i=0 to=4}{cycle ["one", "two"]}, {/for}', "one, two, one, two, one, ");
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testVarBlockModified($tpl_val, $val)
|
||||
{
|
||||
$this->assertRender("{var \$a|low|dots}before {{$tpl_val}} after{/var}\nVar: {\$a}", "\nVar: " . strtolower("before " . $val . " after") . "...");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testCycleIndex() {
|
||||
$this->assertRender('{var $a=["one", "two"]}{for $i=1 to=5}{cycle $a index=$i}, {/for}', "two, one, two, one, two, ");
|
||||
}
|
||||
public function testCycle()
|
||||
{
|
||||
$this->assertRender('{for $i=0 to=4}{cycle ["one", "two"]}, {/for}', "one, two, one, two, one, ");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testFilter($tpl_val, $val) {
|
||||
$this->assertRender("{filter|up} before {{$tpl_val}} after {/filter}", strtoupper(" before {$val} after "));
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testCycleIndex()
|
||||
{
|
||||
$this->assertRender('{var $a=["one", "two"]}{for $i=1 to=5}{cycle $a index=$i}, {/for}', "two, one, two, one, two, ");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerScalars
|
||||
*/
|
||||
public function testFilter($tpl_val, $val)
|
||||
{
|
||||
$this->assertRender("{filter|up} before {{$tpl_val}} after {/filter}", strtoupper(" before {$val} after "));
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -2,58 +2,61 @@
|
||||
namespace Fenom;
|
||||
use Fenom\Tokenizer;
|
||||
|
||||
class TokenizerTest extends \PHPUnit_Framework_TestCase {
|
||||
class TokenizerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function testTokens() {
|
||||
$code = 'hello, please resolve this example: sin($x)+tan($x*$t) = {U|[0,1]}';
|
||||
$tokens = new Tokenizer($code);
|
||||
$this->assertSame(T_STRING, $tokens->key());
|
||||
$this->assertSame("hello", $tokens->current());
|
||||
public function testTokens()
|
||||
{
|
||||
$code = 'hello, please resolve this example: sin($x)+tan($x*$t) = {U|[0,1]}';
|
||||
$tokens = new Tokenizer($code);
|
||||
$this->assertSame(T_STRING, $tokens->key());
|
||||
$this->assertSame("hello", $tokens->current());
|
||||
|
||||
$this->assertTrue($tokens->isNext(","));
|
||||
$this->assertFalse($tokens->isNext("="));
|
||||
$this->assertFalse($tokens->isNext(T_STRING));
|
||||
$this->assertFalse($tokens->isNext($tokens::MACRO_UNARY));
|
||||
$this->assertTrue($tokens->isNext(","));
|
||||
$this->assertFalse($tokens->isNext("="));
|
||||
$this->assertFalse($tokens->isNext(T_STRING));
|
||||
$this->assertFalse($tokens->isNext($tokens::MACRO_UNARY));
|
||||
|
||||
$this->assertFalse($tokens->isNext("=", T_STRING, $tokens::MACRO_UNARY));
|
||||
$this->assertTrue($tokens->isNext("=", T_STRING, $tokens::MACRO_UNARY, ","));
|
||||
$this->assertFalse($tokens->isNext("=", T_STRING, $tokens::MACRO_UNARY));
|
||||
$this->assertTrue($tokens->isNext("=", T_STRING, $tokens::MACRO_UNARY, ","));
|
||||
|
||||
$this->assertSame(",", $tokens->getNext());
|
||||
$this->assertSame(",", $tokens->key());
|
||||
$this->assertSame("please", $tokens->getNext(T_STRING));
|
||||
$this->assertSame("resolve", $tokens->getNext($tokens::MACRO_UNARY, T_STRING));
|
||||
$this->assertSame(",", $tokens->getNext());
|
||||
$this->assertSame(",", $tokens->key());
|
||||
$this->assertSame("please", $tokens->getNext(T_STRING));
|
||||
$this->assertSame("resolve", $tokens->getNext($tokens::MACRO_UNARY, T_STRING));
|
||||
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
|
||||
$this->assertSame(":", $tokens->current());
|
||||
$this->assertSame(":", $tokens->key());
|
||||
$this->assertSame(":", $tokens->current());
|
||||
$this->assertSame(":", $tokens->key());
|
||||
|
||||
|
||||
$this->assertSame("sin", $tokens->getNext($tokens::MACRO_STRING));
|
||||
$this->assertSame("sin", $tokens->current());
|
||||
$this->assertSame(T_STRING, $tokens->key());
|
||||
$this->assertTrue($tokens->is(T_STRING));
|
||||
$this->assertTrue($tokens->is($tokens::MACRO_STRING));
|
||||
$this->assertFalse($tokens->is($tokens::MACRO_EQUALS));
|
||||
$this->assertFalse($tokens->is(T_DNUMBER));
|
||||
$this->assertFalse($tokens->is(":"));
|
||||
$this->assertSame("(", $tokens->getNext("(",")"));
|
||||
$this->assertSame("sin", $tokens->getNext($tokens::MACRO_STRING));
|
||||
$this->assertSame("sin", $tokens->current());
|
||||
$this->assertSame(T_STRING, $tokens->key());
|
||||
$this->assertTrue($tokens->is(T_STRING));
|
||||
$this->assertTrue($tokens->is($tokens::MACRO_STRING));
|
||||
$this->assertFalse($tokens->is($tokens::MACRO_EQUALS));
|
||||
$this->assertFalse($tokens->is(T_DNUMBER));
|
||||
$this->assertFalse($tokens->is(":"));
|
||||
$this->assertSame("(", $tokens->getNext("(", ")"));
|
||||
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
$this->assertSame("+", $tokens->getNext($tokens::MACRO_BINARY));
|
||||
}
|
||||
$tokens->next();
|
||||
$tokens->next();
|
||||
$this->assertSame("+", $tokens->getNext($tokens::MACRO_BINARY));
|
||||
}
|
||||
|
||||
public function testSkip() {
|
||||
public function testSkip()
|
||||
{
|
||||
$text = "1 foo: bar ( 3 + double ) ";
|
||||
$tokens = new Tokenizer($text);
|
||||
|
||||
$tokens->skip()->skip(T_STRING)->skip(':');
|
||||
try {
|
||||
$tokens->skip(T_STRING)->skip('(')->skip(':');
|
||||
} catch(\Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
$this->assertInstanceOf('Fenom\UnexpectedTokenException', $e);
|
||||
$this->assertStringStartsWith("Unexpected token '3' in expression, expect ':'", $e->getMessage());
|
||||
}
|
||||
|
@ -3,22 +3,25 @@
|
||||
use Fenom\Render,
|
||||
Fenom\Provider as FS;
|
||||
|
||||
class FenomTest extends \Fenom\TestCase {
|
||||
class FenomTest extends \Fenom\TestCase
|
||||
{
|
||||
|
||||
public static function providerOptions() {
|
||||
public static function providerOptions()
|
||||
{
|
||||
return array(
|
||||
array("disable_methods", Fenom::DENY_METHODS),
|
||||
array("disable_native_funcs", Fenom::DENY_INLINE_FUNCS),
|
||||
array("disable_cache", Fenom::DISABLE_CACHE),
|
||||
array("force_compile", Fenom::FORCE_COMPILE),
|
||||
array("auto_reload", Fenom::AUTO_RELOAD),
|
||||
array("force_include", Fenom::FORCE_INCLUDE),
|
||||
array("auto_escape", Fenom::AUTO_ESCAPE),
|
||||
array("force_verify", Fenom::FORCE_VERIFY)
|
||||
array("disable_methods", Fenom::DENY_METHODS),
|
||||
array("disable_native_funcs", Fenom::DENY_INLINE_FUNCS),
|
||||
array("disable_cache", Fenom::DISABLE_CACHE),
|
||||
array("force_compile", Fenom::FORCE_COMPILE),
|
||||
array("auto_reload", Fenom::AUTO_RELOAD),
|
||||
array("force_include", Fenom::FORCE_INCLUDE),
|
||||
array("auto_escape", Fenom::AUTO_ESCAPE),
|
||||
array("force_verify", Fenom::FORCE_VERIFY)
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompileFile() {
|
||||
public function testCompileFile()
|
||||
{
|
||||
$a = array(
|
||||
"a" => "a",
|
||||
"b" => "b"
|
||||
@ -29,17 +32,19 @@ class FenomTest extends \Fenom\TestCase {
|
||||
$this->assertSame("Template 2 b", $this->fenom->fetch('template2.tpl', $a));
|
||||
$this->assertInstanceOf('Fenom\Render', $this->fenom->getTemplate('template1.tpl'));
|
||||
$this->assertInstanceOf('Fenom\Render', $this->fenom->getTemplate('template2.tpl'));
|
||||
$this->assertSame(3, iterator_count(new FilesystemIterator(FENOM_RESOURCES.'/compile')));
|
||||
$this->assertSame(3, iterator_count(new FilesystemIterator(FENOM_RESOURCES . '/compile')));
|
||||
}
|
||||
|
||||
public function testStorage() {
|
||||
public function testStorage()
|
||||
{
|
||||
$this->tpl('custom.tpl', 'Custom template');
|
||||
$this->assertSame("Custom template", $this->fenom->fetch('custom.tpl', array()));
|
||||
$this->tpl('custom.tpl', 'Custom template 2');
|
||||
$this->assertSame("Custom template", $this->fenom->fetch('custom.tpl', array()));
|
||||
}
|
||||
|
||||
public function testCheckMTime() {
|
||||
public function testCheckMTime()
|
||||
{
|
||||
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
||||
$this->tpl('custom.tpl', 'Custom template');
|
||||
$this->assertSame("Custom template", $this->fenom->fetch('custom.tpl', array()));
|
||||
@ -49,7 +54,8 @@ class FenomTest extends \Fenom\TestCase {
|
||||
$this->assertSame("Custom template (new)", $this->fenom->fetch('custom.tpl', array()));
|
||||
}
|
||||
|
||||
public function testForceCompile() {
|
||||
public function testForceCompile()
|
||||
{
|
||||
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
||||
$this->tpl('custom.tpl', 'Custom template');
|
||||
$this->assertSame("Custom template", $this->fenom->fetch('custom.tpl', array()));
|
||||
@ -57,7 +63,8 @@ class FenomTest extends \Fenom\TestCase {
|
||||
$this->assertSame("Custom template (new)", $this->fenom->fetch('custom.tpl', array()));
|
||||
}
|
||||
|
||||
public function testSetModifier() {
|
||||
public function testSetModifier()
|
||||
{
|
||||
$this->fenom->addModifier("mymod", "myMod");
|
||||
$this->tpl('custom.tpl', 'Custom modifier {$a|mymod}');
|
||||
$this->assertSame("Custom modifier (myMod)Custom(/myMod)", $this->fenom->fetch('custom.tpl', array("a" => "Custom")));
|
||||
@ -66,7 +73,8 @@ class FenomTest extends \Fenom\TestCase {
|
||||
/**
|
||||
* @group add_functions
|
||||
*/
|
||||
public function testSetFunctions() {
|
||||
public function testSetFunctions()
|
||||
{
|
||||
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
||||
$this->fenom->addFunction("myfunc", "myFunc");
|
||||
$this->fenom->addBlockFunction("myblockfunc", "myBlockFunc");
|
||||
@ -76,22 +84,24 @@ class FenomTest extends \Fenom\TestCase {
|
||||
$this->assertSame("Custom function Block:foo:this block1:Block", $this->fenom->fetch('custom.tpl', array()));
|
||||
}
|
||||
|
||||
public function testSetCompilers() {
|
||||
public function testSetCompilers()
|
||||
{
|
||||
$this->fenom->setOptions(Fenom::FORCE_COMPILE);
|
||||
$this->fenom->addCompiler("mycompiler", 'myCompiler');
|
||||
$this->fenom->addBlockCompiler("myblockcompiler", 'myBlockCompilerOpen', 'myBlockCompilerClose', array(
|
||||
'tag' => 'myBlockCompilerTag'
|
||||
));
|
||||
$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("Custom compiler PHP_VERSION: " . PHP_VERSION . " (for bar)", $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()));
|
||||
$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()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerOptions
|
||||
*/
|
||||
public function testOptions($code, $option) {
|
||||
public function testOptions($code, $option)
|
||||
{
|
||||
static $options = array();
|
||||
static $flags = 0;
|
||||
$options[$code] = true;
|
||||
|
@ -1,31 +1,38 @@
|
||||
<?php
|
||||
|
||||
function myMod($str) {
|
||||
return "(myMod)".$str."(/myMod)";
|
||||
function myMod($str)
|
||||
{
|
||||
return "(myMod)" . $str . "(/myMod)";
|
||||
}
|
||||
|
||||
function myFunc($params) {
|
||||
return "MyFunc:".$params["name"];
|
||||
function myFunc($params)
|
||||
{
|
||||
return "MyFunc:" . $params["name"];
|
||||
}
|
||||
|
||||
function myBlockFunc($params, $content) {
|
||||
return "Block:".$params["name"].':'.trim($content).':Block';
|
||||
function myBlockFunc($params, $content)
|
||||
{
|
||||
return "Block:" . $params["name"] . ':' . trim($content) . ':Block';
|
||||
}
|
||||
|
||||
function myCompiler(Fenom\Tokenizer $tokenizer, Fenom\Template $tpl) {
|
||||
function myCompiler(Fenom\Tokenizer $tokenizer, Fenom\Template $tpl)
|
||||
{
|
||||
$p = $tpl->parseParams($tokenizer);
|
||||
return 'echo "PHP_VERSION: ".PHP_VERSION." (for ".'.$p["name"].'.")";';
|
||||
return 'echo "PHP_VERSION: ".PHP_VERSION." (for ".' . $p["name"] . '.")";';
|
||||
}
|
||||
|
||||
function myBlockCompilerOpen(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope) {
|
||||
function myBlockCompilerOpen(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope)
|
||||
{
|
||||
return myCompiler($tokenizer, $scope->tpl);
|
||||
}
|
||||
|
||||
function myBlockCompilerClose(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope) {
|
||||
function myBlockCompilerClose(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope)
|
||||
{
|
||||
return 'echo "End of compiler";';
|
||||
}
|
||||
|
||||
function myBlockCompilerTag(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope) {
|
||||
function myBlockCompilerTag(Fenom\Tokenizer $tokenizer, Fenom\Scope $scope)
|
||||
{
|
||||
$p = $scope->tpl->parseParams($tokenizer);
|
||||
return 'echo "Tag ".'.$p["name"].'." of compiler";';
|
||||
return 'echo "Tag ".' . $p["name"] . '." of compiler";';
|
||||
}
|
Loading…
Reference in New Issue
Block a user