Merge branch '3.x' into 4.x

* 3.x:
  Add new "find" filter
This commit is contained in:
Fabien Potencier
2024-08-04 13:40:16 +02:00
3 changed files with 120 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
``find``
========
.. versionadded:: 3.11
The ``find`` filter was added in Twig 3.11.
The ``find`` filter returns the first element of a sequence matching an arrow
function. The arrow function receives the value of the sequence:
.. code-block:: twig
{% set sizes = [34, 36, 38, 40, 42] %}
{{ sizes|find(v => v > 38) }}
{# output 40 #}
It also works with mappings:
.. code-block:: twig
{% set sizes = {
xxs: 32,
xs: 34,
s: 36,
m: 38,
l: 40,
xl: 42,
} %}
{{ sizes|find(v => v > 38) }}
{# output 40 #}
The arrow function also receives the key as a second argument:
.. code-block:: twig
{{ sizes|find((v, k) => 's' not in k) }}
{# output 38 #}
Note that the arrow function has access to the current context:
.. code-block:: twig
{% set my_size = 39 %}
{{ sizes|find(v => v >= my_size) }}
{# output 40 #}
Arguments
---------
* ``array``: The sequence or mapping
* ``arrow``: The arrow function
+17
View File
@@ -218,6 +218,7 @@ final class CoreExtension extends AbstractExtension
new TwigFilter('filter', self::filter(...), ['needs_environment' => true]),
new TwigFilter('map', self::map(...), ['needs_environment' => true]),
new TwigFilter('reduce', self::reduce(...), ['needs_environment' => true]),
new TwigFilter('find', [self::class, 'find'], ['needs_environment' => true]),
// string/array filters
new TwigFilter('reverse', self::reverse(...), ['needs_charset' => true]),
@@ -1755,6 +1756,22 @@ final class CoreExtension extends AbstractExtension
return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow);
}
/**
* @internal
*/
public static function find(Environment $env, $array, $arrow)
{
self::checkArrowInSandbox($env, $arrow, 'find', 'filter');
foreach ($array as $k => $v) {
if ($arrow($v, $k)) {
return $v;
}
}
return null;
}
/**
* @internal
*/
+46
View File
@@ -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('<?xml version="1.0" encoding="UTF-8"?><doc><elem>foo</elem><elem>bar</elem><elem>baz</elem></doc>'),
]
--EXPECT--
5
5
5
8
5
5
5
foo