From 49725a1e8e914207246fb4e6e725c8548ffdd092 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 5 Apr 2019 19:11:41 +0200 Subject: [PATCH] fixed "include" with "ignore missing" when an error loading occurs in the included template --- CHANGELOG | 1 + src/Extension/CoreExtension.php | 14 +++--- src/Node/IncludeNode.php | 47 ++++++++++++------- .../include/ignore_missing_exists.test | 11 +++++ .../tags/include/ignore_missing_exists.test | 11 +++++ test/Twig/Tests/Node/IncludeTest.php | 8 +++- 6 files changed, 66 insertions(+), 26 deletions(-) create mode 100644 test/Twig/Tests/Fixtures/functions/include/ignore_missing_exists.test create mode 100644 test/Twig/Tests/Fixtures/tags/include/ignore_missing_exists.test diff --git a/CHANGELOG b/CHANGELOG index 12ab6ef4e..0e3b8fde0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 1.39.0 (2019-XX-XX) + * fixed "include" with "ignore missing" when an error loading occurs in the included template * added support for a new whitespace trimming option ({%~ ~%}, {{~ ~}}, {#~ ~#}) * 1.38.4 (2019-03-23) diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index ae9351946..73f118e3b 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -1544,9 +1544,9 @@ function twig_include(Environment $env, $context, $template, $variables = [], $w } } - $result = ''; + $loaded = null; try { - $result = $env->resolveTemplate($template)->render($variables); + $loaded = $env->resolveTemplate($template); } catch (LoaderError $e) { if (!$ignoreMissing) { if ($isSandboxed && !$alreadySandboxed) { @@ -1569,11 +1569,13 @@ function twig_include(Environment $env, $context, $template, $variables = [], $w throw $e; } - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); + try { + return $loaded ? $loaded->render($variables) : ''; + } finally { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } } - - return $result; } /** diff --git a/src/Node/IncludeNode.php b/src/Node/IncludeNode.php index 72b924771..544db81ea 100644 --- a/src/Node/IncludeNode.php +++ b/src/Node/IncludeNode.php @@ -37,43 +37,54 @@ class IncludeNode extends Node implements NodeOutputInterface $compiler->addDebugInfo($this); if ($this->getAttribute('ignore_missing')) { + $template = $compiler->getVarName(); + $compiler + ->write(sprintf("$%s = null;\n", $template)) ->write("try {\n") ->indent() + ->write(sprintf('$%s = ', $template)) ; - } - $this->addGetTemplate($compiler); + $this->addGetTemplate($compiler); - $compiler->raw('->display('); - - $this->addTemplateArguments($compiler); - - $compiler->raw(");\n"); - - if ($this->getAttribute('ignore_missing')) { $compiler + ->raw(";\n") ->outdent() ->write("} catch (LoaderError \$e) {\n") ->indent() ->write("// ignore missing template\n") ->outdent() - ->write("}\n\n") + ->write("}\n") + ->write(sprintf("if ($%s) {\n", $template)) + ->indent() + ->write(sprintf('$%s->display(', $template)) ; + $this->addTemplateArguments($compiler); + $compiler + ->raw(");\n") + ->outdent() + ->write("}\n") + ; + } else { + $this->addGetTemplate($compiler); + $compiler->raw('->display('); + $this->addTemplateArguments($compiler); + $compiler->raw(");\n"); } } protected function addGetTemplate(Compiler $compiler) { $compiler - ->write('$this->loadTemplate(') - ->subcompile($this->getNode('expr')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; + ->write('$this->loadTemplate(') + ->subcompile($this->getNode('expr')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') + ; } protected function addTemplateArguments(Compiler $compiler) diff --git a/test/Twig/Tests/Fixtures/functions/include/ignore_missing_exists.test b/test/Twig/Tests/Fixtures/functions/include/ignore_missing_exists.test new file mode 100644 index 000000000..fc2d211ad --- /dev/null +++ b/test/Twig/Tests/Fixtures/functions/include/ignore_missing_exists.test @@ -0,0 +1,11 @@ +--TEST-- +"include" function +--TEMPLATE-- +{{ include("included.twig", ignore_missing = true) }} +NOT DISPLAYED +--TEMPLATE(included.twig)-- +{{ include("DOES NOT EXIST") }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "DOES NOT EXIST" is not defined in "included.twig" at line 2. diff --git a/test/Twig/Tests/Fixtures/tags/include/ignore_missing_exists.test b/test/Twig/Tests/Fixtures/tags/include/ignore_missing_exists.test new file mode 100644 index 000000000..1af012210 --- /dev/null +++ b/test/Twig/Tests/Fixtures/tags/include/ignore_missing_exists.test @@ -0,0 +1,11 @@ +--TEST-- +"include" tag +--TEMPLATE-- +{% include "included.twig" ignore missing %} +NOT DISPLAYED +--TEMPLATE(included.twig)-- +{% include "DOES NOT EXIST" %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "DOES NOT EXIST" is not defined in "included.twig" at line 2. diff --git a/test/Twig/Tests/Node/IncludeTest.php b/test/Twig/Tests/Node/IncludeTest.php index d24336e30..ae8ff074c 100644 --- a/test/Twig/Tests/Node/IncludeTest.php +++ b/test/Twig/Tests/Node/IncludeTest.php @@ -76,13 +76,17 @@ EOF $node = new IncludeNode($expr, $vars, true, true, 1); $tests[] = [$node, <<loadTemplate("foo.twig", null, 1)->display(twig_to_array(["foo" => true])); + \$__internal_%s = \$this->loadTemplate("foo.twig", null, 1); } catch (LoaderError \$e) { // ignore missing template } +if (\$__internal_%s) { + \$__internal_%s->display(twig_to_array(["foo" => true])); +} EOF - ]; + , null, true]; return $tests; }