mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-14 19:36:43 +00:00
Add new "find" filter
This commit is contained in:
committed by
Fabien Potencier
parent
ae04075ed1
commit
4e26251193
@@ -1,5 +1,6 @@
|
||||
# 3.11.0 (2024-XX-XX)
|
||||
|
||||
* Add the `find` filter
|
||||
* Fix optimizer mode validation in `OptimizerNodeVisitor`
|
||||
* Add the possibility to yield from a generator in `PrintNode`
|
||||
* Add the `shuffle` filter
|
||||
|
||||
@@ -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
|
||||
@@ -218,6 +218,7 @@ final class CoreExtension extends AbstractExtension
|
||||
new TwigFilter('filter', [self::class, 'filter'], ['needs_environment' => true]),
|
||||
new TwigFilter('map', [self::class, 'map'], ['needs_environment' => true]),
|
||||
new TwigFilter('reduce', [self::class, 'reduce'], ['needs_environment' => true]),
|
||||
new TwigFilter('find', [self::class, 'find'], ['needs_environment' => true]),
|
||||
|
||||
// string/array filters
|
||||
new TwigFilter('reverse', [self::class, 'reverse'], ['needs_charset' => true]),
|
||||
@@ -1775,6 +1776,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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user