Add sequence and mapping tests
Jinja has:
- the iterable test: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-tests.iterable
- the sequence test: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-tests.sequence
- the mapping test: https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-tests.mapping
Twig has only the iterable test, which returns true for any PHP array or any object implementing the Traversable interface : https://twig.symfony.com/doc/3.x/tests/iterable.html
Sometimes, it is necessary to differentiate between sequences and mappings.
For example, Drupal templates are using "render arrays" (renderable objects injected into the template as a mapping variable) and testing "is iterable" is not enough.
Is is conceivable to add those 2 tests?
What do you mean by "sequences" and "mappings"?
It seems like in Drupal "render array" is simple array with some conventions:
Render arrays The core structure of the Render API is the render array, which is a hierarchical associative array containing data to be rendered and properties describing how the data should be rendered. https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/group/theme_render/8.2.x#arrays
PHP have classes Sequence and Map in SPL. But they are rarely used. And it can be tested with additional extensions implement method of "instanceof" like here: https://gist.github.com/xthiago/ad5bce2f7d39bdd54b6f
Hi @pudovmaxim ,
What do you mean by "sequences" and "mappings"?
Those terms come from Jinja terminology and are used many times in Twig documentation without being properly defined. Examples:
- "The slice filter extracts a slice of a sequence, a mapping, or a string". https://twig.symfony.com/doc/3.x/filters/slice.html
- "The first filter returns the first "element" of a sequence, a mapping, or a string". https://twig.symfony.com/doc/3.x/filters/first.html
A sequence is called a list in Pyhton or an array in JSON. PHP 8.1 introduced a similar concept in array_is_list:
Determines if the given array is a list. An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1.
A mapping is called a dict in Python or an object in JSON. In PHP, it would be any array which is not a list.
So, we already have:
function twig_test_iterable($value)
{
return $value instanceof \Traversable || \is_array($value);
}
If we target compatibility with PHP 8.1+, I can propose a patch doing something like that:
function twig_test_sequence($value)
{
return $value instanceof \Traversable || (\is_array($value) && \array_is_list($value));
}
function twig_test_mapping($value)
{
return \is_array($value) && !\array_is_list($value);
}
What do you think about this?
Hello,
one month ago, i did a PR https://github.com/twigphp/Twig/pull/3859 with my proposal and the changes asked by @fabpot
Not 100% sure but I believe the fails reported by https://fabbot.io/report/twigphp/Twig/3859/508bc72c99bea1bfb69284610aaa154a3abeaf9a doesn't come from the code I have changed.
What can I do to unblock the situation?
Merged