Dev accessor. Add ~~ operator. ++Docs. ++Tests

This commit is contained in:
bzick 2014-10-05 20:37:30 +04:00
parent af7546a8ec
commit e55402c2f4
10 changed files with 436 additions and 274 deletions

View File

@ -127,11 +127,13 @@ Fenom поддерживает префиксные и постфиксные о
* `--$a` - префиксный декремент, уменьшает $a на единицу, затем возвращает значение $a.
* `$a--` - постфиксный декремент, возвращает значение $a, затем уменьшает $a на единицу.
### Строковый оператор
### Строковые операторы
Оператор конкатенации `~` возвращает строку, представляющую собой соединение левого и правого аргумента.
`$a ~ $b` - возвращает результат объединения сток `$a` и `$b`
`$a ~~ $b` - возвращает результат объединения сток `$a` и `$b` через пробел
`$a ~= $b` - присвоение с объединением
### Тернарные операторы

View File

@ -81,25 +81,31 @@
Безименная системная переменная начинается с `$.` и предоставляет доступ к глобальным системным переменным и системной информации:
* `$.get` — `$_GET`.
* `$.post` — `$_POST`.
* `$.cookie` — `$_COOKIE`.
* `$.session` — `$_SESSION`.
* `$.globals` — `$GLOBALS`.
* `$.request` — `$_REQUEST`.
* `$.files` — `$_FILES`.
* `$.server` — `$_SERVER`.
* `$.env` — `$_ENV`.
* `$.env` — массив `$_ENV`.
* `$.get` — массив `$_GET`.
* `$.post` — массив `$_POST`.
* `$.files` — массив `$_FILES`.
* `$.cookie` — массив `$_COOKIE`.
* `$.server` — массив `$_SERVER`.
* `$.session` — массив `$_SESSION`.
* `$.globals` — массив `$GLOBALS`.
* `$.request` — массив `$_REQUEST`.
* `$.tpl.name` возвращает текущее название шаблона.
* `$.tpl.schema` возвращает код провайдера шаблона.
* `$.tpl.basename` возвращает текущее название шаблона без схемы.
* `$.tpl.scm` возвращает схему шаблона.
* `$.tpl.options` возвращает параметры шбалона в виде целого числа.
* `$.tpl.depends` возвращает массив шаблонов на которые ссылается текущий шаблон.
* `$.tpl.time` возвращает штамп времени когда шаблон последний раз менялся
* `$.version` возвращает версию Fenom.
* `$.const` обращение к PHP константе: `$.const.PHP_EOL` .
```smarty
{if $.get.debug? && $.const.DEBUG}
...
{/if}
```
* `$.const.*` обращение к PHP константе: `$.const.PHP_EOL` обращение к константе `PHP_EOL`. Поддерживается пространство имен
которое разделяется через точку: `$.const.Storage.FS::DIR_SEPARATOR` обращение к PHP константе `Storage\FS::DIR_SEPARATOR`
если такой констатнты нет будет взята константа `Storage\FS\DIR_SEPARATOR`.
* `$.php.*` обращение к статическомому методу. `$.php.Storage.FS::put($filename, $data)` обращение к методу `Storage\FS::put($filename, $data)`.
`$.php.Storage.FS.put($filename, $data)` `Storage\FS\put($filename, $data)`
* `$.tag.*` обращение к тегу. `$.tag.mailto($filename, $data)` {mailto ""}.
* `$.func.*`
* `$.fetch($name, $values)`
* `$.macro` `$.macro.math.plus` `$.macro.math.plus(...)`
## Скалярные значения
@ -307,7 +313,7 @@ NULL - это отсутствие присутствия, а FALSE - прису
Все сущности шаблона можно разжелить на две группы:
* заполнитель (placeholder) — вывод переменной в шаблоне, например `{$name}`
* тег — конструкция выполняющаяя некоторые действия, выглядит как именованный заполнитель (placeholder), например `{include $name}`
* тег — конструкция, выполняющаяя некоторые действия, которая выглядит как именованный заполнитель (placeholder), например `{include $name}`
Теги так же можно разделить на две группы:
@ -316,6 +322,10 @@ NULL - это отсутствие присутствия, а FALSE - прису
* Компиляторы. В отличии от функций компиляторы вызываются во время компиляции шаблона и возвращают PHP код, который описывает некоторое действие.
Компиляторы и формируют основные конструкции типа `if`, `foreach` и т.д.
```
{set $a = $.func.mailto($email)}
```
### Игнорирование кода
В шаблонизаторе Fenom используются фигурные скобки для отделения HTML от кода Fenom.

View File

@ -17,7 +17,7 @@ use Fenom\Template;
*/
class Fenom
{
const VERSION = '2.0';
const VERSION = '2.4';
/* Actions */
const INLINE_COMPILER = 1;
const BLOCK_COMPILER = 5;
@ -81,6 +81,11 @@ class Fenom
*/
public $tag_filters = array();
/**
* @var string[]
*/
public $call_filters = array();
/**
* @var callable[]
*/
@ -340,6 +345,24 @@ class Fenom
'third' => '!(%s %% 3)'
);
protected $_accessors = array(
'get' => 'Fenom\Accessor::getVar',
'env' => 'Fenom\Accessor::getVar',
'post' => 'Fenom\Accessor::getVar',
'request' => 'Fenom\Accessor::getVar',
'cookie' => 'Fenom\Accessor::getVar',
'globals' => 'Fenom\Accessor::getVar',
'server' => 'Fenom\Accessor::getVar',
'session' => 'Fenom\Accessor::getVar',
'files' => 'Fenom\Accessor::getVar',
'tpl' => 'Fenom\Accessor::tpl',
'version' => 'Fenom\Accessor::version',
'const' => 'Fenom\Accessor::constant',
'php' => 'Fenom\Accessor::php',
'tag' => 'Fenom\Accessor::Tag',
'fetch' => 'Fenom\Accessor::Fetch',
);
/**
* Just factory
*
@ -510,12 +533,7 @@ 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,
@ -772,6 +790,53 @@ class Fenom
return $this->_options;
}
/**
* Add global accessor ($.)
* @param string $name
* @param callable $parser
* @return Fenom
*/
public function addAccessor($name, $parser)
{
$this->_accessors[$name] = $parser;
return $this;
}
/**
* Remove accessor
* @param string $name
* @return Fenom
*/
public function removeAccessor($name)
{
unset($this->_accessors[$name]);
return $this;
}
/**
* Get an accessor
* @param string $name
* @return callable
*/
public function getAccessor($name) {
if(isset($this->_accessors[$name])) {
return $this->_accessors[$name];
} else {
return false;
}
}
/**
* Add filter for $.php accessor.
* Uses glob syntax.
* @param string $pattern
* @return $this
*/
public function addCallFilter($pattern) {
$this->call_filters[] = $pattern;
return $this;
}
/**
* @param bool|string $scm
* @return Fenom\ProviderInterface

113
src/Fenom/Accessor.php Normal file
View File

@ -0,0 +1,113 @@
<?php
/*
* This file is part of Fenom.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the license.md
* file that was distributed with this source code.
*/
namespace Fenom;
use Fenom\Error\UnexpectedTokenException;
/**
* Class Accessor
* @package Fenom
*/
class Accessor {
public static $vars = array(
'get' => '$_GET',
'post' => '$_POST',
'session' => '$_SESSION',
'cookie' => '$_COOKIE',
'request' => '$_REQUEST',
'files' => '$_FILES',
'globals' => '$GLOBALS',
'server' => '$_SERVER',
'env' => '$_ENV'
);
/**
* Accessor for global variables
* @param Tokenizer $tokens
* @param Template $tpl
*/
public static function getVar(Tokenizer $tokens, Template $tpl) {
$name = $tokens->prev[Tokenizer::TEXT];
if(isset(self::$vars[$name])) {
$var = $tpl->parseVariable($tokens, self::$vars[$name]);
return "(isset($var) ? $var : null)";
} else {
throw new UnexpectedTokenException($tokens->back());
}
}
/**
* Accessor for template information
* @param Tokenizer $tokens
*/
public static function tpl(Tokenizer $tokens) {
$method = $tokens->skip('.')->need(T_STRING)->getAndNext();
if(method_exists('Fenom\Render', 'get'.$method)) {
return '$tpl->get'.ucfirst($method).'()';
} else {
throw new UnexpectedTokenException($tokens->back());
}
}
public static function version() {
return 'Fenom::VERSION';
}
/**
* @param Tokenizer $tokens
* @return string
*/
public static function constant(Tokenizer $tokens) {
$const = [$tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()];
while($tokens->is('.')) {
$const[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
}
$const = implode('\\', $const);
if($tokens->is(T_DOUBLE_COLON)) {
$const .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
}
return '@constant('.var_export($const, true).')';
}
/**
* @param Tokenizer $tokens
* @param Template $tpl
* @return string
*/
public static function php(Tokenizer $tokens, Template $tpl) {
$callable = [$tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext()];
while($tokens->is('.')) {
$callable[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
}
$callable = implode('\\', $callable);
if($tokens->is(T_DOUBLE_COLON)) {
$callable .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
}
if(!is_callable($callable)) {
throw new \LogicException("PHP method ".str_replace('\\', '.', $callable).' does not exists.');
}
if($tokens->is('(')) {
$arguments = 'array'.$tpl->parseArgs($tokens).'';
} else {
$arguments = 'array()';
}
return 'call_user_func_array('.var_export($callable, true).', '.$arguments.')';
}
public static function tag(Tokenizer $tokens, Template $tpl) {
$tag = $tokens->get(Tokenizer::MACRO_STRING);
$info = $tpl->getStorage()->getTag($tag, $tpl);
if($info['type'] !== \Fenom::INLINE_FUNCTION) {
throw new \LogicException("Only inline functions allowed in accessor");
}
}
}

View File

@ -90,8 +90,7 @@ class Render extends \ArrayObject
$this->_time = $props["time"];
$this->_depends = $props["depends"];
$this->_macros = $props["macros"];
// $this->_blocks = $props["blocks"];
$this->_code = $code;
$this->_code = $code;
}
/**
@ -249,19 +248,6 @@ class Render extends \ArrayObject
public function __get($name)
{
if ($name == 'info') {
return array(
'name' => $this->_name,
'schema' => $this->_scm,
'time' => $this->_time
);
} else {
return null;
}
}
public function __isset($name)
{
return $name == 'info';
return $this->$name = null;
}
}

View File

@ -268,7 +268,7 @@ class Template extends Render
throw new CompileException("Unclosed tag" . (count($_names) > 1 ? "s" : "") . ": " . implode(
", ",
$_names
), 0, 1, $this->_name, $scope->line); // $scope already defined there!
), 0, 1, $this->_name, $scope->line); // for PHPStorm: $scope already defined there!
}
$this->_src = ""; // cleanup
if ($this->_post) {
@ -662,7 +662,7 @@ class Template extends Render
// parse term
$term = $this->parseTerm($tokens, $var); // term of the expression
if ($term !== false) {
if ($this->_options & Fenom::FORCE_VERIFY) {
if ($var && ($this->_options & Fenom::FORCE_VERIFY)) {
$term = '(isset(' . $term . ') ? ' . $term . ' : null)';
$var = false;
}
@ -728,6 +728,10 @@ class Template extends Render
if ($tokens->is(T_LNUMBER, T_DNUMBER)) {
$concat[] = "strval(" . $this->parseTerm($tokens) . ")";
} else {
if($tokens->is('~')) {
$tokens->next();
$concat[] = " ";
}
if(!$concat[] = $this->parseTerm($tokens)) {
throw new UnexpectedTokenException($tokens);
}
@ -788,7 +792,8 @@ class Template extends Render
}
return $code;
} elseif ($tokens->is('$')) {
$var = $this->parseAccessor($tokens, $is_var);
$is_var = false;
$var = $this->parseAccessor($tokens);
return $unary . $var;
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
return $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
@ -913,44 +918,18 @@ class Template extends Render
/**
* Parse accessor
* @param Tokenizer $tokens
* @return string
*/
public function parseAccessor(Tokenizer $tokens, &$is_var)
public function parseAccessor(Tokenizer $tokens)
{
$is_var = false;
$vars = array(
'get' => '$_GET',
'post' => '$_POST',
'session' => '$_SESSION',
'cookie' => '$_COOKIE',
'request' => '$_REQUEST',
'files' => '$_FILES',
'globals' => '$GLOBALS',
'server' => '$_SERVER',
'env' => '$_ENV',
'tpl' => '$tpl->info'
);
if ($this->_options & Fenom::DENY_ACCESSOR) {
throw new \LogicException("Accessor are disabled");
$accessor = $tokens->need('$')->next()->need('.')->next()->current();
$callback = $this->getStorage()->getAccessor($accessor);
if($callback) {
return call_user_func($callback, $tokens->next(), $this);
} else {
throw new \RuntimeException("Unknown accessor '$accessor'");
}
$key = $tokens->need('$')->next()->need('.')->next()->current();
$tokens->next();
if (isset($vars[$key])) {
$is_var = true;
return $this->parseVariable($tokens, $vars[$key]);
}
switch ($key) {
case 'const':
$tokens->need('.')->next();
$var = '@constant(' . var_export($this->parseName($tokens), true) . ')';
break;
case 'version':
$var = '\Fenom::VERSION';
break;
default:
throw new UnexpectedTokenException($tokens->back());
}
return $var;
}
/**

View File

@ -11,17 +11,6 @@ namespace Fenom;
use Fenom\Error\UnexpectedTokenException;
/**
* 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);
/**
* for PHP <5.5 compatible
*/
defined('T_YIELD') || define('T_YIELD', 267);
/**
* Each token have structure
* - Token (constant T_* or text)
@ -93,154 +82,62 @@ class Tokenizer
*/
public 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_USE => 1,
\T_VAR => 1,
\T_WHILE => 1,
\T_YIELD => 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, 341 /* 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, 355 /* T_TRAIT */ => 1, 365 /* T_TRAIT_C */ => 1,
\T_TRY => 1, \T_UNSET => 1, \T_USE => 1, \T_VAR => 1,
\T_WHILE => 1, 267 /* T_YIELD */ => 1
),
self::MACRO_INCDEC => array(
\T_INC => 1,
\T_DEC => 1
\T_INC => 1, \T_DEC => 1
),
self::MACRO_UNARY => array(
"!" => 1,
"~" => 1,
"-" => 1
"!" => 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,
"+" => 1,
"-" => 1,
"*" => 1,
"/" => 1,
">" => 1,
"<" => 1,
"^" => 1,
"%" => 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_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
"+" => 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_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_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,

View File

@ -276,9 +276,13 @@ class TestCase extends \PHPUnit_Framework_TestCase
}
}
const HELPER_CONSTANT = 'helper.const';
class Helper
{
const CONSTANT = "helper.class.const";
public $word = 'helper';
public function __construct($word)
@ -306,3 +310,7 @@ class Helper
}
}
function helper_func($string, $pad = 10) {
return str_pad($string, $pad, ".");
}

View File

@ -0,0 +1,144 @@
<?php
namespace Fenom;
class AccessorTest extends TestCase
{
public static function providerGetVar()
{
return array(
array("get"),
array("post"),
array("cookie"),
array("request"),
array("files"),
array("globals"),
array("server"),
array("session"),
array("env"),
);
}
/**
* @dataProvider providerGetVar
* @backupGlobals
* @param string $var
*/
public function testGetVar($var)
{
$_GET['one'] = 'get1';
$_POST['one'] = 'post1';
$_COOKIE['one'] = 'cookie1';
$_REQUEST['one'] = 'request1';
$_FILES['one'] = 'files1';
$GLOBALS['one'] = 'globals1';
$_SERVER['one'] = 'server1';
$_SESSION['one'] = 'session1';
$_ENV['one'] = 'env1';
$this->exec('{$.'.$var.'.one}', self::getVars(), "{$var}1");
$this->exec('{$.'.$var.'.undefined}', self::getVars(), "");
}
public static function providerTpl()
{
return array(
array("name"),
array("scm"),
array("basename"),
array("options"),
array("time"),
);
}
/**
* @dataProvider providerTpl
* @param string $name
*/
public function testTpl($name)
{
$this->tpl("accessor.tpl", '{$.tpl.'.$name.'}');
$tpl = $this->fenom->setOptions(\Fenom::FORCE_VERIFY)->getTemplate('accessor.tpl');
$this->assertSame(strval($tpl->{"get$name"}()), $tpl->fetch(self::getVars()));
}
public function testVersion()
{
$this->assertRender('{$.version}', \Fenom::VERSION);
}
public static function providerConst()
{
return array(
array("$.const.PHP_VERSION_ID", PHP_VERSION_ID),
array('$.const.UNDEFINED', ''),
array("$.const.FENOM_RESOURCES", FENOM_RESOURCES),
array("$.const.Fenom.HELPER_CONSTANT", HELPER_CONSTANT),
array("$.const.Fenom.UNDEFINED", ''),
array("$.const.Fenom::VERSION", \Fenom::VERSION),
array("$.const.Fenom::UNDEFINED", ''),
array("$.const.Fenom.Helper::CONSTANT", Helper::CONSTANT),
array("$.const.Fenom.Helper::UNDEFINED", ''),
);
}
/**
* @dataProvider providerConst
* @param $tpl
* @param $value
* @group const
*/
public function testConst($tpl, $value)
{
$this->assertRender('{'.$tpl.'}', strval($value));
}
public static function providerPHP() {
return array(
array('$.php.strrev("string")', strrev("string")),
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12)),
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string")),
);
}
/**
* @dataProvider providerPHP
* @group php
*/
public function testPHP($tpl, $result) {
$this->assertRender('{'.$tpl.'}', $result);
}
public static function providerAccessor()
{
return array(
array('{$.get.one}', 'get1'),
array('{$.post.one}', 'post1'),
array('{$.request.one}', 'request1'),
array('{$.session.one}', 'session1'),
array('{$.files.one}', 'files1'),
array('{$.globals.one}', 'globals1'),
array('{$.cookie.one}', 'cookie1'),
array('{$.server.one}', 'server1'),
array('{"string"|append:"_":$.get.one}', 'string_get1'),
array('{$.get.one?}', '1'),
array('{$.get.one is set}', '1'),
array('{$.get.two is empty}', '1'),
array('{$.version}', \Fenom::VERSION),
array('{$.tpl.name}', 'runtime.tpl'),
array('{$.tpl.time}', '0'),
array('{$.tpl.schema}', ''),
);
}
public static function providerAccessorInvalid()
{
return array(
array('{$.nope.one}', 'Fenom\Error\CompileException', "Unexpected token 'nope'"),
array('{$.get.one}', 'Fenom\Error\SecurityException', 'Accessor are disabled', \Fenom::DENY_ACCESSOR),
);
}
}

View File

@ -17,15 +17,7 @@ class TemplateTest extends TestCase
{
parent::setUp();
$this->tpl('welcome.tpl', '<b>Welcome, {$username} ({$email})</b>');
$_GET['one'] = 'get1';
$_POST['one'] = 'post1';
$_REQUEST['one'] = 'request1';
$_FILES['one'] = 'files1';
$_SERVER['one'] = 'server1';
$_SESSION['one'] = 'session1';
$GLOBALS['one'] = 'globals1';
$_ENV['one'] = 'env1';
$_COOKIE['one'] = 'cookie1';
}
public static function providerVars()
@ -1217,40 +1209,6 @@ class TemplateTest extends TestCase
);
}
public static function providerAccessor()
{
return array(
array('{$.get.one}', 'get1'),
array('{$.post.one}', 'post1'),
array('{$.request.one}', 'request1'),
array('{$.session.one}', 'session1'),
array('{$.files.one}', 'files1'),
array('{$.globals.one}', 'globals1'),
array('{$.cookie.one}', 'cookie1'),
array('{$.server.one}', 'server1'),
array('{$.const.PHP_EOL}', PHP_EOL),
array('{$.const.MY}', ''),
array('{$.version}', Fenom::VERSION),
array('{"string"|append:"_":$.get.one}', 'string_get1'),
array('{$.get.one?}', '1'),
array('{$.get.one is set}', '1'),
array('{$.get.two is empty}', '1'),
array('{$.version}', Fenom::VERSION),
array('{$.tpl?}', '1'),
array('{$.tpl.name}', 'runtime.tpl'),
array('{$.tpl.time}', '0'),
array('{$.tpl.schema}', ''),
);
}
public static function providerAccessorInvalid()
{
return array(
array('{$.nope.one}', 'Fenom\Error\CompileException', "Unexpected token 'nope'"),
array('{$.get.one}', 'Fenom\Error\SecurityException', 'Accessor are disabled', Fenom::DENY_ACCESSOR),
);
}
public function providerStatic()
{
return array(
@ -1622,19 +1580,19 @@ class TemplateTest extends TestCase
* @group accessor
* @dataProvider providerAccessor
*/
public function testAccessor($code, $result)
{
$this->exec($code, self::getVars(), $result);
}
// public function testAccessor($code, $result)
// {
// $this->exec($code, self::getVars(), $result);
// }
/**
* @group accessor
* @dataProvider providerAccessorInvalid
*/
public function testAccessorInvalid($code, $exception, $message, $options = 0)
{
$this->execError($code, $exception, $message, $options);
}
// public function testAccessorInvalid($code, $exception, $message, $options = 0)
// {
// $this->execError($code, $exception, $message, $options);
// }
/**
* @group static