Fix {switch} and ternary operator

This commit is contained in:
bzick 2013-09-05 03:35:02 +04:00
parent 7a84cf4ceb
commit d5ecc1bc20
6 changed files with 60 additions and 25 deletions

View File

@ -5,6 +5,4 @@ php:
- 5.4
- 5.5
before_script: composer install
script: phpunit

View File

@ -30,7 +30,6 @@ $fenom->setOptions($options);
* **auto_escape**, `Fenom::AUTO_ESCAPE`, все выводящие переменные и результаты функций будут экранироваться
* **auto_trim**, `Fenom::AUTO_TRIM`, при компиляции, все пробельные символы между тегами будут удлаены.
* **force_verify**, `Fenom::FORCE_VERIFY`, проверять обращение каждой переменной и возвращать NULL если переменной не существует.
* **deny_static_methods**, `Fenom::DENY_STATIC_METHODS`, отключает возможность вызова статичных методов в шаблоне.
```php
$fenom->setOptions(array(

View File

@ -1,6 +1,12 @@
Tag {switch}
============
The `{switch}` tag is similar to a series of `{if}` statements on the same expression.
In many occasions, you may want to compare the same variable (or expression) with many different values,
and execute a different piece of code depending on which value it equals to. This is exactly what the `{switch}` tag is for.
Tag `{switch}` accepts any expression. But `{case}` accepts only static scalar values or constants.
```smarty
{switch <condition>}
{case <value1>}
@ -9,7 +15,7 @@ Tag {switch}
...
{case <value3>}
...
{default}
{default case <value1>}
...
{/switch}
```
@ -24,14 +30,14 @@ For example,
It is new or current item
{case 'current'}
It is current item
{case 'new'}
{case 'new', $.const.NEW_STATUS}
It is new item, again
{default}
I don't know the type {$type}
{/switch}
```
set `$type = 'new'`, then template output
if `$type = 'new'` then template output
```
It is new item

View File

@ -332,10 +332,12 @@ class Compiler
*/
public static function switchOpen(Tokenizer $tokens, Scope $scope)
{
$scope["expr"] = $scope->tpl->parseExpr($tokens);
$expr = $scope->tpl->parseExpr($tokens);
$scope["case"] = array();
$scope["last"] = array();
$scope["default"] = '';
$scope["var"] = $scope->tpl->tmpVar();
$scope["expr"] = $scope["var"].' = strval('.$expr.')';
// lazy init
return '';
}
@ -409,13 +411,16 @@ class Compiler
public static function switchClose(Tokenizer $tokens, Scope $scope)
{
self::_caseResort($scope);
$expr = $scope["expr"];
$code = "";
$expr = $scope["var"];
$code = $scope["expr"].";\n";
$default = $scope["default"];
foreach ($scope["case"] as $case => $content) {
if(is_numeric($case)) {
$case = "'$case'";
}
$code .= "if($expr == $case) {\n?>$content<?php\n} else";
}
$code .= " {\n?>$default<?php\n}";
$code .= " {\n?>$default<?php\n}\nunset(".$scope["var"].")";
return $code;
}

View File

@ -622,7 +622,7 @@ class Template extends Render
$var = false;
}
if ($tokens->is('?', '!')) {
$term = $this->parseTernary($tokens, $term, $tokens->current());
$term = $this->parseTernary($tokens, $term, $var);
$var = false;
}
$exp[] = $term;
@ -873,35 +873,59 @@ class Template extends Render
*
* @param Tokenizer $tokens
* @param $var
* @param $type
* @param $is_var
* @return string
* @throws UnexpectedTokenException
*/
public function parseTernary(Tokenizer $tokens, $var, $type)
public function parseTernary(Tokenizer $tokens, $var, $is_var)
{
$empty = ($type === "?");
$empty = $tokens->is('?');
$tokens->next();
if ($tokens->is(":")) {
$tokens->next();
if ($empty) {
return '(empty(' . $var . ') ? (' . $this->parseExpr($tokens) . ') : ' . $var . ')';
if($is_var) {
return '(empty(' . $var . ') ? (' . $this->parseExpr($tokens) . ') : ' . $var . ')';
} else {
return '(' . $var . ' ?: (' . $this->parseExpr($tokens) . ')';
}
} else {
return '(isset(' . $var . ') ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))';
if($is_var) {
return '(isset(' . $var . ') ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))';
} else {
return '((' . $var . ' !== null) ? ' . $var . ' : (' . $this->parseExpr($tokens) . '))';
}
}
} elseif ($tokens->is(Tokenizer::MACRO_BINARY, Tokenizer::MACRO_BOOLEAN, Tokenizer::MACRO_MATH) || !$tokens->valid()) {
if ($empty) {
return '!empty(' . $var . ')';
if($is_var) {
return '!empty(' . $var . ')';
} else {
return '(' . $var . ')';
}
} else {
return 'isset(' . $var . ')';
if($is_var) {
return 'isset(' . $var . ')';
} else {
return '(' . $var . ' !== null)';
}
}
} else {
$expr1 = $this->parseExpr($tokens);
$tokens->need(':')->skip();
$expr2 = $this->parseExpr($tokens);
if ($empty) {
return '(empty(' . $var . ') ? ' . $expr2 . ' : ' . $expr1 . ')';
if($is_var) {
return '(empty(' . $var . ') ? ' . $expr2 . ' : ' . $expr1 . ')';
} else {
return '(' . $var . ' ? ' . $expr1 . ' : ' . $expr2 . ')';
}
} else {
return '(isset(' . $var . ') ? ' . $expr1 . ' : ' . $expr2 . ')';
if($is_var) {
return '(isset(' . $var . ') ? ' . $expr1 . ' : ' . $expr2 . ')';
} else {
return '((' . $var . ' !== null) ? ' . $expr1 . ' : ' . $expr2 . ')';
}
}
}
}
@ -1035,22 +1059,23 @@ class Template extends Render
*/
public function parseScalar(Tokenizer $tokens)
{
$_scalar = "";
$token = $tokens->key();
switch ($token) {
case T_CONSTANT_ENCAPSED_STRING:
case T_LNUMBER:
case T_DNUMBER:
$_scalar .= $tokens->getAndNext();
return $tokens->getAndNext();
break;
case T_ENCAPSED_AND_WHITESPACE:
case '"':
$_scalar .= $this->parseQuote($tokens);
return $this->parseQuote($tokens);
break;
case '$':
$tokens->next()->need('.')->next()->need(T_CONST)->next();
return 'constant('.$this->parseName($tokens).')';
default:
throw new UnexpectedTokenException($tokens);
}
return $_scalar;
}
/**

View File

@ -1,6 +1,8 @@
<?php
require_once __DIR__ . "/../vendor/autoload.php";
$loader = include(__DIR__ . "/../vendor/autoload.php");
/* @var Composer\Autoload\ClassLoader $loader */
$loader->add('Fenom', __DIR__.'/cases');
define('FENOM_RESOURCES', __DIR__ . "/resources");