Fix TemplateWrapper::hasBlock() and TemplateWrapper::getBlockNames() omitting environment globals

This commit is contained in:
Fabien Potencier
2026-09-06 14:49:43 +02:00
parent a320927535
commit 0e1852632f
3 changed files with 41 additions and 3 deletions
+1
View File
@@ -3,6 +3,7 @@
* Fix `html_attr` dropping `style` declarations whose value is `0`, `0.0` or `'0'`
* 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
* 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)
+3 -3
View File
@@ -43,7 +43,7 @@ final class TemplateWrapper
*/
public function streamBlock(string $name, array $context = []): iterable
{
yield from $this->template->yieldBlock($name, $context);
yield from $this->template->yieldBlock($name, $context + $this->env->getGlobals());
}
public function render(array $context = []): string
@@ -60,7 +60,7 @@ final class TemplateWrapper
public function hasBlock(string $name, array $context = []): bool
{
return $this->template->hasBlock($name, $context);
return $this->template->hasBlock($name, $context + $this->env->getGlobals());
}
/**
@@ -68,7 +68,7 @@ final class TemplateWrapper
*/
public function getBlockNames(array $context = []): array
{
return $this->template->getBlockNames($context);
return $this->template->getBlockNames($context + $this->env->getGlobals());
}
public function renderBlock(string $name, array $context = []): string
+37
View File
@@ -52,6 +52,43 @@ class TemplateWrapperTest extends TestCase
$this->assertEquals(['foo', 'extended'], $wrapper->getBlockNames());
}
public function testBlockIntrospectionIncludesGlobals(): void
{
$twig = new Environment(new ArrayLoader([
'index' => '{% extends layout %}',
'global_parent' => '{% block global %}{% endblock %}',
'local_parent' => '{% block local %}{% endblock %}',
]));
$twig->addGlobal('layout', 'global_parent');
$wrapper = $twig->load('index');
$this->assertTrue($wrapper->hasBlock('global'));
$this->assertFalse($wrapper->hasBlock('local'));
$this->assertSame(['global'], $wrapper->getBlockNames());
$context = ['layout' => 'local_parent'];
$this->assertTrue($wrapper->hasBlock('local', $context));
$this->assertFalse($wrapper->hasBlock('global', $context));
$this->assertSame(['local'], $wrapper->getBlockNames($context));
}
public function testStreamBlockIncludesGlobals(): void
{
$twig = new Environment(new ArrayLoader([
'index' => '{% extends layout %}',
'layout' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}',
]));
$twig->addGlobal('layout', 'layout');
$twig->addGlobal('bar', 'BAR');
$streamed = '';
foreach ($twig->load('index')->streamBlock('foo', ['foo' => 'FOO']) as $data) {
$streamed .= $data;
}
$this->assertSame('FOOBAR', $streamed);
}
public function testRenderBlock(): void
{
$twig = new Environment(new ArrayLoader([