mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-12 02:16:41 +00:00
Add "some" and "every" filters
This commit is contained in:
@@ -80,7 +80,7 @@ class ExpressionParser
|
|||||||
} elseif (isset($op['callable'])) {
|
} elseif (isset($op['callable'])) {
|
||||||
$expr = $op['callable']($this->parser, $expr);
|
$expr = $op['callable']($this->parser, $expr);
|
||||||
} else {
|
} else {
|
||||||
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
|
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence'], true);
|
||||||
$class = $op['class'];
|
$class = $op['class'];
|
||||||
$expr = new $class($expr, $expr1, $token->getLine());
|
$expr = new $class($expr, $expr1, $token->getLine());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ use Twig\Node\Expression\Binary\EqualBinary;
|
|||||||
use Twig\Node\Expression\Binary\FloorDivBinary;
|
use Twig\Node\Expression\Binary\FloorDivBinary;
|
||||||
use Twig\Node\Expression\Binary\GreaterBinary;
|
use Twig\Node\Expression\Binary\GreaterBinary;
|
||||||
use Twig\Node\Expression\Binary\GreaterEqualBinary;
|
use Twig\Node\Expression\Binary\GreaterEqualBinary;
|
||||||
|
use Twig\Node\Expression\Binary\HasEveryBinary;
|
||||||
|
use Twig\Node\Expression\Binary\HasSomeBinary;
|
||||||
use Twig\Node\Expression\Binary\InBinary;
|
use Twig\Node\Expression\Binary\InBinary;
|
||||||
use Twig\Node\Expression\Binary\LessBinary;
|
use Twig\Node\Expression\Binary\LessBinary;
|
||||||
use Twig\Node\Expression\Binary\LessEqualBinary;
|
use Twig\Node\Expression\Binary\LessEqualBinary;
|
||||||
@@ -284,6 +286,8 @@ final class CoreExtension extends AbstractExtension
|
|||||||
'matches' => ['precedence' => 20, 'class' => MatchesBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
'matches' => ['precedence' => 20, 'class' => MatchesBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
'starts with' => ['precedence' => 20, 'class' => StartsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
'starts with' => ['precedence' => 20, 'class' => StartsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
'ends with' => ['precedence' => 20, 'class' => EndsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
'ends with' => ['precedence' => 20, 'class' => EndsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
|
'has some' => ['precedence' => 20, 'class' => HasSomeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
|
'has every' => ['precedence' => 20, 'class' => HasEveryBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
'..' => ['precedence' => 25, 'class' => RangeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
'..' => ['precedence' => 25, 'class' => RangeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
'+' => ['precedence' => 30, 'class' => AddBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
'+' => ['precedence' => 30, 'class' => AddBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
'-' => ['precedence' => 30, 'class' => SubBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
'-' => ['precedence' => 30, 'class' => SubBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
||||||
@@ -1678,6 +1682,32 @@ function twig_array_reduce(Environment $env, $array, $arrow, $initial = null)
|
|||||||
return array_reduce($array, $arrow, $initial);
|
return array_reduce($array, $arrow, $initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function twig_array_some(Environment $env, $array, $arrow)
|
||||||
|
{
|
||||||
|
twig_check_arrow_in_sandbox($env, $arrow, 'some', 'filter');
|
||||||
|
|
||||||
|
foreach ($array as $k => $v) {
|
||||||
|
if ($arrow($v, $k)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function twig_array_every(Environment $env, $array, $arrow)
|
||||||
|
{
|
||||||
|
twig_check_arrow_in_sandbox($env, $arrow, 'every', 'filter');
|
||||||
|
|
||||||
|
foreach ($array as $k => $v) {
|
||||||
|
if (!$arrow($v, $k)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function twig_check_arrow_in_sandbox(Environment $env, $arrow, $thing, $type)
|
function twig_check_arrow_in_sandbox(Environment $env, $arrow, $thing, $type)
|
||||||
{
|
{
|
||||||
if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
|
if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Twig\Node\Expression\Binary;
|
||||||
|
|
||||||
|
use Twig\Compiler;
|
||||||
|
|
||||||
|
class HasEveryBinary extends AbstractBinary
|
||||||
|
{
|
||||||
|
public function compile(Compiler $compiler): void
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('twig_array_every($this->env, ')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Compiler $compiler): Compiler
|
||||||
|
{
|
||||||
|
return $compiler->raw('');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Twig\Node\Expression\Binary;
|
||||||
|
|
||||||
|
use Twig\Compiler;
|
||||||
|
|
||||||
|
class HasSomeBinary extends AbstractBinary
|
||||||
|
{
|
||||||
|
public function compile(Compiler $compiler): void
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('twig_array_some($this->env, ')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Compiler $compiler): Compiler
|
||||||
|
{
|
||||||
|
return $compiler->raw('');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
--TEST--
|
||||||
|
Twig supports the "has every" operator
|
||||||
|
--TEMPLATE--
|
||||||
|
{% if [0, 2, 4] has every v => 0 == v % 2 %}Every{% else %}Not every{% endif %} items are even in array
|
||||||
|
{{ ([0, 2, 4] has every v => 0 == v % 2) ? 'Every' : 'Not every' }} items are even in array
|
||||||
|
{{ ({ a: 0, b: 2, c: 4 } has every v => 0 == v % 2) ? 'Every' : 'Not every' }} items are even in object
|
||||||
|
{{ ({ a: 0, b: 2, c: 4 } has every (v, k) => "d" > k)? 'Every' : 'Not every' }} keys are before "d" in object
|
||||||
|
{{ (it has every v => 0 == v % 2) ? 'Every' : 'Not every' }} items are even in iterator
|
||||||
|
{{ ([0, 1, 2] has every v => 0 == v % 2) ? 'Every' : 'Not every' }} items are even in array
|
||||||
|
--DATA--
|
||||||
|
return ['it' => new \ArrayIterator([0, 2, 4])]
|
||||||
|
--EXPECT--
|
||||||
|
Every items are even in array
|
||||||
|
Every items are even in array
|
||||||
|
Every items are even in object
|
||||||
|
Every keys are before "d" in object
|
||||||
|
Every items are even in iterator
|
||||||
|
Not every items are even in array
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
--TEST--
|
||||||
|
Twig supports the "has some" operator
|
||||||
|
--TEMPLATE--
|
||||||
|
{% if [1, 2, 3] has some v => 0 == v % 2 %}At least one{% else %}No{% endif %} item is even in array
|
||||||
|
{{ ([1, 2, 3] has some v => 0 == v % 2) ? 'At least one' : 'No' }} item is even in array
|
||||||
|
{{ ({ a: 1, b: 2, c: 3 } has some v => 0 == v % 2) ? 'At least one' : 'No' }} item is even in object
|
||||||
|
{{ ({ a: 1, b: 2, c: 3 } has some (v, k) => "b" == k)? 'At least one' : 'No' }} key is "b" in object
|
||||||
|
{{ (it has some v => 0 == v % 2) ? 'At least one' : 'No' }} item is even in iterator
|
||||||
|
{{ ([1, 3, 5] has some v => 0 == v % 2) ? 'At least one' : 'No' }} item is even in array
|
||||||
|
--DATA--
|
||||||
|
return ['it' => new \ArrayIterator([1, 2, 3])]
|
||||||
|
--EXPECT--
|
||||||
|
At least one item is even in array
|
||||||
|
At least one item is even in array
|
||||||
|
At least one item is even in object
|
||||||
|
At least one key is "b" in object
|
||||||
|
At least one item is even in iterator
|
||||||
|
No item is even in array
|
||||||
|
|
||||||
Reference in New Issue
Block a user