From b6f0347bc05e58a5275345ea4638c0e62d934763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Sun, 14 Jan 2024 00:40:23 +0100 Subject: [PATCH] Add new "find" filter This filter returns the first _value_ matching the given arrow function or null Attempt to solve #3962 (open to any feedback) --- src/Extension/CoreExtension.php | 17 ++++++++++++ tests/Fixtures/filters/find.test | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/Fixtures/filters/find.test diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 3a3caa9fe0..aa78c3a256 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -218,6 +218,7 @@ public function getFilters(): array new TwigFilter('filter', [self::class, 'arrayFilter'], ['needs_environment' => true]), new TwigFilter('map', [self::class, 'arrayMap'], ['needs_environment' => true]), new TwigFilter('reduce', [self::class, 'arrayReduce'], ['needs_environment' => true]), + new TwigFilter('find', [self::class, 'arrayFind'], ['needs_environment' => true]), // string/array filters new TwigFilter('reverse', [self::class, 'reverseFilter'], ['needs_environment' => true]), @@ -1766,6 +1767,22 @@ public static function arrayFilter(Environment $env, $array, $arrow) return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow); } + /** + * @internal + */ + public static function arrayFind(Environment $env, $array, $arrow) + { + self::checkArrowInSandbox($env, $arrow, 'find', 'filter'); + + foreach ($array as $k => $v) { + if ($arrow($v, $k)) { + return $v; + } + } + + return null; + } + /** * @internal */ diff --git a/tests/Fixtures/filters/find.test b/tests/Fixtures/filters/find.test new file mode 100644 index 0000000000..3d1dbd422c --- /dev/null +++ b/tests/Fixtures/filters/find.test @@ -0,0 +1,46 @@ +--TEST-- +"filter" filter +--TEMPLATE-- + +{{ [1, 2]|find((v) => v > 3) }} + +{{ [1, 5, 3, 4, 5]|find((v) => v > 3) }} + +{{ [1, 5, 3, 4, 5]|find((v) => v > 3) }} + +{{ {a: 1, b: 2, c: 5, d: 8}|find(v => v > 3) }} + +{{ {a: 1, b: 2, c: 5, d: 8}|find((v, k) => (v > 3) and (k != "c")) }} + +{{ [1, 5, 3, 4, 5]|find(v => v > 3) }} + +{{ it|find((v) => v > 3) }} + +{{ ita|find(v => v > 3) }} + +{{ xml|find(x => true) }} + +--DATA-- +return [ + 'it' => new \ArrayIterator(['a' => 1, 'b' => 2, 'c' => 5, 'd' => 8]), + 'ita' => new Twig\Tests\IteratorAggregateStub(['a' => 1, 'b' => 2, 'c' => 5, 'd' => 8]), + 'xml' => new \SimpleXMLElement('foobarbaz'), +] +--EXPECT-- + + +5 + +5 + +5 + +8 + +5 + +5 + +5 + +foo