From d5ecc1bc20f91468242d5a3d7807ee581f793bf2 Mon Sep 17 00:00:00 2001 From: bzick Date: Thu, 5 Sep 2013 03:35:02 +0400 Subject: [PATCH] Fix {switch} and ternary operator --- .travis.yml | 2 -- docs/settings.md | 1 - docs/tags/switch.md | 12 +++++++--- src/Fenom/Compiler.php | 13 +++++++---- src/Fenom/Template.php | 53 +++++++++++++++++++++++++++++++----------- tests/autoload.php | 4 +++- 6 files changed, 60 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index b31821d..e1dd962 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,4 @@ php: - 5.4 - 5.5 -before_script: composer install - script: phpunit \ No newline at end of file diff --git a/docs/settings.md b/docs/settings.md index 76794b1..ad88c34 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -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( diff --git a/docs/tags/switch.md b/docs/tags/switch.md index 3df5f9b..1a19599 100644 --- a/docs/tags/switch.md +++ b/docs/tags/switch.md @@ -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 } {case } @@ -9,7 +15,7 @@ Tag {switch} ... {case } ... -{default} +{default case } ... {/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 diff --git a/src/Fenom/Compiler.php b/src/Fenom/Compiler.php index b54d203..5629c01 100644 --- a/src/Fenom/Compiler.php +++ b/src/Fenom/Compiler.php @@ -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$default$defaultis('?', '!')) { - $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; } /** diff --git a/tests/autoload.php b/tests/autoload.php index 685492c..311949c 100644 --- a/tests/autoload.php +++ b/tests/autoload.php @@ -1,6 +1,8 @@ add('Fenom', __DIR__.'/cases'); define('FENOM_RESOURCES', __DIR__ . "/resources");