mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
commit
e96004b166
@ -119,6 +119,7 @@ $fenom->addModifier('my_modifier', function ($variable, $param1, $param2) {
|
|||||||
```php
|
```php
|
||||||
$fenom->addTest($name, $code);
|
$fenom->addTest($name, $code);
|
||||||
?>
|
?>
|
||||||
|
```
|
||||||
|
|
||||||
# Add template provider
|
# Add template provider
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ Documentation
|
|||||||
* [macro](./tags/macro.md) and `import` — template functions
|
* [macro](./tags/macro.md) and `import` — template functions
|
||||||
* [autoescape](./tags/autoescape.md) — escape template fragment
|
* [autoescape](./tags/autoescape.md) — escape template fragment
|
||||||
* [raw](./tags/raw.md) — unescape template fragment
|
* [raw](./tags/raw.md) — unescape template fragment
|
||||||
|
* [unset](./tags/unset.md) — unset a given variables
|
||||||
* or [add](./ext/extend.md#add-tags) yours
|
* or [add](./ext/extend.md#add-tags) yours
|
||||||
|
|
||||||
|
|
||||||
|
12
docs/tags/unset.md
Normal file
12
docs/tags/unset.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Tag {unset}
|
||||||
|
===========
|
||||||
|
|
||||||
|
Unset a given variables.
|
||||||
|
|
||||||
|
```smarty
|
||||||
|
|
||||||
|
{unset $a} unset single variable
|
||||||
|
|
||||||
|
{unset $a $b $c.d.e} multiple unset
|
||||||
|
|
||||||
|
```
|
@ -282,6 +282,10 @@ class Fenom
|
|||||||
'type' => self::BLOCK_COMPILER,
|
'type' => self::BLOCK_COMPILER,
|
||||||
'open' => 'Fenom\Compiler::ignoreOpen',
|
'open' => 'Fenom\Compiler::ignoreOpen',
|
||||||
'close' => 'Fenom\Compiler::nope'
|
'close' => 'Fenom\Compiler::nope'
|
||||||
|
),
|
||||||
|
'unset' => array(
|
||||||
|
'type' => self::INLINE_COMPILER,
|
||||||
|
'parser' => 'Fenom\Compiler::tagUnset'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -137,14 +137,20 @@ class Compiler
|
|||||||
$p = array("index" => false, "first" => false, "last" => false);
|
$p = array("index" => false, "first" => false, "last" => false);
|
||||||
$key = null;
|
$key = null;
|
||||||
$before = $body = array();
|
$before = $body = array();
|
||||||
if ($tokens->is(T_VARIABLE)) {
|
|
||||||
$from = $scope->tpl->parseTerm($tokens);
|
|
||||||
$prepend = "";
|
$prepend = "";
|
||||||
|
if ($tokens->is(T_VARIABLE)) {
|
||||||
|
$from = $scope->tpl->parseTerm($tokens, $is_var);
|
||||||
|
if($is_var) {
|
||||||
|
$check = '!empty('.$from.')';
|
||||||
|
} else {
|
||||||
|
$scope["var"] = $scope->tpl->tmpVar();
|
||||||
|
$prepend = $scope["var"].' = (array)('.$from.')';
|
||||||
|
$from = $check = $scope["var"];
|
||||||
|
}
|
||||||
} elseif ($tokens->is('[')) {
|
} elseif ($tokens->is('[')) {
|
||||||
$from = $scope->tpl->parseArray($tokens);
|
$count = 0;
|
||||||
$uid = '$v' . $scope->tpl->i++;
|
$from = $scope->tpl->parseArray($tokens, $count);
|
||||||
$prepend = $uid . ' = ' . $from . ';';
|
$check = $count;
|
||||||
$from = $uid;
|
|
||||||
} else {
|
} else {
|
||||||
throw new UnexpectedTokenException($tokens, null, "tag {foreach}");
|
throw new UnexpectedTokenException($tokens, null, "tag {foreach}");
|
||||||
}
|
}
|
||||||
@ -189,9 +195,9 @@ class Compiler
|
|||||||
$body = $body ? implode("; ", $body) . ";" : "";
|
$body = $body ? implode("; ", $body) . ";" : "";
|
||||||
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
$scope["after"] = $scope["after"] ? implode("; ", $scope["after"]) . ";" : "";
|
||||||
if ($key) {
|
if ($key) {
|
||||||
return "$prepend if($from) { $before foreach($from as $key => $value) { $body";
|
return "$prepend if($check) { $before foreach($from as $key => $value) { $body";
|
||||||
} else {
|
} else {
|
||||||
return "$prepend if($from) { $before foreach($from as $value) { $body";
|
return "$prepend if($check) { $before foreach($from as $value) { $body";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,4 +1007,19 @@ class Compiler
|
|||||||
{
|
{
|
||||||
$tag->tpl->ignore('ignore');
|
$tag->tpl->ignore('ignore');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag {unset ...}
|
||||||
|
* @param Tokenizer $tokens
|
||||||
|
* @param Tag $tag
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function tagUnset(Tokenizer $tokens, Tag $tag)
|
||||||
|
{
|
||||||
|
$unset = array();
|
||||||
|
while($tokens->valid()) {
|
||||||
|
$unset[] = $tag->tpl->parseVariable($tokens);
|
||||||
|
}
|
||||||
|
return 'unset('.implode(", ", $unset).')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ class Template extends Render
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $tag
|
* @param string $tag
|
||||||
* @return bool|\Fenom\Scope
|
* @return bool|\Fenom\Tag
|
||||||
*/
|
*/
|
||||||
public function getParentScope($tag)
|
public function getParentScope($tag)
|
||||||
{
|
{
|
||||||
@ -1274,50 +1274,35 @@ class Template extends Render
|
|||||||
* [1, 2.3, 5+7/$var, 'string', "str {$var+3} ing", $var2, []]
|
* [1, 2.3, 5+7/$var, 'string', "str {$var+3} ing", $var2, []]
|
||||||
*
|
*
|
||||||
* @param Tokenizer $tokens
|
* @param Tokenizer $tokens
|
||||||
* @throws UnexpectedTokenException
|
* @param int $count amount of elements
|
||||||
|
* @throws Error\UnexpectedTokenException
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function parseArray(Tokenizer $tokens)
|
public function parseArray(Tokenizer $tokens, &$count = 0)
|
||||||
{
|
{
|
||||||
if ($tokens->is("[")) {
|
if ($tokens->is("[")) {
|
||||||
$_arr = "array(";
|
$arr = array();
|
||||||
$key = $val = false;
|
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
while ($tokens->valid()) {
|
while ($tokens->valid()) {
|
||||||
if ($tokens->is(',') && $val) {
|
if ($tokens->is(']')) {
|
||||||
$key = true;
|
|
||||||
$val = false;
|
|
||||||
$_arr .= $tokens->getAndNext() . ' ';
|
|
||||||
} elseif ($tokens->is(
|
|
||||||
Tokenizer::MACRO_SCALAR,
|
|
||||||
T_VARIABLE,
|
|
||||||
T_STRING,
|
|
||||||
T_EMPTY,
|
|
||||||
T_ISSET,
|
|
||||||
"(",
|
|
||||||
"#"
|
|
||||||
) && !$val
|
|
||||||
) {
|
|
||||||
$_arr .= $this->parseExpr($tokens);
|
|
||||||
$key = false;
|
|
||||||
$val = true;
|
|
||||||
} elseif ($tokens->is('"') && !$val) {
|
|
||||||
$_arr .= $this->parseQuote($tokens);
|
|
||||||
$key = false;
|
|
||||||
$val = true;
|
|
||||||
} elseif ($tokens->is(T_DOUBLE_ARROW) && $val) {
|
|
||||||
$_arr .= ' ' . $tokens->getAndNext() . ' ';
|
|
||||||
$key = true;
|
|
||||||
$val = false;
|
|
||||||
} elseif (!$val && $tokens->is('[')) {
|
|
||||||
$_arr .= $this->parseArray($tokens);
|
|
||||||
$key = false;
|
|
||||||
$val = true;
|
|
||||||
} elseif ($tokens->is(']') && (!$key || $tokens->prev[0] === ',')) {
|
|
||||||
$tokens->next();
|
$tokens->next();
|
||||||
return $_arr . ')';
|
return 'array(' . implode(', ', $arr) . ')';
|
||||||
|
}
|
||||||
|
if ($tokens->is('[')) {
|
||||||
|
$arr[] = $this->parseArray($tokens);
|
||||||
|
$count++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
$expr = $this->parseExpr($tokens);
|
||||||
|
if($tokens->is(T_DOUBLE_ARROW)) {
|
||||||
|
$tokens->next();
|
||||||
|
$arr[] = $expr.' => '.$this->parseExpr($tokens);
|
||||||
|
} else {
|
||||||
|
$arr[] = $expr;
|
||||||
|
}
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
if($tokens->is(',')) {
|
||||||
|
$tokens->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,6 +572,38 @@ class TemplateTest extends TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function providerArrays()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('{var $arr = []}', array()),
|
||||||
|
array('{var $arr = [1]}', array(1)),
|
||||||
|
array('{var $arr = [1,]}', array(1)),
|
||||||
|
array('{var $arr = [1, 2, 3, 5]}', array(1, 2, 3, 5)),
|
||||||
|
array('{var $arr = [1, true, false, null, -1, 1.1, -2.2, 5, "str"]}', array(1, true, false, null, -1, 1.1, -2.2, 5, "str")),
|
||||||
|
array('{var $arr = [5 => 1, "two" => 2, 3]}', array(5 => 1, "two" => 2, 3)),
|
||||||
|
array('{var $arr = [1 + 1, 2 * 2, 3 / 3 + 7,]}', array(1 + 1, 2 * 2, 3 / 3 + 7)),
|
||||||
|
array('{var $arr = [$zero, $two => $one, $num.3 => $.const.PHP_VERSION]}', array(0, 2 => 1, "three" => PHP_VERSION)),
|
||||||
|
array('{var $arr = [5 - 1 => 1, "two"|up => "two"|low, 3 => count([1,2])]}', array(4 => 1, "TWO" => "two", 3 => 2)),
|
||||||
|
|
||||||
|
array('{var $arr = [[1]]}', array(array(1))),
|
||||||
|
array('{var $arr = [[],[]]}', array(array(),array())),
|
||||||
|
array('{var $arr = [1, [2, 3], 5]}', array(1, array(2, 3), 5)),
|
||||||
|
array('{var $arr = [1, [true, false, null, -1, 1.1, -2.2, 5], "str"]}', array(1, array(true, false, null, -1, 1.1, -2.2, 5), "str")),
|
||||||
|
array('{var $arr = [5 => [1, "two" => 2], 3]}', array(5 => array(1, "two" => 2), 3)),
|
||||||
|
array('{var $arr = [1 + 1, [2 * 2, 3 / 3 + 7,],]}', array(1 + 1, array(2 * 2, 3 / 3 + 7))),
|
||||||
|
array('{var $arr = [$zero, [$two => $one, $num.3 => $.const.PHP_VERSION]]}', array(0, array(2 => 1, "three" => PHP_VERSION))),
|
||||||
|
array('{var $arr = [5 - 1 => 1, ["two"|up => ("two"|low ~ "..."), 3 => count([1,2])]]}', array(4 => 1, array("TWO" => "two...", 3 => 2))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function providerUnset() {
|
||||||
|
return array(
|
||||||
|
array('{var $a = 5} {unset $a} {if $a is not set}not set{/if}', 'not set'),
|
||||||
|
array('{var $a = ["b" => 5, "c" => 6]} {unset $a.b} {if $a.b is not set}not set{/if} but c is {$a.c}', 'not set but c is 6'),
|
||||||
|
array('{var $a = ["b" => 5, "c" => 6]} {unset $a.b $a.c} {if $a.b is not set}not set{/if} {if $a.c is not set}not set{/if}', 'not set not set'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public static function providerTernary()
|
public static function providerTernary()
|
||||||
{
|
{
|
||||||
$a = array(
|
$a = array(
|
||||||
@ -683,6 +715,7 @@ class TemplateTest extends TestCase
|
|||||||
),
|
),
|
||||||
array('Foreach: {foreach $empty as $k => $e} {$k} => {$e}, {/foreach} end', $a, 'Foreach: end'),
|
array('Foreach: {foreach $empty as $k => $e} {$k} => {$e}, {/foreach} end', $a, 'Foreach: end'),
|
||||||
array('Foreach: {foreach [] as $k => $e} {$k} => {$e}, {/foreach} end', $a, 'Foreach: end'),
|
array('Foreach: {foreach [] as $k => $e} {$k} => {$e}, {/foreach} end', $a, 'Foreach: end'),
|
||||||
|
array('Foreach: {foreach $unexists as $k => $e} {$k} => {$e}, {/foreach} end', $a, 'Foreach: end'),
|
||||||
array(
|
array(
|
||||||
'Foreach: {foreach $empty as $k => $e} {$k} => {$e}, {foreachelse} empty {/foreach} end',
|
'Foreach: {foreach $empty as $k => $e} {$k} => {$e}, {foreachelse} empty {/foreach} end',
|
||||||
$a,
|
$a,
|
||||||
@ -1268,19 +1301,22 @@ class TemplateTest extends TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group sb
|
||||||
|
*/
|
||||||
public function _testSandbox()
|
public function _testSandbox()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
var_dump(
|
var_dump(
|
||||||
$this->fenom->setOptions(0)->compileCode(
|
$this->fenom->compileCode(
|
||||||
"{autoescape true}{test_block_function:raw}{\$html}{/test_block_function}{/autoescape}"
|
'{unset $a $a.c $b}'
|
||||||
)->getBody()
|
)->getBody()
|
||||||
);
|
);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
print_r($e->getMessage() . "\n" . $e->getTraceAsString());
|
print_r($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||||
while ($e->getPrevious()) {
|
while ($e->getPrevious()) {
|
||||||
$e = $e->getPrevious();
|
$e = $e->getPrevious();
|
||||||
print_r("\n\n" . $e->getMessage() . "\n" . $e->getTraceAsString());
|
print_r("\n\n" . $e->getMessage() . " in {$e->getFile()}:{$e->getLine()}\n" . $e->getTraceAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit;
|
exit;
|
||||||
@ -1416,6 +1452,34 @@ class TemplateTest extends TestCase
|
|||||||
$this->execError($code, $exception, $message, $options);
|
$this->execError($code, $exception, $message, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerArrays
|
||||||
|
* @group arrays
|
||||||
|
*/
|
||||||
|
public function testArrays($code, $vars)
|
||||||
|
{
|
||||||
|
$v = $this->getVars();
|
||||||
|
$v['vars'] = $vars;
|
||||||
|
$this->exec($code.'{if $arr === $vars}equal{/if}', $v, 'equal');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerUnset
|
||||||
|
* @group unset
|
||||||
|
*/
|
||||||
|
public function testUnset($code, $result)
|
||||||
|
{
|
||||||
|
$this->exec($code, $this->getVars(), $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerCreateVarInvalid
|
||||||
|
*/
|
||||||
|
// public function testCreateVarInvalid($code, $exception, $message, $options = 0)
|
||||||
|
// {
|
||||||
|
// $this->execError($code, $exception, $message, $options);
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group ternary
|
* @group ternary
|
||||||
* @dataProvider providerTernary
|
* @dataProvider providerTernary
|
||||||
|
Loading…
x
Reference in New Issue
Block a user