mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-19 05:46:41 +00:00
Issue #3828: Add sequence and mapping tests
This commit is contained in:
@@ -3,9 +3,9 @@
|
|||||||
* Deprecate the second argument of `Twig\Node\Expression\CallExpression::compileArguments()`
|
* Deprecate the second argument of `Twig\Node\Expression\CallExpression::compileArguments()`
|
||||||
* Deprecate `Twig\ExpressionParser\parseHashExpression()` in favor of
|
* Deprecate `Twig\ExpressionParser\parseHashExpression()` in favor of
|
||||||
`Twig\ExpressionParser::parseMappingExpression()`
|
`Twig\ExpressionParser::parseMappingExpression()`
|
||||||
|
|
||||||
* Deprecate `Twig\ExpressionParser\parseArrayExpression()`` in favor of
|
* Deprecate `Twig\ExpressionParser\parseArrayExpression()`` in favor of
|
||||||
`Twig\ExpressionParser::parseSequenceExpression()`
|
`Twig\ExpressionParser::parseSequenceExpression()`
|
||||||
|
* Add `sequence` and `mapping` tests.
|
||||||
|
|
||||||
# 3.10.3 (2024-05-16)
|
# 3.10.3 (2024-05-16)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -28,7 +28,8 @@
|
|||||||
"symfony/polyfill-php80": "^1.22",
|
"symfony/polyfill-php80": "^1.22",
|
||||||
"symfony/deprecation-contracts": "^2.5|^3",
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
"symfony/polyfill-mbstring": "^1.3",
|
"symfony/polyfill-mbstring": "^1.3",
|
||||||
"symfony/polyfill-ctype": "^1.8"
|
"symfony/polyfill-ctype": "^1.8",
|
||||||
|
"symfony/polyfill-php81": "^1.29"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0",
|
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
.. code-block:: twig
|
.. code-block:: twig
|
||||||
|
|
||||||
{# evaluates to true if the foo variable is iterable #}
|
{# evaluates to true if the users variable is iterable #}
|
||||||
{% if users is iterable %}
|
{% if users is iterable %}
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
Hello {{ user }}!
|
Hello {{ user }}!
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
``mapping``
|
||||||
|
===========
|
||||||
|
|
||||||
|
``mapping`` checks if a variable is a mapping:
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
|
||||||
|
{% set users = {alice: "Alice Dupond", bob: "Bob Smith"} %}
|
||||||
|
{# evaluates to true if the users variable is a mapping #}
|
||||||
|
{% if users is mapping %}
|
||||||
|
{% for key, user in users %}
|
||||||
|
{{ key }}: {{ user }};
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
``sequence``
|
||||||
|
============
|
||||||
|
|
||||||
|
``sequence`` checks if a variable is a sequence:
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
|
||||||
|
{% set users = ["Alice", "Bob"] %}
|
||||||
|
{# evaluates to true if the users variable is a sequence #}
|
||||||
|
{% if users is sequence %}
|
||||||
|
{% for user in users %}
|
||||||
|
Hello {{ user }}!
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
@@ -260,6 +260,8 @@ final class CoreExtension extends AbstractExtension
|
|||||||
new TwigTest('constant', null, ['node_class' => ConstantTest::class]),
|
new TwigTest('constant', null, ['node_class' => ConstantTest::class]),
|
||||||
new TwigTest('empty', [self::class, 'testEmpty']),
|
new TwigTest('empty', [self::class, 'testEmpty']),
|
||||||
new TwigTest('iterable', 'is_iterable'),
|
new TwigTest('iterable', 'is_iterable'),
|
||||||
|
new TwigTest('sequence', [self::class, 'testSequence']),
|
||||||
|
new TwigTest('mapping', [self::class, 'testMapping']),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1285,6 +1287,56 @@ final class CoreExtension extends AbstractExtension
|
|||||||
return '' === $value || false === $value || null === $value || [] === $value;
|
return '' === $value || false === $value || null === $value || [] === $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a variable is a sequence.
|
||||||
|
*
|
||||||
|
* {# evaluates to true if the foo variable is a sequence #}
|
||||||
|
* {% if foo is sequence %}
|
||||||
|
* {# ... #}
|
||||||
|
* {% endif %}
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public static function testSequence($value): bool
|
||||||
|
{
|
||||||
|
if ($value instanceof \ArrayObject) {
|
||||||
|
$value = $value->getArrayCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value instanceof \Traversable) {
|
||||||
|
$value = iterator_to_array($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return \is_array($value) && array_is_list($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a variable is a mapping.
|
||||||
|
*
|
||||||
|
* {# evaluates to true if the foo variable is a mapping #}
|
||||||
|
* {% if foo is mapping %}
|
||||||
|
* {# ... #}
|
||||||
|
* {% endif %}
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public static function testMapping($value): bool
|
||||||
|
{
|
||||||
|
if ($value instanceof \ArrayObject) {
|
||||||
|
$value = $value->getArrayCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value instanceof \Traversable) {
|
||||||
|
$value = iterator_to_array($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (\is_array($value) && !array_is_list($value)) || \is_object($value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a template.
|
* Renders a template.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
--TEST--
|
||||||
|
"mapping" test
|
||||||
|
--TEMPLATE--
|
||||||
|
{{ empty is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ sequence is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ empty_array_obj is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ sequence_array_obj is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ mapping_array_obj is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ obj is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ mapping is mapping ? 'ok' : 'ko' }}
|
||||||
|
{{ string is mapping ? 'ok' : 'ko' }}
|
||||||
|
--DATA--
|
||||||
|
return [
|
||||||
|
'empty' => [],
|
||||||
|
'sequence' => [
|
||||||
|
'foo',
|
||||||
|
'bar',
|
||||||
|
'baz'
|
||||||
|
],
|
||||||
|
'empty_array_obj' => new \ArrayObject(),
|
||||||
|
'sequence_array_obj' => new \ArrayObject(['foo', 'bar']),
|
||||||
|
'mapping_array_obj' => new \ArrayObject(['foo' => 'bar']),
|
||||||
|
'obj' => new \stdClass(),
|
||||||
|
'mapping' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'bar' => 'foo'
|
||||||
|
],
|
||||||
|
'string' => 'test',
|
||||||
|
]
|
||||||
|
--EXPECT--
|
||||||
|
ko
|
||||||
|
ko
|
||||||
|
ko
|
||||||
|
ko
|
||||||
|
ok
|
||||||
|
ok
|
||||||
|
ok
|
||||||
|
ko
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
--TEST--
|
||||||
|
"sequence" test
|
||||||
|
--TEMPLATE--
|
||||||
|
{{ empty is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ sequence is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ empty_array_obj is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ sequence_array_obj is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ mapping_array_obj is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ obj is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ mapping is sequence ? 'ok' : 'ko' }}
|
||||||
|
{{ string is sequence ? 'ok' : 'ko' }}
|
||||||
|
--DATA--
|
||||||
|
return [
|
||||||
|
'empty' => [],
|
||||||
|
'sequence' => [
|
||||||
|
'foo',
|
||||||
|
'bar',
|
||||||
|
'baz'
|
||||||
|
],
|
||||||
|
'empty_array_obj' => new \ArrayObject(),
|
||||||
|
'sequence_array_obj' => new \ArrayObject(['foo', 'bar']),
|
||||||
|
'mapping_array_obj' => new \ArrayObject(['foo' => 'bar']),
|
||||||
|
'obj' => new \stdClass(),
|
||||||
|
'mapping' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'bar' => 'foo'
|
||||||
|
],
|
||||||
|
'string' => 'test',
|
||||||
|
]
|
||||||
|
--EXPECT--
|
||||||
|
ok
|
||||||
|
ok
|
||||||
|
ok
|
||||||
|
ok
|
||||||
|
ko
|
||||||
|
ko
|
||||||
|
ko
|
||||||
|
ko
|
||||||
Reference in New Issue
Block a user