From 7050bc82dd25c54095891abf8f6ec5701598a787 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 4 Jul 2023 10:04:29 +0200 Subject: [PATCH] [ExpressionLanguage] Remove deprecated code paths --- UPGRADE-7.0.md | 5 +++ .../Component/ExpressionLanguage/CHANGELOG.md | 5 +++ .../ExpressionLanguage/Node/BinaryNode.php | 42 +++++++------------ .../Tests/ExpressionLanguageTest.php | 2 +- .../Tests/Node/BinaryNodeTest.php | 23 +++++----- .../ExpressionLanguage/composer.json | 1 - 6 files changed, 36 insertions(+), 42 deletions(-) diff --git a/UPGRADE-7.0.md b/UPGRADE-7.0.md index 4c294b66bffc8..1a9e94fbc18b9 100644 --- a/UPGRADE-7.0.md +++ b/UPGRADE-7.0.md @@ -45,6 +45,11 @@ DoctrineBridge * DoctrineBridge now requires `doctrine/event-manager:^2` * Add parameter `$isSameDatabase` to `DoctrineTokenProvider::configureSchema()` +ExpressionLanguage +------------------ + + * The `in` and `not in` operators now use strict comparison + Filesystem ---------- diff --git a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md index b06620cd79acb..f54f943ac15de 100644 --- a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md +++ b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * The `in` and `not in` operators now use strict comparison + 6.3 --- diff --git a/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php b/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php index 48331167bd275..d1a98a04fde31 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php @@ -30,8 +30,8 @@ class BinaryNode extends Node private const FUNCTIONS = [ '**' => 'pow', '..' => 'range', - 'in' => '\\'.self::class.'::inArray', - 'not in' => '!\\'.self::class.'::inArray', + 'in' => '\\in_array', + 'not in' => '!\\in_array', 'contains' => 'str_contains', 'starts with' => 'str_starts_with', 'ends with' => 'str_ends_with', @@ -71,9 +71,14 @@ public function compile(Compiler $compiler): void ->compile($this->nodes['left']) ->raw(', ') ->compile($this->nodes['right']) - ->raw(')') ; + if ('in' === $operator || 'not in' === $operator) { + $compiler->raw(', true'); + } + + $compiler->raw(')'); + return; } @@ -100,12 +105,11 @@ public function evaluate(array $functions, array $values): mixed if (isset(self::FUNCTIONS[$operator])) { $right = $this->nodes['right']->evaluate($functions, $values); - if ('not in' === $operator) { - return !self::inArray($left, $right); - } - $f = self::FUNCTIONS[$operator]; - - return $f($left, $right); + return match ($operator) { + 'in' => \in_array($left, $right, true), + 'not in' => !\in_array($left, $right, true), + default => self::FUNCTIONS[$operator]($left, $right), + }; } switch ($operator) { @@ -143,9 +147,9 @@ public function evaluate(array $functions, array $values): mixed case '<=': return $left <= $right; case 'not in': - return !self::inArray($left, $right); + return !\in_array($left, $right, true); case 'in': - return self::inArray($left, $right); + return \in_array($left, $right, true); case '+': return $left + $right; case '-': @@ -176,22 +180,6 @@ public function toArray(): array return ['(', $this->nodes['left'], ' '.$this->attributes['operator'].' ', $this->nodes['right'], ')']; } - /** - * @internal to be replaced by an inline strict call to in_array() in version 7.0 - */ - public static function inArray($value, array $array): bool - { - if (false === $key = array_search($value, $array)) { - return false; - } - - if (!\in_array($value, $array, true)) { - trigger_deprecation('symfony/expression-language', '6.3', 'The "in" operator will use strict comparisons in Symfony 7.0. Loose match found with key "%s" for value %s. Normalize the array parameter so it only has the expected types or implement loose matching in your own expression function.', $key, json_encode($value)); - } - - return true; - } - private function evaluateMatches(string $regexp, ?string $str): int { set_error_handler(function ($t, $m) use ($regexp) { diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index bef2395e859c6..b2e072b5785bc 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -269,7 +269,7 @@ public function testOperatorCollisions() $expressionLanguage = new ExpressionLanguage(); $expression = 'foo.not in [bar]'; $compiled = $expressionLanguage->compile($expression, ['foo', 'bar']); - $this->assertSame('\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray($foo->not, [0 => $bar])', $compiled); + $this->assertSame('\in_array($foo->not, [0 => $bar], true)', $compiled); $result = $expressionLanguage->evaluate($expression, ['foo' => (object) ['not' => 'test'], 'bar' => 'test']); $this->assertTrue($result); diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php index 610c6b0dd289b..bfbcd2dd5b75f 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\ExpressionLanguage\Compiler; use Symfony\Component\ExpressionLanguage\Node\ArrayNode; use Symfony\Component\ExpressionLanguage\Node\BinaryNode; @@ -21,8 +20,6 @@ class BinaryNodeTest extends AbstractNodeTestCase { - use ExpectDeprecationTrait; - public static function getEvaluateData(): array { $array = new ArrayNode(); @@ -116,10 +113,10 @@ public static function getCompileData(): array ['pow(5, 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))], ['("a" . "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))], - ['\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("a", [0 => "a", 1 => "b"])', new BinaryNode('in', new ConstantNode('a'), $array)], - ['\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("c", [0 => "a", 1 => "b"])', new BinaryNode('in', new ConstantNode('c'), $array)], - ['!\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("c", [0 => "a", 1 => "b"])', new BinaryNode('not in', new ConstantNode('c'), $array)], - ['!\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("a", [0 => "a", 1 => "b"])', new BinaryNode('not in', new ConstantNode('a'), $array)], + ['\in_array("a", [0 => "a", 1 => "b"], true)', new BinaryNode('in', new ConstantNode('a'), $array)], + ['\in_array("c", [0 => "a", 1 => "b"], true)', new BinaryNode('in', new ConstantNode('c'), $array)], + ['!\in_array("c", [0 => "a", 1 => "b"], true)', new BinaryNode('not in', new ConstantNode('c'), $array)], + ['!\in_array("a", [0 => "a", 1 => "b"], true)', new BinaryNode('not in', new ConstantNode('a'), $array)], ['range(1, 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))], @@ -219,17 +216,17 @@ public function testCompileMatchesWithInvalidRegexpAsExpression() } /** - * @group legacy + * @testWith [1] + * ["true"] */ - public function testInOperatorStrictness() + public function testInOperatorStrictness(mixed $value) { $array = new ArrayNode(); - $array->addElement(new ConstantNode('a')); + $array->addElement(new ConstantNode('1')); $array->addElement(new ConstantNode(true)); - $node = new BinaryNode('in', new ConstantNode('b'), $array); + $node = new BinaryNode('in', new ConstantNode($value), $array); - $this->expectDeprecation('Since symfony/expression-language 6.3: The "in" operator will use strict comparisons in Symfony 7.0. Loose match found with key "1" for value "b". Normalize the array parameter so it only has the expected types or implement loose matching in your own expression function.'); - $this->assertTrue($node->evaluate([], [])); + $this->assertFalse($node->evaluate([], [])); } } diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index a516235ae9c32..b1652e8c8ee6f 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/cache": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" },