diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 91562b242..2e63d8b81 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -1736,6 +1736,10 @@ function twig_array_reduce(Environment $env, $array, $arrow, $initial = null) } if (!\is_array($array)) { + if (!$array instanceof \Traversable) { + throw new RuntimeError(sprintf('The "reduce" filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array))); + } + $array = iterator_to_array($array); } diff --git a/tests/ErrorTest.php b/tests/ErrorTest.php index 85cc60b91..8019f053b 100644 --- a/tests/ErrorTest.php +++ b/tests/ErrorTest.php @@ -161,6 +161,85 @@ EOHTML } } + public function testTwigArrayFilterThrowsRuntimeExceptions() + { + $loader = new ArrayLoader([ + 'filter-null.html' => << x > 3) %} + This list contains {{n}}. +{% endfor %} +EOHTML + ]); + + $twig = new Environment($loader, ['debug' => true, 'cache' => false]); + + $template = $twig->load('filter-null.html'); + $out = $template->render(['variable' => [1, 2, 3, 4]]); + $this->assertEquals('This list contains 4.', trim($out)); + + try { + $template->render(['variable' => null]); + + $this->fail(); + } catch (RuntimeError $e) { + $this->assertEquals(2, $e->getTemplateLine()); + $this->assertEquals('filter-null.html', $e->getSourceContext()->getName()); + } + } + + public function testTwigArrayMapThrowsRuntimeExceptions() + { + $loader = new ArrayLoader([ + 'map-null.html' => << x * 3) %} + {{- n -}} +{% endfor %} +EOHTML + ]); + + $twig = new Environment($loader, ['debug' => true, 'cache' => false]); + + $template = $twig->load('map-null.html'); + $out = $template->render(['variable' => [1, 2, 3, 4]]); + $this->assertEquals('36912', trim($out)); + + try { + $template->render(['variable' => null]); + + $this->fail(); + } catch (RuntimeError $e) { + $this->assertEquals(2, $e->getTemplateLine()); + $this->assertEquals('map-null.html', $e->getSourceContext()->getName()); + } + } + + public function testTwigArrayReduceThrowsRuntimeExceptions() + { + $loader = new ArrayLoader([ + 'reduce-null.html' => << carry + x) }} +EOHTML + ]); + + $twig = new Environment($loader, ['debug' => true, 'cache' => false]); + + $template = $twig->load('reduce-null.html'); + $out = $template->render(['variable' => [1, 2, 3, 4]]); + $this->assertEquals('10', trim($out)); + + try { + $template->render(['variable' => null]); + + $this->fail(); + } catch (RuntimeError $e) { + $this->assertEquals(2, $e->getTemplateLine()); + $this->assertEquals('reduce-null.html', $e->getSourceContext()->getName()); + } + } + public function getErroredTemplates() { return [