From 8ed4e786254eeae9eb705c074c8a737c42082b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=BCsges?= Date: Thu, 20 Feb 2020 09:34:02 +0100 Subject: [PATCH 1/5] Fix refactorTextNode --- src/Utils/TwigBuilder.php | 34 ++++++++++++++++++++++++++++--- tests/TextNodeTest.php | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 tests/TextNodeTest.php diff --git a/src/Utils/TwigBuilder.php b/src/Utils/TwigBuilder.php index 232222a..7dd53de 100644 --- a/src/Utils/TwigBuilder.php +++ b/src/Utils/TwigBuilder.php @@ -176,6 +176,7 @@ public function refactorCondition(string $condition): string $condition = str_replace('&&', 'and', $condition); $condition = str_replace('||', 'or', $condition); $condition = preg_replace('/!([^=])/', 'not $1', $condition); + $condition = str_replace('+', '~', $condition); $condition = str_replace('.length', '|length', $condition); $condition = str_replace('.trim', '|trim', $condition); @@ -188,10 +189,37 @@ public function refactorCondition(string $condition): string public function refactorTextNode(string $content): string { - $content = str_replace('.length', '|length', $content); - $content = str_replace('.trim', '|trim', $content); + $refactoredContent = ''; + $charsCount = mb_strlen($content, 'UTF-8'); + $open = false; + $lastChar = null; + $quoteChar = null; + $buffer = ''; + + for ($i = 0; $i < $charsCount; $i++) { + $char = mb_substr($content, $i, 1, 'UTF-8'); + if ($open === false) { + $refactoredContent .= $char; + if ($char === '{' && $lastChar === '{') { + $open = true; + } + } else { + $buffer .= $char; + if ($quoteChar === null && ($char === '"' || $char === '\'')) { + $quoteChar = $char; + } elseif ($quoteChar === $char && $lastChar !== '\\') { + $quoteChar = null; + } + if ($quoteChar === null && $char === '}' && $lastChar === '}') { + $open = false; + $refactoredContent .= $this->refactorCondition(trim($buffer, '}')) . '}}'; + $buffer = ''; + } + } + $lastChar = $char; + } - return $content; + return $refactoredContent; } public function createVariableOutput($varName, ?string $fallbackVariableName = null): string diff --git a/tests/TextNodeTest.php b/tests/TextNodeTest.php new file mode 100644 index 0000000..90329ce --- /dev/null +++ b/tests/TextNodeTest.php @@ -0,0 +1,42 @@ +
foo {{ bar.trim }}
'; + $expected = '
foo {{ bar|trim }}
'; + + $compiler = $this->createCompiler($html); + + $actual = $compiler->convert(); + + $this->assertEqualHtml($expected, $actual); + } + + public function testTextNodeNoReplace() + { + $html = ''; + $expected = '
foo.trim {{ \'foo === bar\' }}
'; + + $compiler = $this->createCompiler($html); + + $actual = $compiler->convert(); + + $this->assertEqualHtml($expected, $actual); + } + + public function testTextNodeDontCloseInQuote() + { + $html = ''; + $expected = '
{{ \'}}\' ~ foo|trim }}
'; + + $compiler = $this->createCompiler($html); + + $actual = $compiler->convert(); + + $this->assertEqualHtml($expected, $actual); + } +} From 71c67b9ce8683175bd897c00e1442557474883e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=BCsges?= Date: Thu, 20 Feb 2020 10:32:44 +0100 Subject: [PATCH 2/5] Update refactorTextNode --- src/Utils/TwigBuilder.php | 9 ++++++++- tests/TextNodeTest.php | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Utils/TwigBuilder.php b/src/Utils/TwigBuilder.php index 7dd53de..91a88c9 100644 --- a/src/Utils/TwigBuilder.php +++ b/src/Utils/TwigBuilder.php @@ -176,10 +176,17 @@ public function refactorCondition(string $condition): string $condition = str_replace('&&', 'and', $condition); $condition = str_replace('||', 'or', $condition); $condition = preg_replace('/!([^=])/', 'not $1', $condition); - $condition = str_replace('+', '~', $condition); $condition = str_replace('.length', '|length', $condition); $condition = str_replace('.trim', '|trim', $condition); + if (preg_match_all('/(\S+)\s*\+\s*(\S+)/', $condition, $matches, PREG_SET_ORDER )) { + foreach ($matches as $match) { + if (!is_numeric($match[1]) || !is_numeric($match[2])) { + $condition = str_replace($match[0], str_replace('+', '~', $match[0]), $condition); + } + } + } + foreach (Replacements::getConstants() as $constant => $value) { $condition = str_replace($value, Replacements::getSanitizedConstant($constant), $condition); } diff --git a/tests/TextNodeTest.php b/tests/TextNodeTest.php index 90329ce..31da565 100644 --- a/tests/TextNodeTest.php +++ b/tests/TextNodeTest.php @@ -39,4 +39,16 @@ public function testTextNodeDontCloseInQuote() $this->assertEqualHtml($expected, $actual); } + + public function testTextNodeNumbers() + { + $html = ''; + $expected = '
{{ 1 + 1 }}
'; + + $compiler = $this->createCompiler($html); + + $actual = $compiler->convert(); + + $this->assertEqualHtml($expected, $actual); + } } From 71b97afabd3f0a5aabc2880bf7bb94b0a7504004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=BCsges?= Date: Thu, 20 Feb 2020 11:49:49 +0100 Subject: [PATCH 3/5] Add convertTemplateString and convertConcat --- src/Utils/TwigBuilder.php | 48 ++++++++++++++++++++++++++++++++------- tests/TextNodeTest.php | 12 ++++++++++ 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/Utils/TwigBuilder.php b/src/Utils/TwigBuilder.php index 91a88c9..66c174c 100644 --- a/src/Utils/TwigBuilder.php +++ b/src/Utils/TwigBuilder.php @@ -179,13 +179,7 @@ public function refactorCondition(string $condition): string $condition = str_replace('.length', '|length', $condition); $condition = str_replace('.trim', '|trim', $condition); - if (preg_match_all('/(\S+)\s*\+\s*(\S+)/', $condition, $matches, PREG_SET_ORDER )) { - foreach ($matches as $match) { - if (!is_numeric($match[1]) || !is_numeric($match[2])) { - $condition = str_replace($match[0], str_replace('+', '~', $match[0]), $condition); - } - } - } + $condition = $this->convertConcat($condition); foreach (Replacements::getConstants() as $constant => $value) { $condition = str_replace($value, Replacements::getSanitizedConstant($constant), $condition); @@ -219,7 +213,8 @@ public function refactorTextNode(string $content): string } if ($quoteChar === null && $char === '}' && $lastChar === '}') { $open = false; - $refactoredContent .= $this->refactorCondition(trim($buffer, '}')) . '}}'; + $buffer = $this->convertTemplateString(trim($buffer, '}')); + $refactoredContent .= $this->refactorCondition($buffer) . '}}'; $buffer = ''; } } @@ -229,6 +224,43 @@ public function refactorTextNode(string $content): string return $refactoredContent; } + private function convertConcat($content) { + if (preg_match_all('/(\S+)(\s*\+\s*(\S+))+/', $content, $matches, PREG_SET_ORDER )) { + foreach ($matches as $match) { + $parts = explode('+', $match[0]); + $lastPart = null; + $convertedContent = ''; + foreach ($parts as $part) { + $part = trim($part); + if ($lastPart !== null) { + if (is_numeric($lastPart) && is_numeric($part)) { + $convertedContent .= ' + ' . $part; + } else { + $convertedContent .= ' ~ ' . $part; + } + } else { + $convertedContent = $part; + } + $lastPart = $part; + } + $content = str_replace($match[0], $convertedContent, $content); + } + } + + return $content; + } + + private function convertTemplateString($content) { + if (preg_match_all('/\`([^\`]+)\`/', $content, $matches, PREG_SET_ORDER )) { + foreach ($matches as $match) { + $match[1] = str_replace('${', '" ~ ', $match[1]); + $match[1] = str_replace('}', ' ~ "', $match[1]); + $content = str_replace($match[0], '"' . $match[1] . '"', $content); + } + } + return $content; + } + public function createVariableOutput($varName, ?string $fallbackVariableName = null): string { if ($fallbackVariableName) { diff --git a/tests/TextNodeTest.php b/tests/TextNodeTest.php index 31da565..d54bb29 100644 --- a/tests/TextNodeTest.php +++ b/tests/TextNodeTest.php @@ -51,4 +51,16 @@ public function testTextNodeNumbers() $this->assertEqualHtml($expected, $actual); } + + public function testTextNodeWithTemplateString() + { + $html = ''; + $expected = '
{{ "Var = " ~ var ~ "" }}
'; + + $compiler = $this->createCompiler($html); + + $actual = $compiler->convert(); + + $this->assertEqualHtml($expected, $actual); + } } From 0bcff46844939cebbad62333b9f2e05efb2231d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=BCsges?= Date: Fri, 21 Feb 2020 06:22:42 +0100 Subject: [PATCH 4/5] Update refactorCondition --- src/Utils/TwigBuilder.php | 9 +++++---- tests/TextNodeTest.php | 14 +------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/Utils/TwigBuilder.php b/src/Utils/TwigBuilder.php index 66c174c..f079a80 100644 --- a/src/Utils/TwigBuilder.php +++ b/src/Utils/TwigBuilder.php @@ -179,7 +179,8 @@ public function refactorCondition(string $condition): string $condition = str_replace('.length', '|length', $condition); $condition = str_replace('.trim', '|trim', $condition); - $condition = $this->convertConcat($condition); + $condition = str_replace('+', '~', $condition); +// $condition = $this->convertConcat($condition); foreach (Replacements::getConstants() as $constant => $value) { $condition = str_replace($value, Replacements::getSanitizedConstant($constant), $condition); @@ -253,9 +254,9 @@ private function convertConcat($content) { private function convertTemplateString($content) { if (preg_match_all('/\`([^\`]+)\`/', $content, $matches, PREG_SET_ORDER )) { foreach ($matches as $match) { - $match[1] = str_replace('${', '" ~ ', $match[1]); - $match[1] = str_replace('}', ' ~ "', $match[1]); - $content = str_replace($match[0], '"' . $match[1] . '"', $content); + $match[1] = str_replace('${', '\' ~ ', $match[1]); + $match[1] = str_replace('}', ' ~ \'', $match[1]); + $content = str_replace($match[0], '\'' . $match[1] . '\'', $content); } } return $content; diff --git a/tests/TextNodeTest.php b/tests/TextNodeTest.php index d54bb29..ec2a1ba 100644 --- a/tests/TextNodeTest.php +++ b/tests/TextNodeTest.php @@ -40,22 +40,10 @@ public function testTextNodeDontCloseInQuote() $this->assertEqualHtml($expected, $actual); } - public function testTextNodeNumbers() - { - $html = ''; - $expected = '
{{ 1 + 1 }}
'; - - $compiler = $this->createCompiler($html); - - $actual = $compiler->convert(); - - $this->assertEqualHtml($expected, $actual); - } - public function testTextNodeWithTemplateString() { $html = ''; - $expected = '
{{ "Var = " ~ var ~ "" }}
'; + $expected = '
{{ \'Var = \' ~ var ~ \'\' }}
'; $compiler = $this->createCompiler($html); From 0a2ffe842ae9138acec11a062607d649a972d12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20H=C3=BCsges?= Date: Fri, 21 Feb 2020 10:41:05 +0100 Subject: [PATCH 5/5] Update refactorCondition --- src/Utils/TwigBuilder.php | 3 +-- tests/TextNodeTest.php | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Utils/TwigBuilder.php b/src/Utils/TwigBuilder.php index da3e6fc..41e0e4d 100644 --- a/src/Utils/TwigBuilder.php +++ b/src/Utils/TwigBuilder.php @@ -214,7 +214,6 @@ private function refactorConditionPart($condition) { $condition = str_replace('.length', '|length', $condition); $condition = str_replace('.trim', '|trim', $condition); - $condition = str_replace('+', '~', $condition); // $condition = $this->convertConcat($condition); foreach (Replacements::getConstants() as $constant => $value) { @@ -261,7 +260,7 @@ public function refactorTextNode(string $content): string } private function convertConcat($content) { - if (preg_match_all('/(\S+)(\s*\+\s*(\S+))+/', $content, $matches, PREG_SET_ORDER )) { + if (preg_match_all('/(\S*)(\s*\+\s*(\S+))+/', $content, $matches, PREG_SET_ORDER )) { foreach ($matches as $match) { $parts = explode('+', $match[0]); $lastPart = null; diff --git a/tests/TextNodeTest.php b/tests/TextNodeTest.php index ec2a1ba..37469de 100644 --- a/tests/TextNodeTest.php +++ b/tests/TextNodeTest.php @@ -30,8 +30,8 @@ public function testTextNodeNoReplace() public function testTextNodeDontCloseInQuote() { - $html = ''; - $expected = '
{{ \'}}\' ~ foo|trim }}
'; + $html = ''; + $expected = '
{{ \'}}\' or foo|length }}
'; $compiler = $this->createCompiler($html); @@ -51,4 +51,17 @@ public function testTextNodeWithTemplateString() $this->assertEqualHtml($expected, $actual); } + + + public function testTextNodeNumbers() + { + $html = ''; + $expected = '
{{ 1 + 1 }}
'; + + $compiler = $this->createCompiler($html); + + $actual = $compiler->convert(); + + $this->assertEqualHtml($expected, $actual); + } }