diff --git a/CHANGELOG b/CHANGELOG index 85043d29f..e7e4d4acf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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) diff --git a/src/TemplateWrapper.php b/src/TemplateWrapper.php index afadc2b53..c08fca5e3 100644 --- a/src/TemplateWrapper.php +++ b/src/TemplateWrapper.php @@ -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 diff --git a/tests/TemplateWrapperTest.php b/tests/TemplateWrapperTest.php index 475c22e68..a9bb5ca77 100644 --- a/tests/TemplateWrapperTest.php +++ b/tests/TemplateWrapperTest.php @@ -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([