From 76bd9721f848d4a851518f2490b58b7309e9ac31 Mon Sep 17 00:00:00 2001 From: John Koster Date: Fri, 16 Feb 2024 16:07:53 -0600 Subject: [PATCH] [4.x] Antlers: stops double-initial execution of tags within conditions (#9504) --- .../Language/Runtime/ConditionProcessor.php | 1 - .../Language/Runtime/Sandbox/Environment.php | 6 ++- tests/Antlers/Sandbox/ConditionalsTest.php | 54 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/View/Antlers/Language/Runtime/ConditionProcessor.php b/src/View/Antlers/Language/Runtime/ConditionProcessor.php index 3d22965796..8a2a43319a 100644 --- a/src/View/Antlers/Language/Runtime/ConditionProcessor.php +++ b/src/View/Antlers/Language/Runtime/ConditionProcessor.php @@ -104,7 +104,6 @@ public function process(ConditionNode $node, $data) } if ($result == true) { - $this->processor->setIsConditionProcessor($condValueToRestore); return $branch; diff --git a/src/View/Antlers/Language/Runtime/Sandbox/Environment.php b/src/View/Antlers/Language/Runtime/Sandbox/Environment.php index 1be0064e03..f39a8ed31f 100644 --- a/src/View/Antlers/Language/Runtime/Sandbox/Environment.php +++ b/src/View/Antlers/Language/Runtime/Sandbox/Environment.php @@ -1567,7 +1567,11 @@ public function getValue($val) $varName = $this->nameOf($val); if ($val->isInterpolationReference) { - $interpolationValue = $this->adjustValue($this->nodeProcessor->reduceInterpolatedVariable($val), $val); + if (array_key_exists($varName->normalizedReference, $this->data)) { + $interpolationValue = $this->adjustValue($this->data[$varName->normalizedReference], $val); + } else { + $interpolationValue = $this->adjustValue($this->nodeProcessor->reduceInterpolatedVariable($val), $val); + } // If the currently active node is an instance of ArithmeticNodeContract, // we will ask the runtime type coercion to convert whatever value diff --git a/tests/Antlers/Sandbox/ConditionalsTest.php b/tests/Antlers/Sandbox/ConditionalsTest.php index 7c905b4e87..f355bae547 100644 --- a/tests/Antlers/Sandbox/ConditionalsTest.php +++ b/tests/Antlers/Sandbox/ConditionalsTest.php @@ -2,6 +2,7 @@ namespace Tests\Antlers\Sandbox; +use Statamic\Tags\Tags; use Tests\Antlers\ParserTestCase; class ConditionalsTest extends ParserTestCase @@ -47,6 +48,59 @@ public function test_sandbox_will_defer_collapsing_arrays() $this->assertSame('no', $this->renderString($template, $data)); } + public function test_tags_are_not_initially_evaluated_twice() + { + $template = <<<'EOT' +{{ if {switch between='yes|no'} == 'yes' }}yes{{ else }}no{{ /if }}{{ if {switch between='yes|no'} == 'yes' }}yes{{ else }}no{{ /if }} +EOT; + + $this->assertSame('yesno', $this->renderString($template, [], true)); + } + + public function test_tags_are_evaluated_twice_if_called_twice() + { + $template = <<<'EOT' +{{ if {switch between='yes|no'} == 'yes' && {switch between='yes|no'} == 'no' }}yes{{ else }}no{{ /if }}{{ if {switch between='yes|no'} == 'yes' && {switch between='yes|no'} == 'no' }}yes{{ else }}no{{ /if }}{{ if {switch between='yes|no'} == 'no' && {switch between='yes|no'} == 'yes' }}yes{{ else }}no{{ /if }} +EOT; + + $this->assertSame('yesyesno', $this->renderString($template, [], true)); + } + + public function test_value_adjustments_inside_of_conditionals() + { + $template = <<<'EOT' +{{ if 'bob' == 'bo{c}' }}yes{{ else }}no{{ /if }} +EOT; + $this->assertSame('yes', $this->renderString($template, ['c' => 'b'], false)); + } + + public function test_many_tag_value_adjustments_inside_of_conditionals() + { + $template = <<<'EOT' +{{ if 'one_{switch between='yes|no'}' == 'one_yes' && 'two_{switch between='yes|no'}' == 'two_no' }}yes{{ else }}no{{ /if }} +EOT; + + $this->assertSame('yes', $this->renderString($template, [], true)); + } + + public function test_value_adjustments_resolved_tag_values() + { + (new class extends Tags + { + protected static $handle = 'the_tag'; + + public function index() + { + return 'bob'; + } + })::register(); + + $template = <<<'EOT' +{{ if 'bob' == '{the_tag}' }}yes{{ else }}no{{ /if }} +EOT; + $this->assertSame('yes', $this->renderString($template, [], true)); + } + public function test_sandbox_evaluates_simple_boolean_expressions() { $result = $this->getBoolResult('true == false', []);