From 210c8e788340e824ed98dcd2fca7f19483efec5b Mon Sep 17 00:00:00 2001 From: Matthias Leuffen Date: Wed, 26 Jul 2017 19:02:49 +0200 Subject: [PATCH] Implemented {else} to {if} (#2) * Added Test for if/else * Added else construction --- .gitignore | 1 + README.md | 22 ++++++- src/TextTemplate.php | 103 ++++++++++++++++++++---------- test/templates.phpt | 4 ++ test/unit/tpls/07_if_else/_in.php | 5 ++ test/unit/tpls/07_if_else/_in.txt | 12 ++++ test/unit/tpls/07_if_else/out.txt | 5 ++ 7 files changed, 119 insertions(+), 33 deletions(-) create mode 100644 test/unit/tpls/07_if_else/_in.php create mode 100644 test/unit/tpls/07_if_else/_in.txt create mode 100644 test/unit/tpls/07_if_else/out.txt diff --git a/.gitignore b/.gitignore index f417e74..e26f5d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.idea /vendor +/test/output \ No newline at end of file diff --git a/README.md b/README.md index ccccba1..644f186 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,14 @@ TextTemplate supports infinite-nested loops and sequences. // 1. Define the Template $tplStr = << diff --git a/src/TextTemplate.php b/src/TextTemplate.php index 2e78a43..d4824d6 100644 --- a/src/TextTemplate.php +++ b/src/TextTemplate.php @@ -89,6 +89,20 @@ public function addFilter ($filterName, callable $filterFn) { } + public function _replaceElseIf ($input) { + $lines = explode("\n", $input); + for ($li=0; $li < count ($lines); $li++) { + $lines[$li] = preg_replace_callback('/\{else\}/im', + function ($matches) use (&$nestingIndex, &$indexCounter, &$li) { + return "{/if}{if ::NL_ELSE_FALSE}"; + }, + $lines[$li] + ); + + } + return implode ("\n", $lines); + } + /** * Tag-Nesting is done by initially adding an index to both the opening and the * closing tag. (By the way some cleanup is done) @@ -266,58 +280,83 @@ private function _getItemValue ($compName, $context) { } - private function _runIf ($context, $content, $cmdParam, $softFail=TRUE) { + private function _runIf ($context, $content, $cmdParam, $softFail=TRUE, &$ifConditionDidMatch) { //echo $cmdParam; - if ( ! preg_match('/([\"\']?.*?[\"\']?)\s*(==|<|>|!=)\s*([\"\']?.*[\"\']?)/i', $cmdParam, $matches)) - return "!! Invalid command sequence: '$cmdParam' !!"; - - //print_r ($matches); - - $comp1 = $this->_getItemValue(trim ($matches[1]), $context); - $comp2 = $this->_getItemValue(trim ($matches[3]), $context); - - //decho $comp1 . $comp2; - - $doIf = FALSE; - switch ($matches[2]) { - case "==": - $doIf = ($comp1 == $comp2); - break; - case "!=": - $doIf = ($comp1 != $comp2); - break; - case "<": - $doIf = ($comp1 < $comp2); - break; - case ">": - $doIf = ($comp1 > $comp2); - break; + $doIf = false; + + if (trim ($cmdParam) == "::NL_ELSE_FALSE") { + // This is the {else} path of a if construction + if ($ifConditionDidMatch == false) + $doIf = true; // Run the block if + + } else { + + if ( ! preg_match('/([\"\']?.*?[\"\']?)\s*(==|<|>|!=)\s*([\"\']?.*[\"\']?)/i', $cmdParam, $matches)) { + return "!! Invalid command sequence: '$cmdParam' !!"; + } + + //print_r ($matches); + + $comp1 = $this->_getItemValue(trim($matches[1]), $context); + $comp2 = $this->_getItemValue(trim($matches[3]), $context); + + //decho $comp1 . $comp2; + + + switch ($matches[2]) { + case "==": + $doIf = ($comp1 == $comp2); + break; + case "!=": + $doIf = ($comp1 != $comp2); + break; + case "<": + $doIf = ($comp1 < $comp2); + break; + case ">": + $doIf = ($comp1 > $comp2); + break; + } } if ( ! $doIf) return ""; + $ifConditionDidMatch = true; // Skip further else / elseif execution $content = $this->_parseBlock($context, $content, $softFail); $content = $this->_parseValueOfTags($context, $content, $softFail); return $content; } + public function _runIfElse ($context, $content, $softFail=TRUE, &$ifConditionDidMatch) { + if ($ifConditionDidMatch == true) + return ""; + $ifConditionDidMatch = true; // Skip further else / elseif execution + $content = $this->_parseBlock($context, $content, $softFail); + $content = $this->_parseValueOfTags($context, $content, $softFail); + return $content; + } + private function _parseBlock ($context, $block, $softFail=TRUE) { // (?!\{): Lookahead Regex: Don't touch double {{ - $result = preg_replace_callback('/\n?\{(?!=)(([a-z]+)[0-9]+)(.*?)\}(.*?)\n?\{\/\1\}/ism', - function ($matches) use ($context, $softFail) { - $command = $matches[2]; - $cmdParam = $matches[3]; - $content = $matches[4]; + $ifConditionDidMatch = []; // Array with nesting-Levels + $result = preg_replace_callback('/\n?\{(?!=)((?[a-z]+)(?[0-9]+))(?.*?)\}(?.*?)\n?\{\/\1\}/ism', + function ($matches) use ($context, $softFail, &$ifConditionDidMatch) { + $command = $matches["command"]; + $cmdParam = $matches["cmdParam"]; + $content = $matches["content"]; + $nestingLevel = $matches["nestingLevel"]; switch ($command) { case "for": return $this->_runFor($context, $content, $cmdParam, $softFail); case "if": - return $this->_runIf ($context, $content, $cmdParam, $softFail); + $ifConditionDidMatch[$nestingLevel] = false; + return $this->_runIf ($context, $content, $cmdParam, $softFail, $ifConditionDidMatch[$nestingLevel]); + default: return "!! Invalid command: '$command' !!"; @@ -350,7 +389,7 @@ public function apply ($params, $softFail=TRUE) { $text = $this->mTemplateText; $context = $params; - + $text = $this->_replaceElseIf($text); $text = $this->_replaceNestingLevels($text); $text = $this->_parseBlock($context, $text, $softFail); diff --git a/test/templates.phpt b/test/templates.phpt index 1e6a1ab..f34b671 100644 --- a/test/templates.phpt +++ b/test/templates.phpt @@ -17,6 +17,10 @@ use Tester\Assert; \Tester\Environment::setup(); +$in = "{ if xyz}{ if zzz}{=value}{ /if}{else}{/if}"; +$tt = new TextTemplate(); +$out = $tt->_replaceElseIf($in); +Assert::equal("{ if xyz}{ if zzz}{=value}{ /if}{/if}{if ::NL_ELSE_FALSE}{/if}", $out); $in = "{ if xyz}{ if zzz}{=value}{ /if}{/if}"; $tt = new TextTemplate(); diff --git a/test/unit/tpls/07_if_else/_in.php b/test/unit/tpls/07_if_else/_in.php new file mode 100644 index 0000000..162d97a --- /dev/null +++ b/test/unit/tpls/07_if_else/_in.php @@ -0,0 +1,5 @@ + TRUE +]; \ No newline at end of file diff --git a/test/unit/tpls/07_if_else/_in.txt b/test/unit/tpls/07_if_else/_in.txt new file mode 100644 index 0000000..4a34bb0 --- /dev/null +++ b/test/unit/tpls/07_if_else/_in.txt @@ -0,0 +1,12 @@ +1: Start +{if boolVal == TRUE} +2: Boolean is true +{else} +3: Some Line of Code +{/if} +{if boolVal == FALSE} +4: Boolean is true +{else} +5: Some Line of Code +{/if} +6: Some other text \ No newline at end of file diff --git a/test/unit/tpls/07_if_else/out.txt b/test/unit/tpls/07_if_else/out.txt new file mode 100644 index 0000000..16fad5c --- /dev/null +++ b/test/unit/tpls/07_if_else/out.txt @@ -0,0 +1,5 @@ +1: Start +2: Boolean is true +3: Some Line of Code +5: Some Line of Code +6: Some other text \ No newline at end of file