mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Done accessor
This commit is contained in:
parent
4b65e80312
commit
0091b17c8a
@ -48,5 +48,9 @@ $fenom->setOptions(array(
|
||||
$fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::FORCE_INCLUDE);
|
||||
```
|
||||
|
||||
```php
|
||||
$fenom->addCallFilter('View\Widget\*::get*')
|
||||
```
|
||||
|
||||
**Замечание**
|
||||
По умолчанию все параметры деактивированы.
|
||||
|
@ -97,15 +97,12 @@
|
||||
* `$.tpl.depends` возвращает массив шаблонов на которые ссылается текущий шаблон.
|
||||
* `$.tpl.time` возвращает штамп времени когда шаблон последний раз менялся
|
||||
* `$.version` возвращает версию Fenom.
|
||||
* `$.const.*` обращение к PHP константе: `$.const.PHP_EOL` обращение к константе `PHP_EOL`. Поддерживается пространство имен
|
||||
* `$.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` обращение к статическомому методу. `$.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(...)`
|
||||
|
||||
## Скалярные значения
|
||||
|
||||
@ -116,7 +113,21 @@
|
||||
#### Двойные кавычки
|
||||
|
||||
Если строка заключена в двойные кавычки `"`, Fenom распознает большее количество управляющих последовательностей для специальных символов:
|
||||
`\n`, `\r`, `\t`, `\v`, `\e`, `\f`, `\\`, `\$`, `\"`, `\[0-7]{1,3}`, `\x[0-9A-Fa-f]{1,2}`.
|
||||
|
||||
| Последовательность | Значение |
|
||||
|---------------------|----------|
|
||||
| `\n` | новая строка (LF или 0x0A (10) в ASCII)
|
||||
| `\r` | возврат каретки (CR или 0x0D (13) в ASCII)
|
||||
| `\t` | горизонтальная табуляция (HT или 0x09 (9) в ASCII)
|
||||
| `\v` | вертикальная табуляция (VT или 0x0B (11) в ASCII)
|
||||
<!--| `\e` | escape-знак (ESC или 0x1B (27) в ASCII) (с версии PHP 5.4.0) -->
|
||||
| `\f` | подача страницы (FF или 0x0C (12) в ASCII)
|
||||
| `\\` | обратная косая черта
|
||||
| `\$` | знак доллара
|
||||
| `\"` | двойная кавычка
|
||||
| `\[0-7]{1,3}` | последовательность символов, соответствующая регулярному выражению символа в восьмеричной системе счисления
|
||||
| `\x[0-9A-Fa-f]{1,2}`| последовательность символов, соответствующая регулярному выражению символа в шестнадцатеричной системе счисления
|
||||
|
||||
Но самым важным свойством строк в двойных кавычках является обработка переменных.
|
||||
Существует два типа синтаксиса: простой и сложный. Простой синтаксис более легок и удобен.
|
||||
Он дает возможность обработки переменной, значения массива или свойства объекта с минимумом усилий.
|
||||
|
@ -620,12 +620,8 @@ 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,
|
||||
@ -1034,7 +1030,7 @@ class Fenom
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush internal memory template cache
|
||||
* Flush internal template in-memory-cache
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
@ -1047,6 +1043,7 @@ class Fenom
|
||||
public function clearAllCompiles()
|
||||
{
|
||||
\Fenom\Provider::clean($this->_compile_dir);
|
||||
$this->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,8 @@ class Accessor {
|
||||
* @param Tokenizer $tokens
|
||||
* @param Template $tpl
|
||||
*/
|
||||
public static function getVar(Tokenizer $tokens, 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]);
|
||||
@ -47,7 +48,8 @@ class Accessor {
|
||||
* Accessor for template information
|
||||
* @param Tokenizer $tokens
|
||||
*/
|
||||
public static function tpl(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).'()';
|
||||
@ -56,7 +58,8 @@ class Accessor {
|
||||
}
|
||||
}
|
||||
|
||||
public static function version() {
|
||||
public static function version()
|
||||
{
|
||||
return 'Fenom::VERSION';
|
||||
}
|
||||
|
||||
@ -64,7 +67,8 @@ class Accessor {
|
||||
* @param Tokenizer $tokens
|
||||
* @return string
|
||||
*/
|
||||
public static function constant(Tokenizer $tokens) {
|
||||
public static function constant(Tokenizer $tokens)
|
||||
{
|
||||
$const = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext());
|
||||
while($tokens->is('.')) {
|
||||
$const[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
@ -82,7 +86,8 @@ class Accessor {
|
||||
* @param Template $tpl
|
||||
* @return string
|
||||
*/
|
||||
public static function php(Tokenizer $tokens, Template $tpl) {
|
||||
public static function php(Tokenizer $tokens, Template $tpl)
|
||||
{
|
||||
$callable = array($tokens->skip('.')->need(Tokenizer::MACRO_STRING)->getAndNext());
|
||||
while($tokens->is('.')) {
|
||||
$callable[] = $tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
@ -91,8 +96,16 @@ class Accessor {
|
||||
if($tokens->is(T_DOUBLE_COLON)) {
|
||||
$callable .= '::'.$tokens->next()->need(Tokenizer::MACRO_STRING)->getAndNext();
|
||||
}
|
||||
$call_filter = $tpl->getStorage()->call_filters;
|
||||
if($call_filter) {
|
||||
foreach($call_filter as $filter) {
|
||||
if(!fnmatch(addslashes($filter), $callable)) {
|
||||
throw new \LogicException("Callback ".str_replace('\\', '.', $callable)." is not available by settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!is_callable($callable)) {
|
||||
throw new \LogicException("PHP method ".str_replace('\\', '.', $callable).' does not exists.');
|
||||
throw new \RuntimeException("PHP method ".str_replace('\\', '.', $callable).' does not exists.');
|
||||
}
|
||||
if($tokens->is('(')) {
|
||||
$arguments = 'array'.$tpl->parseArgs($tokens).'';
|
||||
@ -103,11 +116,28 @@ class Accessor {
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
/**
|
||||
* Accessor {$.fetch(...)}
|
||||
* @param Tokenizer $tokens
|
||||
* @param Template $tpl
|
||||
* @return string
|
||||
*/
|
||||
public static function fetch(Tokenizer $tokens, Template $tpl)
|
||||
{
|
||||
$tokens->skip('(');
|
||||
$name = $tpl->parsePlainArg($tokens, $static);
|
||||
if($static) {
|
||||
if(!$tpl->getStorage()->templateExists($static)) {
|
||||
throw new \RuntimeException("Template $static not found");
|
||||
}
|
||||
}
|
||||
if($tokens->is(',')) {
|
||||
$tokens->skip()->need('[');
|
||||
$vars = $tpl->parseArray($tokens) . ' + $var';
|
||||
} else {
|
||||
$vars = '$var';
|
||||
}
|
||||
$tokens->skip(')');
|
||||
return '$tpl->getStorage()->fetch('.$name.', '.$vars.')';
|
||||
}
|
||||
}
|
@ -241,7 +241,7 @@ class Compiler
|
||||
*/
|
||||
public static function forOpen(Tokenizer $tokens, Tag $scope)
|
||||
{
|
||||
$p = array(
|
||||
$p = array(
|
||||
"index" => false,
|
||||
"first" => false,
|
||||
"last" => false,
|
||||
|
@ -161,13 +161,13 @@ 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, array $vars = array(), $debug = false)
|
||||
{
|
||||
$template = $this->fenom->compileCode($tpl);
|
||||
if ($debug) {
|
||||
print_r("\nDEBUG $tpl:\n" . $template->getBody());
|
||||
}
|
||||
$this->assertSame($result, $template->fetch($this->values));
|
||||
$this->assertSame($result, $template->fetch($vars + $this->values));
|
||||
return $template;
|
||||
}
|
||||
|
||||
|
@ -97,8 +97,23 @@ class AccessorTest extends TestCase
|
||||
public static function providerPHP() {
|
||||
return array(
|
||||
array('$.php.strrev("string")', strrev("string")),
|
||||
array('$.php.strrev("string")', strrev("string"), 'str*'),
|
||||
array('$.php.strrev("string")', strrev("string"), 'strrev'),
|
||||
array('$.php.get_current_user', get_current_user()),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12)),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), 'Fenom\\*'),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), 'Fenom\helper_func'),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), '*helper_func'),
|
||||
array('$.php.Fenom.helper_func("string", 12)', helper_func("string", 12), '*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string")),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\TestCase*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\TestCase::*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\*::dots'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\*::*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), 'Fenom\TestCase::dots'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), '*::dots'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', TestCase::dots("string"), '*'),
|
||||
);
|
||||
}
|
||||
|
||||
@ -106,10 +121,45 @@ class AccessorTest extends TestCase
|
||||
* @dataProvider providerPHP
|
||||
* @group php
|
||||
*/
|
||||
public function testPHP($tpl, $result) {
|
||||
public function testPHP($tpl, $result, $mask = null) {
|
||||
if($mask) {
|
||||
$this->fenom->addCallFilter($mask);
|
||||
}
|
||||
$this->assertRender('{'.$tpl.'}', $result);
|
||||
}
|
||||
|
||||
public static function providerPHPInvalid() {
|
||||
return array(
|
||||
array('$.php.aaa("string")', 'Fenom\Error\CompileException', 'PHP method aaa does not exists'),
|
||||
array('$.php.strrev("string")', 'Fenom\Error\SecurityException', 'Callback strrev is not available by settings', 'strrevZ'),
|
||||
array('$.php.strrev("string")', 'Fenom\Error\SecurityException', 'Callback strrev is not available by settings', 'str*Z'),
|
||||
array('$.php.strrev("string")', 'Fenom\Error\SecurityException', 'Callback strrev is not available by settings', '*Z'),
|
||||
array('$.php.Fenom.aaa("string")', 'Fenom\Error\CompileException', 'PHP method Fenom.aaa does not exists'),
|
||||
array('$.php.Fenom.helper_func("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.helper_func is not available by settings', 'Reflection\*'),
|
||||
array('$.php.Fenom.helper_func("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.helper_func is not available by settings', 'Fenom\*Z'),
|
||||
array('$.php.Fenom.helper_func("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.helper_func is not available by settings', 'Fenom\*::*'),
|
||||
array('$.php.TestCase::aaa("string")', 'Fenom\Error\CompileException', 'PHP method TestCase::aaa does not exists'),
|
||||
array('$.php.Fenom.TestCase::aaa("string")', 'Fenom\Error\CompileException', 'PHP method Fenom.TestCase::aaa does not exists'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Reflection\*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\*Z'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\*::get*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\TestCase::get*'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', 'Fenom\TestCase::*Z'),
|
||||
array('$.php.Fenom.TestCase::dots("string")', 'Fenom\Error\SecurityException', 'Callback Fenom.TestCase::dots is not available by settings', '*::*Z'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerPHPInvalid
|
||||
* @group php
|
||||
*/
|
||||
public function testPHPInvalid($tpl, $exception, $message, $methods = null) {
|
||||
if($methods) {
|
||||
$this->fenom->addCallFilter($methods);
|
||||
}
|
||||
$this->execError('{'.$tpl.'}', $exception, $message);
|
||||
}
|
||||
|
||||
|
||||
public static function providerAccessor()
|
||||
{
|
||||
@ -133,7 +183,6 @@ class AccessorTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function providerAccessorInvalid()
|
||||
{
|
||||
return array(
|
||||
@ -141,4 +190,41 @@ class AccessorTest extends TestCase
|
||||
array('{$.get.one}', 'Fenom\Error\SecurityException', 'Accessor are disabled', \Fenom::DENY_ACCESSOR),
|
||||
);
|
||||
}
|
||||
|
||||
public static function providerFetch()
|
||||
{
|
||||
return array(
|
||||
array('{$.fetch("welcome.tpl")}'),
|
||||
array('{set $tpl = "welcome.tpl"}{$.fetch($tpl)}'),
|
||||
array('{$.fetch("welcome.tpl", ["username" => "Bzick", "email" => "bzick@dev.null"])}'),
|
||||
array('{set $tpl = "welcome.tpl"}{$.fetch($tpl, ["username" => "Bzick", "email" => "bzick@dev.null"])}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group fetch
|
||||
* @dataProvider providerFetch
|
||||
*/
|
||||
public function testFetch($code)
|
||||
{
|
||||
$this->tpl('welcome.tpl', '<b>Welcome, {$username} ({$email})</b>');
|
||||
$values = array('username' => 'Bzick', 'email' => 'bzick@dev.null');
|
||||
$this->assertRender($code, $this->fenom->fetch('welcome.tpl', $values), $values);
|
||||
}
|
||||
|
||||
public static function providerFetchInvalid()
|
||||
{
|
||||
return array(
|
||||
array('{$.fetch("welcome_.tpl")}', 'Fenom\Error\CompileException', "Template welcome_.tpl not found"),
|
||||
array('{$.fetch("welcome_.tpl", [])}', 'Fenom\Error\CompileException', "Template welcome_.tpl not found"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group fetchInvalid
|
||||
* @dataProvider providerFetchInvalid
|
||||
*/
|
||||
public function testFetchInvalidTpl($tpl, $exception, $message) {
|
||||
$this->execError($tpl, $exception, $message);
|
||||
}
|
||||
}
|
29
tests/cases/Fenom/SandboxTest.php
Normal file
29
tests/cases/Fenom/SandboxTest.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Fenom;
|
||||
|
||||
|
||||
class SandboxTest extends TestCase {
|
||||
|
||||
public function test()
|
||||
{
|
||||
|
||||
|
||||
// $this->assertEquals([1, 2, 4, "as" => 767, "df" => ["qert"]], [1, 2, 4, "as" => 767, "df" => ["qet"]]);
|
||||
// $this->fenom->addBlockCompiler('php', 'Fenom\Compiler::nope', function ($tokens, Tag $tag) {
|
||||
// return '<?php ' . $tag->cutContent();
|
||||
// });
|
||||
// $this->tpl('welcome.tpl', '{$a}');
|
||||
// try {
|
||||
// var_dump($this->fenom->compileCode('{$.fetch("welcome.tpl", ["a" => 1])}')->getBody());
|
||||
// } catch (\Exception $e) {
|
||||
// print_r($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||
// while ($e->getPrevious()) {
|
||||
// $e = $e->getPrevious();
|
||||
// print_r("\n\n" . $e->getMessage() . " in {$e->getFile()}:{$e->getLine()}\n" . $e->getTraceAsString());
|
||||
// }
|
||||
// }
|
||||
// exit;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user