mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-12 02:16:41 +00:00
Wrap dynamic parent expression errors
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
* Fix the `default` filter fallback emitting an undefined variable warning when it uses the null-safe operator
|
||||
* Fix the `matches` operator silently treating PCRE execution errors as non-matches
|
||||
* Fix `TemplateWrapper::streamBlock()`, `TemplateWrapper::hasBlock()`, and `TemplateWrapper::getBlockNames()` omitting environment globals
|
||||
* Fix exceptions from dynamic parent expressions escaping without template context
|
||||
* Add the `HtmlExtension::htmlAttrValue()` method to resolve a single HTML attribute value the way the `html_attr` function renders it
|
||||
* Fix `html_attr` JSON encoding a `Stringable` value in a `data-*` attribute instead of using its string representation
|
||||
* Add documentation comments to attach metadata to nodes (experimental)
|
||||
|
||||
+7
-1
@@ -89,7 +89,13 @@ abstract class Template
|
||||
// resolved against a parent, or yieldBlock() into a pre-warmed instance).
|
||||
$this->ensureSecurityChecked();
|
||||
|
||||
if (!$parent = $this->doGetParent($context)) {
|
||||
try {
|
||||
$parent = $this->doGetParent($context);
|
||||
} catch (\Throwable $e) {
|
||||
$this->handleException($e);
|
||||
}
|
||||
|
||||
if (!$parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,13 @@ namespace Twig\Tests;
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class TemplateWrapperTest extends TestCase
|
||||
{
|
||||
@@ -89,6 +93,52 @@ class TemplateWrapperTest extends TestCase
|
||||
$this->assertSame('FOOBAR', $streamed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideDynamicParentFailures
|
||||
*/
|
||||
#[DataProvider('provideDynamicParentFailures')]
|
||||
public function testDynamicParentFailuresAreWrapped(string $template, ?TwigFunction $function, string $previousException): void
|
||||
{
|
||||
$twig = new Environment(new ArrayLoader(['index' => $template]));
|
||||
if (null !== $function) {
|
||||
$twig->addFunction($function);
|
||||
}
|
||||
|
||||
foreach ([
|
||||
'block introspection' => static fn () => $twig->load('index')->getBlockNames(),
|
||||
'rendering' => static fn () => $twig->render('index'),
|
||||
] as $entryPoint => $call) {
|
||||
try {
|
||||
$call();
|
||||
$this->fail(\sprintf('Resolving the dynamic parent during %s must fail.', $entryPoint));
|
||||
} catch (RuntimeError $e) {
|
||||
$this->assertSame('index', $e->getSourceContext()->getName());
|
||||
$this->assertSame(1, $e->getTemplateLine());
|
||||
$this->assertInstanceOf($previousException, $e->getPrevious());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testDynamicParentTwigErrorsAreNotWrapped(): void
|
||||
{
|
||||
$twig = new Environment(new ArrayLoader(['index' => '{% extends parent %}']));
|
||||
|
||||
try {
|
||||
$twig->load('index')->getBlockNames(['parent' => 'missing']);
|
||||
$this->fail('Loading the dynamic parent must fail.');
|
||||
} catch (LoaderError $e) {
|
||||
$this->assertSame('index', $e->getSourceContext()->getName());
|
||||
$this->assertSame(1, $e->getTemplateLine());
|
||||
$this->assertNull($e->getPrevious());
|
||||
}
|
||||
}
|
||||
|
||||
public static function provideDynamicParentFailures(): iterable
|
||||
{
|
||||
yield 'missing parent variable' => ['{% extends parent %}', null, \TypeError::class];
|
||||
yield 'exception thrown by parent expression' => ['{% extends boom() %}', new TwigFunction('boom', static function (): never { throw new \DomainException('kaboom'); }), \DomainException::class];
|
||||
}
|
||||
|
||||
public function testRenderBlock(): void
|
||||
{
|
||||
$twig = new Environment(new ArrayLoader([
|
||||
|
||||
Reference in New Issue
Block a user