mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-15 20:06:31 +00:00
Reject cross-environment template wrappers in block chains
This commit is contained in:
+2
-7
@@ -49,12 +49,11 @@ final class BlockChain
|
||||
throw new \TypeError(\sprintf('Block chain templates must be strings or "%s" instances, "%s" given.', TemplateWrapper::class, get_debug_type($template)));
|
||||
}
|
||||
|
||||
$template = $template->unwrap();
|
||||
if (!$template->isOwnedBy($env)) {
|
||||
throw new \LogicException('A block chain cannot contain templates from different Twig environments.');
|
||||
}
|
||||
|
||||
$this->templates[] = $template;
|
||||
$this->templates[] = $template->unwrap($env);
|
||||
}
|
||||
|
||||
if (!$this->templates) {
|
||||
@@ -173,11 +172,7 @@ final class BlockChain
|
||||
$parent = $template->getParent($context);
|
||||
$fixed = $fixed && $template->hasFixedParent();
|
||||
|
||||
// a dynamic parent expression can evaluate to a template from another environment
|
||||
$template = $parent instanceof TemplateWrapper ? $parent->unwrap() : $parent;
|
||||
if (false !== $template && !$template->isOwnedBy($this->env)) {
|
||||
throw new \LogicException('A block chain cannot contain templates from different Twig environments.');
|
||||
}
|
||||
$template = $parent;
|
||||
} while (false !== $template);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,10 +78,6 @@ abstract class Template
|
||||
public function getParent(array $context): self|false
|
||||
{
|
||||
if (null !== $this->parent) {
|
||||
if ($this->parent instanceof TemplateWrapper) {
|
||||
$this->parent = $this->load($this->parent, -1);
|
||||
}
|
||||
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,12 +96,20 @@ final class TemplateWrapper
|
||||
return $this->template->getTemplateName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function isOwnedBy(Environment $env): bool
|
||||
{
|
||||
return $this->env === $env && $this->template->isOwnedBy($env);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function unwrap(Environment $env): Template
|
||||
{
|
||||
if ($this->env !== $env) {
|
||||
if (!$this->isOwnedBy($env)) {
|
||||
throw new RuntimeError(\sprintf('A "%s" can only be used with the "%s" that created it.', self::class, Environment::class));
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ class BlockChainTest extends TestCase
|
||||
{
|
||||
$twig = new Environment(new ArrayLoader(['theme' => '']));
|
||||
$other = new Environment(new ArrayLoader(['theme' => '']));
|
||||
$wrapper = new TemplateWrapper($twig, $other->load('theme')->unwrap());
|
||||
$wrapper = new TemplateWrapper($twig, $other->load('theme')->unwrap($other));
|
||||
|
||||
$this->expectException(\LogicException::class);
|
||||
$this->expectExceptionMessage('A block chain cannot contain templates from different Twig environments.');
|
||||
@@ -267,8 +267,8 @@ class BlockChainTest extends TestCase
|
||||
$other = new Environment(new ArrayLoader(['parent' => '']));
|
||||
$chain = new BlockChain($twig, ['theme'], ['parent' => $other->load('parent')]);
|
||||
|
||||
$this->expectException(\LogicException::class);
|
||||
$this->expectExceptionMessage('A block chain cannot contain templates from different Twig environments.');
|
||||
$this->expectException(RuntimeError::class);
|
||||
$this->expectExceptionMessage('A "Twig\TemplateWrapper" can only be used with the "Twig\Environment" that created it in "theme" at line 1.');
|
||||
|
||||
$chain->getBlockNames();
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ class TemplateTest extends TestCase
|
||||
'parent' => '{% block content %}{{ missing.value }}{% endblock %}',
|
||||
'child' => '{% extends "parent" %}',
|
||||
]), ['debug' => $debug, 'strict_variables' => true, 'use_yield' => false]);
|
||||
$template = $twig->load('child')->unwrap();
|
||||
$template = $twig->load('child')->unwrap($twig);
|
||||
$level = ob_get_level();
|
||||
|
||||
try {
|
||||
@@ -261,14 +261,14 @@ class TemplateTest extends TestCase
|
||||
'dynamic_parent' => '{% extends parent %}',
|
||||
]));
|
||||
|
||||
$this->assertTrue($twig->load('no_parent')->unwrap()->hasFixedParent());
|
||||
$this->assertTrue($twig->load('no_parent')->unwrap($twig)->hasFixedParent());
|
||||
|
||||
$constant = $twig->load('constant_parent')->unwrap();
|
||||
$constant = $twig->load('constant_parent')->unwrap($twig);
|
||||
$this->assertFalse($constant->hasFixedParent());
|
||||
$constant->getParent([]);
|
||||
$this->assertTrue($constant->hasFixedParent());
|
||||
|
||||
$dynamic = $twig->load('dynamic_parent')->unwrap();
|
||||
$dynamic = $twig->load('dynamic_parent')->unwrap($twig);
|
||||
$this->assertFalse($dynamic->hasFixedParent());
|
||||
$dynamic->getParent(['parent' => 'no_parent']);
|
||||
$this->assertFalse($dynamic->hasFixedParent());
|
||||
|
||||
Reference in New Issue
Block a user