From 91aeacbf3591c3126e39ca84faf6f4dc06254864 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 9 Feb 2022 12:59:14 +0200 Subject: [PATCH] formula null coalescing --- .../ComparisonGroup/NullCoalescingType.php | 59 ++++++++++++++++++ application/Espo/Core/Formula/Parser.php | 2 + .../unit/Espo/Core/Formula/EvaluatorTest.php | 60 +++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 application/Espo/Core/Formula/Functions/ComparisonGroup/NullCoalescingType.php diff --git a/application/Espo/Core/Formula/Functions/ComparisonGroup/NullCoalescingType.php b/application/Espo/Core/Formula/Functions/ComparisonGroup/NullCoalescingType.php new file mode 100644 index 0000000000..ca1e60ee63 --- /dev/null +++ b/application/Espo/Core/Formula/Functions/ComparisonGroup/NullCoalescingType.php @@ -0,0 +1,59 @@ +throwTooFewArguments(); + } + + $array = []; + + foreach ($args as $arg) { + $array[] = $arg; + } + + foreach (array_slice($array, 0, -1) as $arg) { + $value = $this->evaluate($arg); + + if ($value !== null) { + return $value; + } + } + + return $this->evaluate($array[count($array) - 1]); + } +} diff --git a/application/Espo/Core/Formula/Parser.php b/application/Espo/Core/Formula/Parser.php index d5cf3c6ab2..6952bbd856 100644 --- a/application/Espo/Core/Formula/Parser.php +++ b/application/Espo/Core/Formula/Parser.php @@ -40,6 +40,7 @@ class Parser { private $priorityList = [ ['='], + ['??'], ['||'], ['&&'], ['==', '!=', '>', '<', '>=', '<='], @@ -49,6 +50,7 @@ class Parser private $operatorMap = [ '=' => 'assign', + '??' => 'comparison\\nullCoalescing', '||' => 'logical\\or', '&&' => 'logical\\and', '+' => 'numeric\\summation', diff --git a/tests/unit/Espo/Core/Formula/EvaluatorTest.php b/tests/unit/Espo/Core/Formula/EvaluatorTest.php index c361c1b541..3a7bf6b4be 100644 --- a/tests/unit/Espo/Core/Formula/EvaluatorTest.php +++ b/tests/unit/Espo/Core/Formula/EvaluatorTest.php @@ -704,4 +704,64 @@ class EvaluatorTest extends \PHPUnit\Framework\TestCase $this->evaluator->process($expression, null) ); } + + public function testNullCoalescing1(): void + { + $expression = "null ?? 1"; + + $this->assertSame( + 1, + $this->evaluator->process($expression, null) + ); + } + + public function testNullCoalescing2(): void + { + $expression = "(null) ?? 1 ?? 0"; + + $this->assertSame( + 1, + $this->evaluator->process($expression, null) + ); + } + + public function testNullCoalescing3(): void + { + $expression = "(null) ?? ifThenElse(false, 1, null) ?? 0"; + + $this->assertSame( + 0, + $this->evaluator->process($expression, null) + ); + } + + public function testNullCoalescing4(): void + { + $expression = "null ?? (1 ?? 0)"; + + $this->assertSame( + 1, + $this->evaluator->process($expression, null) + ); + } + + public function testNullCoalescing5(): void + { + $expression = "null ?? 1 + 2"; + + $this->assertSame( + 3, + $this->evaluator->process($expression, null) + ); + } + + public function testNullCoalescing6(): void + { + $expression = "null ?? true || false"; + + $this->assertSame( + true, + $this->evaluator->process($expression, null) + ); + } }