Merge branch 'master' into develop
This commit is contained in:
commit
9670f0433a
|
@ -1,5 +1,4 @@
|
||||||
service_name: travis-ci
|
service_name: travis-ci
|
||||||
|
|
||||||
src_dir: src
|
|
||||||
coverage_clover: build/logs/clover.xml
|
coverage_clover: build/logs/clover.xml
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,10 @@ php:
|
||||||
- 5.5
|
- 5.5
|
||||||
- 5.6
|
- 5.6
|
||||||
- 7.0
|
- 7.0
|
||||||
|
- 7.1
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- composer update --dev
|
- composer update --dev --quiet
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- phpunit
|
- phpunit
|
||||||
|
|
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,6 +1,21 @@
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
## 2.11.0 (2016-06-09)
|
||||||
|
|
||||||
|
- Added method to get the name of the cache template `$fenom->getCacheName($template_name)`(#231)
|
||||||
|
- Fix bug with before-code in template inheritance (#229)
|
||||||
|
- Added `??` operator.
|
||||||
|
- Improve compile mechanism
|
||||||
|
- ++Docs
|
||||||
|
- ++Test
|
||||||
|
|
||||||
|
## 2.10.0 (2016-05-08)
|
||||||
|
|
||||||
|
- Add tag `{do ...}`
|
||||||
|
- ++Docs
|
||||||
|
- ++Tests
|
||||||
|
|
||||||
## 2.9.0 (2016-05-08)
|
## 2.9.0 (2016-05-08)
|
||||||
|
|
||||||
- Add `$.block`
|
- Add `$.block`
|
||||||
|
|
|
@ -19,7 +19,7 @@ Also if a child template extends a parent template with the `{extends}` tag it m
|
||||||
|
|
||||||
### {use}
|
### {use}
|
||||||
|
|
||||||
Что бы импортировать блоки из другого шаблона используйте тег {use}:
|
Import the blocks defined in another file. Specifying blocks in this template will override those from the other file.
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
{use 'blocks.tpl'} merge blocks from blocks.tpl template
|
{use 'blocks.tpl'} merge blocks from blocks.tpl template
|
||||||
|
@ -31,6 +31,8 @@ Also if a child template extends a parent template with the `{extends}` tag it m
|
||||||
|
|
||||||
### {parent}
|
### {parent}
|
||||||
|
|
||||||
|
Uses the code from the block as defined in the parent.
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
{extends 'parent.tpl'}
|
{extends 'parent.tpl'}
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ Also if a child template extends a parent template with the `{extends}` tag it m
|
||||||
|
|
||||||
### {paste}
|
### {paste}
|
||||||
|
|
||||||
Paste code of any block
|
Pastes the code of any block
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
{block 'b1'}
|
{block 'b1'}
|
||||||
|
@ -65,4 +67,4 @@ Checks if clock exists
|
||||||
{if $.block.header}
|
{if $.block.header}
|
||||||
block header exists
|
block header exists
|
||||||
{/if}
|
{/if}
|
||||||
```
|
```
|
||||||
|
|
|
@ -5,4 +5,5 @@
|
||||||
* [Fenom + Kohana](https://github.com/2bj/kofenom) — Kofenom
|
* [Fenom + Kohana](https://github.com/2bj/kofenom) — Kofenom
|
||||||
* Fenom + Symphony
|
* Fenom + Symphony
|
||||||
* Fenom + Symphony2
|
* Fenom + Symphony2
|
||||||
* Fenom + Zend Framework 2
|
* Fenom + Zend Framework 2
|
||||||
|
* [Fenom + MODX Revolution](https://docs.modx.pro/components/pdotools/parser#Шаблонизатор-Fenom)
|
||||||
|
|
|
@ -141,7 +141,7 @@ $fenom->addAccessor('project', function (Fenom\Tokenizer $tokens) { /* code */ }
|
||||||
## Готовые решения
|
## Готовые решения
|
||||||
|
|
||||||
Орпеделить парсер для глобальной переменной весьма трудозатратно и требует полного понимания как работают парсеры в Fenom.
|
Орпеделить парсер для глобальной переменной весьма трудозатратно и требует полного понимания как работают парсеры в Fenom.
|
||||||
Это не удобно. Поэтому есть несколько предзаготовленных (умных) парсеоров, которые берут рутину на себя, а пользоватею остается указать ключевые параметры.
|
Это не удобно. Поэтому есть несколько предзаготовленных (умных) парсеров, которые берут рутину на себя, а пользователю остается указать ключевые параметры.
|
||||||
|
|
||||||
Умные парсеты добавляются через метод `Fenom::addAccessorSmart(string $name, string $accessor, string $parser)`,
|
Умные парсеты добавляются через метод `Fenom::addAccessorSmart(string $name, string $accessor, string $parser)`,
|
||||||
где `$name` имя глобальной переменной, `$accessor` — параметр к парсеру, `$parser` — предопределенный парсер.
|
где `$name` имя глобальной переменной, `$accessor` — параметр к парсеру, `$parser` — предопределенный парсер.
|
||||||
|
|
|
@ -23,4 +23,7 @@
|
||||||
{if $color|match:"*gr[ae]y"}
|
{if $color|match:"*gr[ae]y"}
|
||||||
какой-то оттенок серого
|
какой-то оттенок серого
|
||||||
{/if}
|
{/if}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Замечание:**
|
||||||
|
максимальная длинна проверяемой строки не должна превышать 4096 символов.
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
|
|
||||||
### `{paste}`
|
### `{paste}`
|
||||||
|
|
||||||
Иставка кода блока в любое место через тег `{paste}`
|
Вставка кода блока в любое место через тег `{paste}`
|
||||||
|
|
||||||
```smarty
|
```smarty
|
||||||
{block 'b1'}
|
{block 'b1'}
|
||||||
|
|
|
@ -5,9 +5,12 @@ require_once __DIR__.'/../tests/tools.php';
|
||||||
|
|
||||||
\Fenom::registerAutoload();
|
\Fenom::registerAutoload();
|
||||||
|
|
||||||
$fenom = Fenom::factory(__DIR__.'/templates', __DIR__.'/../tests/resources/compile');
|
$fenom = Fenom::factory(__DIR__.'/templates', __DIR__.'/compiled');
|
||||||
$fenom->setOptions(Fenom::AUTO_RELOAD);
|
$fenom->setOptions(Fenom::AUTO_RELOAD | Fenom::FORCE_VERIFY | Fenom::FORCE_INCLUDE);
|
||||||
var_dump($fenom->compileCode('{do $object->method()}')->getTemplateCode());
|
//var_dump($fenom->compile("nested.tpl", [])->getTemplateCode());
|
||||||
|
//exit;
|
||||||
|
var_dump($fenom->compile('bug241/recursive.tpl', false)->getBody());
|
||||||
|
//var_dump($fenom->compile('bug249/bread.tpl', false)->getBody());
|
||||||
//var_dump($fenom->compile("bug158/main.tpl", [])->getTemplateCode());
|
//var_dump($fenom->compile("bug158/main.tpl", [])->getTemplateCode());
|
||||||
//var_dump($fenom->display("bug158/main.tpl", []));
|
//var_dump($fenom->display("bug158/main.tpl", []));
|
||||||
// $fenom->getTemplate("problem.tpl");
|
// $fenom->getTemplate("problem.tpl");
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
{if $n < 10}
|
||||||
|
{include 'bug241/recursive.tpl' n=$n - 1}
|
||||||
|
{/if}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{block 'content'}{/block}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1 @@
|
||||||
|
{extends 'bug247/base.tpl'}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{*<div class='bread'>*}
|
||||||
|
{*<ul>*}
|
||||||
|
{*<li><a href='/'>Главная</a><li>*}
|
||||||
|
{*{foreach 1..$arr|length as $counter index=$i first=$first last=$last}*}
|
||||||
|
{*{if !$first}*}
|
||||||
|
{*<li class='delim'>/</li>*}
|
||||||
|
{*<li>{$last}*}
|
||||||
|
{*{if !$last}*}
|
||||||
|
{*<a href='{$arr[$i]['hidden_url']}'>{else}<span>*}
|
||||||
|
{*{/if}*}
|
||||||
|
{*{$arr[$i]['name']}{if !$last}</a>{else}</span>{/if}</li>{/if}*}
|
||||||
|
{*{/foreach}*}
|
||||||
|
{*</ul>*}
|
||||||
|
{*</div>*}
|
||||||
|
|
||||||
|
=== {(1..3)|length} ===
|
||||||
|
|
||||||
|
{foreach 1..3 as $c index=$i first=$first last=$last}
|
||||||
|
{$i}: {$last}
|
||||||
|
{/foreach}
|
||||||
|
|
||||||
|
<div class='bread'>
|
||||||
|
<ul>
|
||||||
|
<li><a href='/'>Главная</a><li>
|
||||||
|
{foreach $arr as $item first=$first last=$last}
|
||||||
|
{if !$first}
|
||||||
|
<li class='delim'>/</li>
|
||||||
|
<li>{$last}
|
||||||
|
{if $last}
|
||||||
|
<span>{$item.name}</span>
|
||||||
|
{else}
|
||||||
|
<a href='{$item.hidden_url}'>{$item.name}</a>
|
||||||
|
{/if}
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
{/foreach}
|
||||||
|
</ul>
|
||||||
|
</div>
|
|
@ -64,6 +64,11 @@ class Fenom
|
||||||
|
|
||||||
public static $charset = "UTF-8";
|
public static $charset = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int maximum length of compiled filename (use sha1 of name if bigger)
|
||||||
|
*/
|
||||||
|
public static $filename_length = 200;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int[] of possible options, as associative array
|
* @var int[] of possible options, as associative array
|
||||||
* @see setOptions
|
* @see setOptions
|
||||||
|
@ -939,9 +944,9 @@ class Fenom
|
||||||
*
|
*
|
||||||
* @return Fenom\Template
|
* @return Fenom\Template
|
||||||
*/
|
*/
|
||||||
public function getRawTemplate()
|
public function getRawTemplate(Template $parent = null)
|
||||||
{
|
{
|
||||||
return new Template($this, $this->_options);
|
return new Template($this, $this->_options, $parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1075,13 +1080,17 @@ class Fenom
|
||||||
if (is_array($tpl)) {
|
if (is_array($tpl)) {
|
||||||
$hash = implode(".", $tpl) . ":" . $options;
|
$hash = implode(".", $tpl) . ":" . $options;
|
||||||
foreach ($tpl as &$t) {
|
foreach ($tpl as &$t) {
|
||||||
$t = str_replace(":", "_", basename($t));
|
$t = urlencode(str_replace(":", "_", basename($t)));
|
||||||
}
|
}
|
||||||
return $this->_compile_id . implode("~", $tpl) . "." . sprintf("%x.%x.php", crc32($hash), strlen($hash));
|
$tpl = implode("~", $tpl);
|
||||||
} else {
|
} else {
|
||||||
$hash = $tpl . ":" . $options;
|
$hash = $tpl . ":" . $options;
|
||||||
return sprintf($this->_compile_id . "%s.%x.%x.php", str_replace(":", "_", basename($tpl)), crc32($hash), strlen($hash));
|
$tpl = urlencode(str_replace(":", "_", basename($tpl)));
|
||||||
}
|
}
|
||||||
|
if($tpl > self::$filename_length) {
|
||||||
|
$tpl = sha1($tpl);
|
||||||
|
}
|
||||||
|
return $this->_compile_id . $tpl . "." . sprintf("%x.%x.php", crc32($hash), strlen($hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,13 +38,24 @@ class Compiler
|
||||||
$p = $tpl->parseParams($tokens);
|
$p = $tpl->parseParams($tokens);
|
||||||
if ($name) {
|
if ($name) {
|
||||||
if ($tpl->getStorage()->getOptions() & \Fenom::FORCE_INCLUDE) {
|
if ($tpl->getStorage()->getOptions() & \Fenom::FORCE_INCLUDE) {
|
||||||
$inc = $tpl->getStorage()->compile($name, false);
|
$_t = $tpl;
|
||||||
$tpl->addDepend($inc);
|
$recursion = false;
|
||||||
$var = $tpl->tmpVar();
|
while($_t->parent) {
|
||||||
if ($p) {
|
if($_t->parent->getName() == $name) { // recursion detected
|
||||||
return $var . ' = $var; $var = ' . self::toArray($p) . ' + $var; ?>' . $inc->getBody() . '<?php $var = ' . $var . '; unset(' . $var . ');';
|
$recursion = true;
|
||||||
} else {
|
}
|
||||||
return $var . ' = $var; ?>' . $inc->getBody() . '<?php $var = ' . $var . '; unset(' . $var . ');';
|
$_t = $_t->parent;
|
||||||
|
}
|
||||||
|
if(!$recursion) {
|
||||||
|
$inc = $tpl->getStorage()->getRawTemplate($tpl);
|
||||||
|
$inc->load($name, true);
|
||||||
|
$tpl->addDepend($inc);
|
||||||
|
$var = $tpl->tmpVar();
|
||||||
|
if ($p) {
|
||||||
|
return $var . ' = $var; $var = ' . self::toArray($p) . ' + $var; ?>' . $inc->getBody() . '<?php $var = ' . $var . '; unset(' . $var . ');';
|
||||||
|
} else {
|
||||||
|
return $var . ' = $var; ?>' . $inc->getBody() . '<?php $var = ' . $var . '; unset(' . $var . ');';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} elseif (!$tpl->getStorage()->templateExists($name)) {
|
} elseif (!$tpl->getStorage()->templateExists($name)) {
|
||||||
throw new \LogicException("Template $name not found");
|
throw new \LogicException("Template $name not found");
|
||||||
|
|
|
@ -90,7 +90,7 @@ class RangeIterator implements \Iterator, \Countable
|
||||||
*/
|
*/
|
||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
return intval(($this->max - $this->min) / $this->step);
|
return intval(($this->max - $this->min + 1) / $this->step);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -237,7 +237,7 @@ class Tag extends \ArrayObject
|
||||||
*/
|
*/
|
||||||
public function cutContent()
|
public function cutContent()
|
||||||
{
|
{
|
||||||
$content = substr($this->_body, $this->_offset + 1);
|
$content = substr($this->_body, $this->_offset);
|
||||||
$this->_body = substr($this->_body, 0, $this->_offset);
|
$this->_body = substr($this->_body, 0, $this->_offset);
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
namespace Fenom;
|
namespace Fenom;
|
||||||
|
|
||||||
use Fenom;
|
use Fenom;
|
||||||
use Fenom\Error\UnexpectedTokenException;
|
|
||||||
use Fenom\Error\CompileException;
|
use Fenom\Error\CompileException;
|
||||||
use Fenom\Error\InvalidUsageException;
|
use Fenom\Error\InvalidUsageException;
|
||||||
use Fenom\Error\SecurityException;
|
use Fenom\Error\SecurityException;
|
||||||
use Fenom\Error\TokenizeException;
|
use Fenom\Error\TokenizeException;
|
||||||
|
use Fenom\Error\UnexpectedTokenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template compiler
|
* Template compiler
|
||||||
|
@ -27,6 +27,12 @@ class Template extends Render
|
||||||
const VAR_NAME = '$var';
|
const VAR_NAME = '$var';
|
||||||
const TPL_NAME = '$tpl';
|
const TPL_NAME = '$tpl';
|
||||||
|
|
||||||
|
const COMPILE_STAGE_LOADED = 1;
|
||||||
|
const COMPILE_STAGE_PRE_FILTERED = 2;
|
||||||
|
const COMPILE_STAGE_PARSED = 3;
|
||||||
|
const COMPILE_STAGE_PROCESSED = 4;
|
||||||
|
const COMPILE_STAGE_POST_FILTERED = 5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable array parser.
|
* Disable array parser.
|
||||||
*/
|
*/
|
||||||
|
@ -75,11 +81,18 @@ class Template extends Render
|
||||||
|
|
||||||
public $extend_body = false;
|
public $extend_body = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent template
|
||||||
|
* @var Template
|
||||||
|
*/
|
||||||
|
public $parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template PHP code
|
* Template PHP code
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $_body;
|
private $_body;
|
||||||
|
private $_compile_stage = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call stack
|
* Call stack
|
||||||
|
@ -114,10 +127,11 @@ class Template extends Render
|
||||||
/**
|
/**
|
||||||
* @param Fenom $fenom Template storage
|
* @param Fenom $fenom Template storage
|
||||||
* @param int $options
|
* @param int $options
|
||||||
* @return \Fenom\Template
|
* @param Template $parent
|
||||||
*/
|
*/
|
||||||
public function __construct(Fenom $fenom, $options)
|
public function __construct(Fenom $fenom, $options, Template $parent = null)
|
||||||
{
|
{
|
||||||
|
$this->parent = $parent;
|
||||||
$this->_fenom = $fenom;
|
$this->_fenom = $fenom;
|
||||||
$this->_options = $options;
|
$this->_options = $options;
|
||||||
$this->_filters = $this->_fenom->getFilters();
|
$this->_filters = $this->_fenom->getFilters();
|
||||||
|
@ -166,6 +180,7 @@ class Template extends Render
|
||||||
}
|
}
|
||||||
$this->_provider = $this->_fenom->getProvider($provider);
|
$this->_provider = $this->_fenom->getProvider($provider);
|
||||||
$this->_src = $this->_provider->getSource($this->_base_name, $this->_time);
|
$this->_src = $this->_provider->getSource($this->_base_name, $this->_time);
|
||||||
|
$this->_compile_stage = self::COMPILE_STAGE_LOADED;
|
||||||
if ($compile) {
|
if ($compile) {
|
||||||
$this->compile();
|
$this->compile();
|
||||||
}
|
}
|
||||||
|
@ -196,10 +211,12 @@ class Template extends Render
|
||||||
*/
|
*/
|
||||||
public function compile()
|
public function compile()
|
||||||
{
|
{
|
||||||
$end = $pos = 0;
|
$end = $pos = 0;
|
||||||
foreach ($this->_fenom->getPreFilters() as $filter) {
|
foreach ($this->_fenom->getPreFilters() as $filter) {
|
||||||
$this->_src = call_user_func($filter, $this, $this->_src);
|
$this->_src = call_user_func($filter, $this, $this->_src);
|
||||||
}
|
}
|
||||||
|
$this->_compile_stage = self::COMPILE_STAGE_PRE_FILTERED;
|
||||||
|
|
||||||
while (($start = strpos($this->_src, '{', $pos)) !== false) { // search open-symbol of tags
|
while (($start = strpos($this->_src, '{', $pos)) !== false) { // search open-symbol of tags
|
||||||
switch (substr($this->_src, $start + 1, 1)) { // check next character
|
switch (substr($this->_src, $start + 1, 1)) { // check next character
|
||||||
case "\n":
|
case "\n":
|
||||||
|
@ -265,6 +282,7 @@ class Template extends Render
|
||||||
}
|
}
|
||||||
$pos = $end + 1; // move search-pointer to end of the tag
|
$pos = $end + 1; // move search-pointer to end of the tag
|
||||||
}
|
}
|
||||||
|
$this->_compile_stage = self::COMPILE_STAGE_PARSED;
|
||||||
|
|
||||||
gc_collect_cycles();
|
gc_collect_cycles();
|
||||||
$this->_appendText(substr($this->_src, $end ? $end + 1 : 0)); // append tail of the template
|
$this->_appendText(substr($this->_src, $end ? $end + 1 : 0)); // append tail of the template
|
||||||
|
@ -283,10 +301,16 @@ class Template extends Render
|
||||||
call_user_func_array($cb, array($this, &$this->_body));
|
call_user_func_array($cb, array($this, &$this->_body));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->_compile_stage = self::COMPILE_STAGE_PROCESSED;
|
||||||
$this->addDepend($this); // for 'verify' performance
|
$this->addDepend($this); // for 'verify' performance
|
||||||
foreach ($this->_fenom->getPostFilters() as $filter) {
|
foreach ($this->_fenom->getPostFilters() as $filter) {
|
||||||
$this->_body = call_user_func($filter, $this, $this->_body);
|
$this->_body = call_user_func($filter, $this, $this->_body);
|
||||||
}
|
}
|
||||||
|
$this->_compile_stage = self::COMPILE_STAGE_POST_FILTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isStageDone($stage_no) {
|
||||||
|
return $this->_compile_stage >= $stage_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -350,7 +374,7 @@ class Template extends Render
|
||||||
} else {
|
} else {
|
||||||
$text = str_replace("<?", '<?php echo "<?"; ?>' . ($strip ? '' : PHP_EOL), $text);
|
$text = str_replace("<?", '<?php echo "<?"; ?>' . ($strip ? '' : PHP_EOL), $text);
|
||||||
}
|
}
|
||||||
if($strip) {
|
if ($strip) {
|
||||||
$text = preg_replace('/\s+/uS', ' ', str_replace(array("\r", "\n"), " ", $text));
|
$text = preg_replace('/\s+/uS', ' ', str_replace(array("\r", "\n"), " ", $text));
|
||||||
$text = str_replace("> <", "><", $text);
|
$text = str_replace("> <", "><", $text);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +400,8 @@ class Template extends Render
|
||||||
/**
|
/**
|
||||||
* @param $tag_name
|
* @param $tag_name
|
||||||
*/
|
*/
|
||||||
public function ignore($tag_name) {
|
public function ignore($tag_name)
|
||||||
|
{
|
||||||
$this->_ignore = $tag_name;
|
$this->_ignore = $tag_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +515,7 @@ class Template extends Render
|
||||||
$escape = $this->_options & Fenom::AUTO_ESCAPE;
|
$escape = $this->_options & Fenom::AUTO_ESCAPE;
|
||||||
}
|
}
|
||||||
if ($escape) {
|
if ($escape) {
|
||||||
return "echo htmlspecialchars($data, ENT_COMPAT, ".var_export(Fenom::$charset, true).");";
|
return "echo htmlspecialchars($data, ENT_COMPAT, " . var_export(Fenom::$charset, true) . ");";
|
||||||
} else {
|
} else {
|
||||||
return "echo $data;";
|
return "echo $data;";
|
||||||
}
|
}
|
||||||
|
@ -519,13 +544,13 @@ class Template extends Render
|
||||||
*/
|
*/
|
||||||
public function extend($tpl)
|
public function extend($tpl)
|
||||||
{
|
{
|
||||||
if (!$this->_body) {
|
if (!$this->isStageDone(self::COMPILE_STAGE_PARSED)) {
|
||||||
$this->compile();
|
$this->compile();
|
||||||
}
|
}
|
||||||
$parent = $this->_fenom->getRawTemplate()->load($tpl, false);
|
$parent = $this->_fenom->getRawTemplate()->load($tpl, false);
|
||||||
$parent->blocks = & $this->blocks;
|
$parent->blocks = &$this->blocks;
|
||||||
$parent->macros = & $this->macros;
|
$parent->macros = &$this->macros;
|
||||||
$parent->_before = & $this->_before;
|
$parent->_before = &$this->_before;
|
||||||
$parent->extended = $this->getName();
|
$parent->extended = $this->getName();
|
||||||
if (!$this->ext_stack) {
|
if (!$this->ext_stack) {
|
||||||
$this->ext_stack[] = $this->getName();
|
$this->ext_stack[] = $this->getName();
|
||||||
|
@ -638,10 +663,12 @@ class Template extends Render
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($tags = $this->_fenom->getTagOwners($action)) { // unknown template tag
|
if ($tags = $this->_fenom->getTagOwners($action)) { // unknown template tag
|
||||||
throw new TokenizeException("Unexpected tag '$action' (this tag can be used with '" . implode(
|
throw new TokenizeException(
|
||||||
|
"Unexpected tag '$action' (this tag can be used with '" . implode(
|
||||||
"', '",
|
"', '",
|
||||||
$tags
|
$tags
|
||||||
) . "')");
|
) . "')"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw new TokenizeException("Unexpected tag '$action'");
|
throw new TokenizeException("Unexpected tag '$action'");
|
||||||
}
|
}
|
||||||
|
@ -675,9 +702,9 @@ class Template extends Render
|
||||||
$term = $this->parseTerm($tokens, $var, -1); // term of the expression
|
$term = $this->parseTerm($tokens, $var, -1); // term of the expression
|
||||||
if ($term !== false) {
|
if ($term !== false) {
|
||||||
if ($tokens->is('?', '!')) {
|
if ($tokens->is('?', '!')) {
|
||||||
if($cond) {
|
if ($cond) {
|
||||||
$term = array_pop($exp) . ' ' . $term;
|
$term = array_pop($exp) . ' ' . $term;
|
||||||
$term = '('. array_pop($exp) . ' ' . $term . ')';
|
$term = '(' . array_pop($exp) . ' ' . $term . ')';
|
||||||
$var = false;
|
$var = false;
|
||||||
}
|
}
|
||||||
$term = $this->parseTernary($tokens, $term, $var);
|
$term = $this->parseTernary($tokens, $term, $var);
|
||||||
|
@ -707,7 +734,7 @@ class Template extends Render
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$op = $tokens->getAndNext();
|
$op = $tokens->getAndNext();
|
||||||
if($op == '[') {
|
if ($op == '[') {
|
||||||
$tokens->need(']')->next()->need('=')->next();
|
$tokens->need(']')->next()->need('=')->next();
|
||||||
$op = '[]=';
|
$op = '[]=';
|
||||||
}
|
}
|
||||||
|
@ -742,7 +769,7 @@ class Template extends Render
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
$concat[] = "' '";
|
$concat[] = "' '";
|
||||||
}
|
}
|
||||||
if (!$term2 = "strval(".$this->parseTerm($tokens).")") {
|
if (!$term2 = "strval(" . $this->parseTerm($tokens) . ")") {
|
||||||
throw new UnexpectedTokenException($tokens);
|
throw new UnexpectedTokenException($tokens);
|
||||||
}
|
}
|
||||||
$concat[] = $term2;
|
$concat[] = $term2;
|
||||||
|
@ -762,7 +789,7 @@ class Template extends Render
|
||||||
throw new UnexpectedTokenException($tokens);
|
throw new UnexpectedTokenException($tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count($exp) == 1 && $var) {
|
if (count($exp) == 1 && $var) {
|
||||||
$is_var = true;
|
$is_var = true;
|
||||||
}
|
}
|
||||||
return implode(' ', $exp);
|
return implode(' ', $exp);
|
||||||
|
@ -785,7 +812,7 @@ class Template extends Render
|
||||||
} else {
|
} else {
|
||||||
$unary = "";
|
$unary = "";
|
||||||
}
|
}
|
||||||
switch($tokens->key()) {
|
switch ($tokens->key()) {
|
||||||
case T_LNUMBER:
|
case T_LNUMBER:
|
||||||
case T_DNUMBER:
|
case T_DNUMBER:
|
||||||
$code = $unary . $this->parseScalar($tokens);
|
$code = $unary . $this->parseScalar($tokens);
|
||||||
|
@ -801,13 +828,13 @@ class Template extends Render
|
||||||
/** @noinspection PhpMissingBreakStatementInspection */
|
/** @noinspection PhpMissingBreakStatementInspection */
|
||||||
case '$':
|
case '$':
|
||||||
$code = $this->parseAccessor($tokens, $is_var);
|
$code = $this->parseAccessor($tokens, $is_var);
|
||||||
if(!$is_var) {
|
if (!$is_var) {
|
||||||
$code = $unary . $code;
|
$code = $unary . $code;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* no break */
|
/* no break */
|
||||||
case T_VARIABLE:
|
case T_VARIABLE:
|
||||||
if(!isset($code)) {
|
if (!isset($code)) {
|
||||||
$code = $this->parseVariable($tokens);
|
$code = $this->parseVariable($tokens);
|
||||||
}
|
}
|
||||||
if ($tokens->is("(") && $tokens->hasBackList(T_STRING, T_OBJECT_OPERATOR)) {
|
if ($tokens->is("(") && $tokens->hasBackList(T_STRING, T_OBJECT_OPERATOR)) {
|
||||||
|
@ -816,25 +843,25 @@ class Template extends Render
|
||||||
}
|
}
|
||||||
$code = $unary . $this->parseChain($tokens, $code);
|
$code = $unary . $this->parseChain($tokens, $code);
|
||||||
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
|
} elseif ($tokens->is(Tokenizer::MACRO_INCDEC)) {
|
||||||
if($this->_options & Fenom::FORCE_VERIFY) {
|
if ($this->_options & Fenom::FORCE_VERIFY) {
|
||||||
$code = $unary . '(isset(' . $code . ') ? ' . $code . $tokens->getAndNext() . ' : null)';
|
$code = $unary . '(isset(' . $code . ') ? ' . $code . $tokens->getAndNext() . ' : null)';
|
||||||
} else {
|
} else {
|
||||||
$code = $unary . $code . $tokens->getAndNext();
|
$code = $unary . $code . $tokens->getAndNext();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if($this->_options & Fenom::FORCE_VERIFY) {
|
if ($this->_options & Fenom::FORCE_VERIFY) {
|
||||||
$code = $unary . '(isset(' . $code . ') ? ' . $code . ' : null)';
|
$code = $unary . '(isset(' . $code . ') ? ' . $code . ' : null)';
|
||||||
} else {
|
} else {
|
||||||
$is_var = true;
|
$is_var = true;
|
||||||
$code = $unary . $code;
|
$code = $unary . $code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_DEC:
|
case T_DEC:
|
||||||
case T_INC:
|
case T_INC:
|
||||||
if($this->_options & Fenom::FORCE_VERIFY) {
|
if ($this->_options & Fenom::FORCE_VERIFY) {
|
||||||
$var = $this->parseVariable($tokens);
|
$var = $this->parseVariable($tokens);
|
||||||
$code = $unary . '(isset(' . $var . ') ? ' . $tokens->getAndNext() . $this->parseVariable($tokens).' : null)';
|
$code = $unary . '(isset(' . $var . ') ? ' . $tokens->getAndNext() . $this->parseVariable($tokens) . ' : null)';
|
||||||
} else {
|
} else {
|
||||||
$code = $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
|
$code = $unary . $tokens->getAndNext() . $this->parseVariable($tokens);
|
||||||
}
|
}
|
||||||
|
@ -853,7 +880,7 @@ class Template extends Render
|
||||||
throw new \Exception("Function " . $tokens->getAndNext() . " not found");
|
throw new \Exception("Function " . $tokens->getAndNext() . " not found");
|
||||||
}
|
}
|
||||||
if (!is_string($func)) { // dynamic modifier
|
if (!is_string($func)) { // dynamic modifier
|
||||||
$call = 'call_user_func_array($tpl->getStorage()->getModifier("' . $modifier . '"), array'.$this->parseArgs($tokens->next()).')'; // @todo optimize
|
$call = 'call_user_func_array($tpl->getStorage()->getModifier("' . $modifier . '"), array' . $this->parseArgs($tokens->next()) . ')'; // @todo optimize
|
||||||
} else {
|
} else {
|
||||||
$call = $func . $this->parseArgs($tokens->next());
|
$call = $func . $this->parseArgs($tokens->next());
|
||||||
}
|
}
|
||||||
|
@ -890,13 +917,13 @@ class Template extends Render
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (($allows & self::TERM_MODS) && $tokens->is('|')) {
|
if (($allows & self::TERM_MODS) && $tokens->is('|')) {
|
||||||
$code = $this->parseModifier($tokens, $code);
|
$code = $this->parseModifier($tokens, $code);
|
||||||
$is_var = false;
|
$is_var = false;
|
||||||
}
|
}
|
||||||
if(($allows & self::TERM_RANGE) && $tokens->is('.') && $tokens->isNext('.')) {
|
if (($allows & self::TERM_RANGE) && $tokens->is('.') && $tokens->isNext('.')) {
|
||||||
$tokens->next()->next();
|
$tokens->next()->next();
|
||||||
$code = '(new \Fenom\RangeIterator('.$code.', '.$this->parseTerm($tokens, $var, self::TERM_MODS).'))';
|
$code = '(new \Fenom\RangeIterator(' . $code . ', ' . $this->parseTerm($tokens, $var, self::TERM_MODS) . '))';
|
||||||
$is_var = false;
|
$is_var = false;
|
||||||
}
|
}
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
@ -907,7 +934,8 @@ class Template extends Render
|
||||||
* @param string $code start point (it is $var)
|
* @param string $code start point (it is $var)
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function parseChain(Tokenizer $tokens, $code) {
|
public function parseChain(Tokenizer $tokens, $code)
|
||||||
|
{
|
||||||
do {
|
do {
|
||||||
if ($tokens->is('(')) {
|
if ($tokens->is('(')) {
|
||||||
$code .= $this->parseArgs($tokens);
|
$code .= $this->parseArgs($tokens);
|
||||||
|
@ -930,10 +958,10 @@ class Template extends Render
|
||||||
public function parseVariable(Tokenizer $tokens, $var = null)
|
public function parseVariable(Tokenizer $tokens, $var = null)
|
||||||
{
|
{
|
||||||
if (!$var) {
|
if (!$var) {
|
||||||
if($tokens->isNext('@')) {
|
if ($tokens->isNext('@')) {
|
||||||
// $v = $tokens->get(T_VARIABLE);
|
// $v = $tokens->get(T_VARIABLE);
|
||||||
$prop = $tokens->next()->next()->get(T_STRING);
|
$prop = $tokens->next()->next()->get(T_STRING);
|
||||||
if($tag = $this->getParentScope("foreach")) {
|
if ($tag = $this->getParentScope("foreach")) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
return Compiler::foreachProp($tag, $prop);
|
return Compiler::foreachProp($tag, $prop);
|
||||||
} else {
|
} else {
|
||||||
|
@ -955,7 +983,7 @@ class Template extends Render
|
||||||
$key = "[" . $tokens->getAndNext() . "]";
|
$key = "[" . $tokens->getAndNext() . "]";
|
||||||
} elseif ($tokens->is('"')) {
|
} elseif ($tokens->is('"')) {
|
||||||
$key = "[" . $this->parseQuote($tokens) . "]";
|
$key = "[" . $this->parseQuote($tokens) . "]";
|
||||||
} elseif($tokens->is('.')) {
|
} elseif ($tokens->is('.')) {
|
||||||
$tokens->back();
|
$tokens->back();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -963,7 +991,7 @@ class Template extends Render
|
||||||
}
|
}
|
||||||
$var .= $key;
|
$var .= $key;
|
||||||
} elseif ($t === "[") {
|
} elseif ($t === "[") {
|
||||||
if($tokens->isNext(']')) {
|
if ($tokens->isNext(']')) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
|
@ -1001,16 +1029,23 @@ class Template extends Render
|
||||||
public function parseAccessor(Tokenizer $tokens, &$is_var = false)
|
public function parseAccessor(Tokenizer $tokens, &$is_var = false)
|
||||||
{
|
{
|
||||||
$accessor = $tokens->need('$')->next()->need('.')->next()->current();
|
$accessor = $tokens->need('$')->next()->need('.')->next()->current();
|
||||||
$parser = $this->getStorage()->getAccessor($accessor);
|
$parser = $this->getStorage()->getAccessor($accessor);
|
||||||
$is_var = false;
|
$is_var = false;
|
||||||
if($parser) {
|
if ($parser) {
|
||||||
if(is_array($parser)) {
|
if (is_array($parser)) {
|
||||||
if(isset($parser['callback'])) {
|
if (isset($parser['callback'])) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
return 'call_user_func($tpl->getStorage()->getAccessor('.var_export($accessor, true).
|
return 'call_user_func($tpl->getStorage()->getAccessor(' . var_export($accessor, true) .
|
||||||
', "callback"), '.var_export($accessor, true).', $tpl, $var)';
|
', "callback"), ' . var_export($accessor, true) . ', $tpl, $var)';
|
||||||
} else {
|
} else {
|
||||||
return call_user_func_array($parser['parser'], array($parser['accessor'], $tokens->next(), $this, &$is_var));
|
return call_user_func_array(
|
||||||
|
$parser['parser'], array(
|
||||||
|
$parser['accessor'],
|
||||||
|
$tokens->next(),
|
||||||
|
$this,
|
||||||
|
&$is_var
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return call_user_func_array($parser, array($tokens->next(), $this, &$is_var));
|
return call_user_func_array($parser, array($tokens->next(), $this, &$is_var));
|
||||||
|
@ -1365,15 +1400,15 @@ class Template extends Render
|
||||||
$count++;
|
$count++;
|
||||||
} else {
|
} else {
|
||||||
$expr = $this->parseExpr($tokens);
|
$expr = $this->parseExpr($tokens);
|
||||||
if($tokens->is(T_DOUBLE_ARROW)) {
|
if ($tokens->is(T_DOUBLE_ARROW)) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
$arr[] = $expr.' => '.$this->parseExpr($tokens);
|
$arr[] = $expr . ' => ' . $this->parseExpr($tokens);
|
||||||
} else {
|
} else {
|
||||||
$arr[] = $expr;
|
$arr[] = $expr;
|
||||||
}
|
}
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
if($tokens->is(',')) {
|
if ($tokens->is(',')) {
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,12 @@ class TestCase extends \PHPUnit\Framework\TestCase
|
||||||
return filemtime(FENOM_RESOURCES . '/template/' . $name);
|
return filemtime(FENOM_RESOURCES . '/template/' . $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function tpls(array $list) {
|
||||||
|
foreach($list as $name => $tpl) {
|
||||||
|
$this->tpl($name, $tpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile and execute template
|
* Compile and execute template
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,8 +9,4 @@ require_once FENOM_RESOURCES . "/actions.php";
|
||||||
require_once __DIR__ . "/TestCase.php";
|
require_once __DIR__ . "/TestCase.php";
|
||||||
require_once __DIR__ . "/tools.php";
|
require_once __DIR__ . "/tools.php";
|
||||||
|
|
||||||
ini_set('date.timezone', 'Europe/Moscow');
|
ini_set('date.timezone', 'Europe/Moscow');
|
||||||
|
|
||||||
if(PHP_VERSION_ID > 50400) {
|
|
||||||
function php_gte_54() {}
|
|
||||||
}
|
|
|
@ -268,48 +268,6 @@ class TemplateTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function providerInclude()
|
|
||||||
{
|
|
||||||
$a = array(
|
|
||||||
"name" => "welcome",
|
|
||||||
"tpl" => "welcome.tpl",
|
|
||||||
"fragment" => "come",
|
|
||||||
"pr_fragment" => "Come",
|
|
||||||
"pr_name" => "Welcome",
|
|
||||||
"username" => "Master",
|
|
||||||
"email" => "dev@null.net"
|
|
||||||
);
|
|
||||||
$result = 'Include <b>Welcome, Master (dev@null.net)</b> template';
|
|
||||||
$result2 = 'Include <b>Welcome, Flame (dev@null.net)</b> template';
|
|
||||||
$result3 = 'Include <b>Welcome, Master (flame@dev.null)</b> template';
|
|
||||||
$result4 = 'Include <b>Welcome, Flame (flame@dev.null)</b> template';
|
|
||||||
return array(
|
|
||||||
array('Include {include "welcome.tpl"} template', $a, $result),
|
|
||||||
array('Include {include "welcome.tpl"} template', $a, $result, Fenom::FORCE_INCLUDE),
|
|
||||||
array('Include {include $tpl} template', $a, $result),
|
|
||||||
array('Include {include "$tpl"} template', $a, $result),
|
|
||||||
array('Include {include "{$tpl}"} template', $a, $result),
|
|
||||||
array('Include {include "$name.tpl"} template', $a, $result),
|
|
||||||
array('Include {include "{$name}.tpl"} template', $a, $result),
|
|
||||||
array('Include {include "{$pr_name|lower}.tpl"} template', $a, $result),
|
|
||||||
array('Include {include "wel{$fragment}.tpl"} template', $a, $result),
|
|
||||||
array('Include {include "wel{$pr_fragment|lower}.tpl"} template', $a, $result),
|
|
||||||
array('Include {include "welcome.tpl" username="Flame"} template', $a, $result2),
|
|
||||||
array('Include {include "welcome.tpl" username="Flame"} template', $a, $result2, Fenom::FORCE_INCLUDE),
|
|
||||||
array('Include {include "welcome.tpl" email="flame@dev.null"} template', $a, $result3),
|
|
||||||
array(
|
|
||||||
'Include {include "welcome.tpl" email="flame@dev.null"} template',
|
|
||||||
$a,
|
|
||||||
$result3,
|
|
||||||
Fenom::FORCE_INCLUDE
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Include {include "welcome.tpl" username="Flame" email="flame@dev.null"} template',
|
|
||||||
$a,
|
|
||||||
$result4
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function providerIncludeInvalid()
|
public static function providerIncludeInvalid()
|
||||||
{
|
{
|
||||||
|
@ -830,38 +788,6 @@ class TemplateTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function providerSwitch()
|
|
||||||
{
|
|
||||||
$code1 = 'Switch: {switch $a}
|
|
||||||
{case 1, "one"} one
|
|
||||||
{case 2, "two"} two
|
|
||||||
{case "string", default} str
|
|
||||||
{default} def
|
|
||||||
{/switch} end';
|
|
||||||
|
|
||||||
$code2 = 'Switch: {switch $a}
|
|
||||||
{case 1, "one"} one
|
|
||||||
{case 2, "two"} two
|
|
||||||
{case "string"} str
|
|
||||||
{/switch} end';
|
|
||||||
|
|
||||||
$code3 = 'Switch: {switch $a} invalid
|
|
||||||
{case 1, "one"} one
|
|
||||||
{/switch} end';
|
|
||||||
|
|
||||||
return array(
|
|
||||||
array($code1, array("a" => 1), 'Switch: one end'),
|
|
||||||
array($code1, array("a" => 'one'), 'Switch: one end'),
|
|
||||||
array($code1, array("a" => 2), 'Switch: two end'),
|
|
||||||
array($code1, array("a" => 'two'), 'Switch: two end'),
|
|
||||||
array($code1, array("a" => "string"), 'Switch: str end'),
|
|
||||||
array($code1, array("a" => "unk"), 'Switch: str def end'),
|
|
||||||
array($code2, array("a" => "unk"), 'Switch: end'),
|
|
||||||
array($code3, array("a" => 1), 'Switch: one end'),
|
|
||||||
array($code3, array("a" => 'one'), 'Switch: one end'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function providerSwitchInvalid()
|
public static function providerSwitchInvalid()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
@ -1129,27 +1055,6 @@ class TemplateTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @group sb
|
|
||||||
*/
|
|
||||||
public function _testSandbox()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
var_dump(
|
|
||||||
$this->fenom->compileCode(
|
|
||||||
'{Fenom\Helper::method()->page->title}'
|
|
||||||
)->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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerScalars
|
* @dataProvider providerScalars
|
||||||
*/
|
*/
|
||||||
|
@ -1216,12 +1121,66 @@ class TemplateTest extends TestCase
|
||||||
$this->execError($code, $exception, $message, $options);
|
$this->execError($code, $exception, $message, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function providerInclude()
|
||||||
|
{
|
||||||
|
$a = array(
|
||||||
|
"name" => "welcome",
|
||||||
|
"tpl" => "welcome.tpl",
|
||||||
|
"fragment" => "come",
|
||||||
|
"pr_fragment" => "Come",
|
||||||
|
"pr_name" => "Welcome",
|
||||||
|
"username" => "Master",
|
||||||
|
"email" => "dev@null.net"
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = 'Include <b>Welcome, Master (dev@null.net)</b> template';
|
||||||
|
$result2 = 'Include <b>Welcome, Flame (dev@null.net)</b> template';
|
||||||
|
$result3 = 'Include <b>Welcome, Master (flame@dev.null)</b> template';
|
||||||
|
$result4 = 'Include <b>Welcome, Flame (flame@dev.null)</b> template';
|
||||||
|
|
||||||
|
$recursive_result = 'Include <b>Hello, Master (dev@null.net)</b> template';
|
||||||
|
$recursive_result2 = 'Include <b>Hello, Flame (dev@null.net)</b> template';
|
||||||
|
return array(
|
||||||
|
array('Include {include "welcome.tpl"} template', $a, $result),
|
||||||
|
array('Include {include "welcome.tpl"} template', $a, $result, Fenom::FORCE_INCLUDE),
|
||||||
|
array('Include {include "recursive.tpl"} template', $a, $recursive_result, Fenom::FORCE_INCLUDE),
|
||||||
|
array('Include {include $tpl} template', $a, $result),
|
||||||
|
array('Include {include "$tpl"} template', $a, $result),
|
||||||
|
array('Include {include "{$tpl}"} template', $a, $result),
|
||||||
|
array('Include {include "$name.tpl"} template', $a, $result),
|
||||||
|
array('Include {include "{$name}.tpl"} template', $a, $result),
|
||||||
|
array('Include {include "{$pr_name|lower}.tpl"} template', $a, $result),
|
||||||
|
array('Include {include "wel{$fragment}.tpl"} template', $a, $result),
|
||||||
|
array('Include {include "wel{$pr_fragment|lower}.tpl"} template', $a, $result),
|
||||||
|
array('Include {include "welcome.tpl" username="Flame"} template', $a, $result2),
|
||||||
|
array('Include {include "welcome.tpl" username="Flame"} template', $a, $result2, Fenom::FORCE_INCLUDE),
|
||||||
|
array('Include {include "recursive.tpl" username="Flame"} template', $a, $recursive_result2, Fenom::FORCE_INCLUDE),
|
||||||
|
array('Include {include "welcome.tpl" email="flame@dev.null"} template', $a, $result3),
|
||||||
|
array(
|
||||||
|
'Include {include "welcome.tpl" email="flame@dev.null"} template',
|
||||||
|
$a,
|
||||||
|
$result3,
|
||||||
|
Fenom::FORCE_INCLUDE
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Include {include "welcome.tpl" username="Flame" email="flame@dev.null"} template',
|
||||||
|
$a,
|
||||||
|
$result4,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group include
|
* @group dev
|
||||||
* @dataProvider providerInclude
|
* @dataProvider providerInclude
|
||||||
*/
|
*/
|
||||||
public function testInclude($code, $vars, $result, $options = 0)
|
public function testInclude($code, $vars, $result, $options = 0)
|
||||||
{
|
{
|
||||||
|
$this->tpls(array(
|
||||||
|
'welcome.tpl' => '<b>Welcome, {$username} ({$email})</b>',
|
||||||
|
'recursive.tpl' => '<b>Hello, {$username} ({$email}){if false}{include "recursive.tpl"}{/if}</b>'
|
||||||
|
));
|
||||||
$this->exec($code, $vars, $result, $options);
|
$this->exec($code, $vars, $result, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1427,6 +1386,11 @@ class TemplateTest extends TestCase
|
||||||
$a,
|
$a,
|
||||||
'Foreach: 0 => 1, 1 => 2, 2 => 3, end'
|
'Foreach: 0 => 1, 1 => 2, 2 => 3, end'
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'Foreach: {foreach 1..3 as $k => $e last=$l} {$k} => {$e}, {if $l}last{/if} {/foreach} end',
|
||||||
|
$a,
|
||||||
|
'Foreach: 0 => 1, 1 => 2, 2 => 3, last end'
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'Foreach: {foreach $.get.items as $e} {$e}, {/foreach} end',
|
'Foreach: {foreach $.get.items as $e} {$e}, {/foreach} end',
|
||||||
$a,
|
$a,
|
||||||
|
@ -1478,6 +1442,44 @@ class TemplateTest extends TestCase
|
||||||
$this->exec($code, $vars, $result);
|
$this->exec($code, $vars, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function providerSwitch()
|
||||||
|
{
|
||||||
|
$code1 = 'Switch: {switch $a}
|
||||||
|
{case 1, "one"} one
|
||||||
|
{case 2, "two"} two
|
||||||
|
{case "string", default} str
|
||||||
|
{default} def
|
||||||
|
{/switch} end';
|
||||||
|
|
||||||
|
$code2 = 'Switch: {switch $a}
|
||||||
|
{case 1, "one"} one
|
||||||
|
{case 2, "two"} two
|
||||||
|
{case "string"} str
|
||||||
|
{/switch} end';
|
||||||
|
|
||||||
|
$code3 = 'Switch: {switch $a} invalid
|
||||||
|
{case 1, "one"} one
|
||||||
|
{/switch} end';
|
||||||
|
|
||||||
|
$code4 = 'Switch:{switch $a}{case 1}<b>one</b>{/switch}end';
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array($code1, array("a" => 1), 'Switch: one end'),
|
||||||
|
array($code1, array("a" => 'one'), 'Switch: one end'),
|
||||||
|
array($code1, array("a" => 2), 'Switch: two end'),
|
||||||
|
array($code1, array("a" => 'two'), 'Switch: two end'),
|
||||||
|
array($code1, array("a" => "string"), 'Switch: str end'),
|
||||||
|
array($code1, array("a" => "unk"), 'Switch: str def end'),
|
||||||
|
array($code2, array("a" => "unk"), 'Switch: end'),
|
||||||
|
array($code3, array("a" => 1), 'Switch: one end'),
|
||||||
|
array($code3, array("a" => 'one'), 'Switch: one end'),
|
||||||
|
array($code4, array("a" => 1), 'Switch:<b>one</b>end'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group switch
|
* @group switch
|
||||||
* @dataProvider providerSwitch
|
* @dataProvider providerSwitch
|
||||||
|
|
|
@ -321,7 +321,7 @@ class FenomTest extends \Fenom\TestCase
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @requires function php_gte_54
|
* @requires PHP 5.4
|
||||||
* @group pipe
|
* @group pipe
|
||||||
*/
|
*/
|
||||||
public function testPipe()
|
public function testPipe()
|
||||||
|
|
Loading…
Reference in New Issue