mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-31 04:27:00 +00:00
feature #2909 Allow Traversable objects to be used in the with keyword of the include and embed tags (thewilkybarkid)
This PR was squashed before being merged into the 1.x branch (closes #2909).
Discussion
----------
Allow Traversable objects to be used in the with keyword of the include and embed tags
Same as #2901 but for `include` and `embed`.
Commits
-------
068306fe Allow Traversable objects to be used in the with keyword of the include and embed tags
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* fixed BC break on Environment::resolveTemplate()
|
||||
* fixed the bundled Autoloader to also load namespaced classes
|
||||
* allowed Traversable objects to be used in the "with" tag
|
||||
* allowed Traversable objects to be used in the "with" argument of the "include" and "embed" tags
|
||||
|
||||
* 1.38.2 (2019-03-12)
|
||||
|
||||
|
||||
@@ -362,9 +362,7 @@ function twig_random(Environment $env, $values = null, $max = null)
|
||||
return mt_rand($min, $max);
|
||||
}
|
||||
|
||||
if ($values instanceof \Traversable) {
|
||||
$values = iterator_to_array($values);
|
||||
} elseif (\is_string($values)) {
|
||||
if (\is_string($values)) {
|
||||
if ('' === $values) {
|
||||
return '';
|
||||
}
|
||||
@@ -387,10 +385,12 @@ function twig_random(Environment $env, $values = null, $max = null)
|
||||
}
|
||||
}
|
||||
|
||||
if (!\is_array($values)) {
|
||||
if (!twig_test_iterable($values)) {
|
||||
return $values;
|
||||
}
|
||||
|
||||
$values = twig_to_array($values);
|
||||
|
||||
if (0 === \count($values)) {
|
||||
throw new RuntimeError('The random function cannot pick from an empty array.');
|
||||
}
|
||||
@@ -510,17 +510,15 @@ function twig_date_converter(Environment $env, $date = null, $timezone = null)
|
||||
*/
|
||||
function twig_replace_filter($str, $from, $to = null)
|
||||
{
|
||||
if ($from instanceof \Traversable) {
|
||||
$from = iterator_to_array($from);
|
||||
} elseif (\is_string($from) && \is_string($to)) {
|
||||
if (\is_string($from) && \is_string($to)) {
|
||||
@trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED);
|
||||
|
||||
return strtr($str, $from, $to);
|
||||
} elseif (!\is_array($from)) {
|
||||
} elseif (!twig_test_iterable($from)) {
|
||||
throw new RuntimeError(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from)));
|
||||
}
|
||||
|
||||
return strtr($str, $from);
|
||||
return strtr($str, twig_to_array($from));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,19 +637,15 @@ function _twig_markup2string(&$value)
|
||||
*/
|
||||
function twig_array_merge($arr1, $arr2)
|
||||
{
|
||||
if ($arr1 instanceof \Traversable) {
|
||||
$arr1 = iterator_to_array($arr1);
|
||||
} elseif (!\is_array($arr1)) {
|
||||
if (!twig_test_iterable($arr1)) {
|
||||
throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($arr1)));
|
||||
}
|
||||
|
||||
if ($arr2 instanceof \Traversable) {
|
||||
$arr2 = iterator_to_array($arr2);
|
||||
} elseif (!\is_array($arr2)) {
|
||||
if (!twig_test_iterable($arr2)) {
|
||||
throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', \gettype($arr2)));
|
||||
}
|
||||
|
||||
return array_merge($arr1, $arr2);
|
||||
return array_merge(twig_to_array($arr1), twig_to_array($arr2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -745,13 +739,9 @@ function twig_last(Environment $env, $item)
|
||||
*/
|
||||
function twig_join_filter($value, $glue = '', $and = null)
|
||||
{
|
||||
if ($value instanceof \Traversable) {
|
||||
$value = iterator_to_array($value, false);
|
||||
} else {
|
||||
$value = (array) $value;
|
||||
}
|
||||
$value = twig_to_array($value, false);
|
||||
|
||||
if (0 === \count($value)) {
|
||||
if (!\is_array($value) || 0 === \count($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -759,12 +749,11 @@ function twig_join_filter($value, $glue = '', $and = null)
|
||||
return implode($glue, $value);
|
||||
}
|
||||
|
||||
$v = array_values($value);
|
||||
if (1 === \count($v)) {
|
||||
return $v[0];
|
||||
if (1 === \count($value)) {
|
||||
return $value[0];
|
||||
}
|
||||
|
||||
return implode($glue, \array_slice($value, 0, -1)).$and.$v[\count($v) - 1];
|
||||
return implode($glue, \array_slice($value, 0, -1)).$and.$value[\count($value) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1470,6 +1459,26 @@ function twig_ensure_traversable($seq)
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_to_array($seq, $preserveKeys = true)
|
||||
{
|
||||
if ($seq instanceof \Traversable) {
|
||||
return iterator_to_array($seq, $preserveKeys);
|
||||
}
|
||||
|
||||
if (!is_array($seq)) {
|
||||
return (array) $seq;
|
||||
}
|
||||
|
||||
if(!$preserveKeys) {
|
||||
return array_values($seq);
|
||||
}
|
||||
|
||||
return $seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a variable is empty.
|
||||
*
|
||||
@@ -1640,13 +1649,9 @@ function twig_constant_is_defined($constant, $object = null)
|
||||
*/
|
||||
function twig_array_batch($items, $size, $fill = null, $preserveKeys = true)
|
||||
{
|
||||
if ($items instanceof \Traversable) {
|
||||
$items = iterator_to_array($items, $preserveKeys);
|
||||
}
|
||||
|
||||
$size = ceil($size);
|
||||
|
||||
$result = array_chunk($items, $size, $preserveKeys);
|
||||
$result = array_chunk(twig_to_array($items, $preserveKeys), $size, $preserveKeys);
|
||||
|
||||
if (null !== $fill && $result) {
|
||||
$last = \count($result) - 1;
|
||||
|
||||
@@ -82,12 +82,14 @@ class IncludeNode extends Node implements NodeOutputInterface
|
||||
$compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]');
|
||||
} elseif (false === $this->getAttribute('only')) {
|
||||
$compiler
|
||||
->raw('array_merge($context, ')
|
||||
->raw('twig_array_merge($context, ')
|
||||
->subcompile($this->getNode('variables'))
|
||||
->raw(')')
|
||||
;
|
||||
} else {
|
||||
$compiler->raw('twig_to_array(');
|
||||
$compiler->subcompile($this->getNode('variables'));
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,18 @@
|
||||
--TEMPLATE--
|
||||
{% include "foo.twig" %}
|
||||
{% include "foo.twig" only %}
|
||||
{% include "foo.twig" with {'foo1': 'bar'} %}
|
||||
{% include "foo.twig" with {'foo1': 'bar'} only %}
|
||||
{% include "foo.twig" with vars1 %}
|
||||
{% include "foo.twig" with vars1 only %}
|
||||
{% include "foo.twig" with vars2 %}
|
||||
{% include "foo.twig" with vars2 only %}
|
||||
--TEMPLATE(foo.twig)--
|
||||
{% for k, v in _context %}{{ k }},{% endfor %}
|
||||
--DATA--
|
||||
return ['foo' => 'bar']
|
||||
return ['vars1' => ['foo1' => 'bar'], 'vars2' => new ArrayObject(['foo2' => 'bar'])]
|
||||
--EXPECT--
|
||||
foo,global,_parent,
|
||||
vars1,vars2,global,_parent,
|
||||
global,_parent,
|
||||
foo,global,foo1,_parent,
|
||||
vars1,vars2,global,foo1,_parent,
|
||||
foo1,global,_parent,
|
||||
vars1,vars2,global,foo2,_parent,
|
||||
foo2,global,_parent,
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
"include" tag accept variables
|
||||
--TEMPLATE--
|
||||
{% include "foo.twig" with {'foo': 'bar'} %}
|
||||
{% include "foo.twig" with vars %}
|
||||
{% include "foo.twig" with vars1 %}
|
||||
{% include "foo.twig" with vars2 %}
|
||||
--TEMPLATE(foo.twig)--
|
||||
{{ foo }}
|
||||
--DATA--
|
||||
return ['vars' => ['foo' => 'bar']]
|
||||
return ['vars1' => ['foo' => 'bar'], 'vars2' => new ArrayObject(['foo' => 'bar'])]
|
||||
--EXPECT--
|
||||
bar
|
||||
bar
|
||||
bar
|
||||
|
||||
@@ -62,14 +62,14 @@ EOF
|
||||
$node = new IncludeNode($expr, $vars, false, false, 1);
|
||||
$tests[] = [$node, <<<EOF
|
||||
// line 1
|
||||
\$this->loadTemplate("foo.twig", null, 1)->display(array_merge(\$context, ["foo" => true]));
|
||||
\$this->loadTemplate("foo.twig", null, 1)->display(twig_array_merge(\$context, ["foo" => true]));
|
||||
EOF
|
||||
];
|
||||
|
||||
$node = new IncludeNode($expr, $vars, true, false, 1);
|
||||
$tests[] = [$node, <<<EOF
|
||||
// line 1
|
||||
\$this->loadTemplate("foo.twig", null, 1)->display(["foo" => true]);
|
||||
\$this->loadTemplate("foo.twig", null, 1)->display(twig_to_array(["foo" => true]));
|
||||
EOF
|
||||
];
|
||||
|
||||
@@ -77,7 +77,7 @@ EOF
|
||||
$tests[] = [$node, <<<EOF
|
||||
// line 1
|
||||
try {
|
||||
\$this->loadTemplate("foo.twig", null, 1)->display(["foo" => true]);
|
||||
\$this->loadTemplate("foo.twig", null, 1)->display(twig_to_array(["foo" => true]));
|
||||
} catch (LoaderError \$e) {
|
||||
// ignore missing template
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user