Remove obsolete code about non-yield templates

This commit is contained in:
Fabien Potencier
2024-02-05 15:26:25 +01:00
parent b1c22a1cee
commit b3eeb41861
17 changed files with 71 additions and 299 deletions
+1 -21
View File
@@ -78,7 +78,6 @@ class Environment
*/
private array $runtimes = [];
private string $optionsHash;
private bool $useYield;
/**
* Constructor.
@@ -110,10 +109,6 @@ class Environment
* * optimizations: A flag that indicates which optimizations to apply
* (default to -1 which means that all optimizations are enabled;
* set it to 0 to disable).
*
* * use_yield: Enable a new mode where template are using "yield" instead of "echo"
* (default to "false", but switch it to "true" when possible
* as this will be the only supported mode in Twig 4.0)
*/
public function __construct(LoaderInterface $loader, $options = [])
{
@@ -127,14 +122,8 @@ class Environment
'cache' => false,
'auto_reload' => null,
'optimizations' => -1,
'use_yield' => false,
], $options);
$this->useYield = (bool) $options['use_yield'];
if (!$this->useYield) {
trigger_deprecation('twig/twig', '3.9.0', 'Not setting "use_yield" to "true" is deprecated.');
}
$this->debug = (bool) $options['debug'];
$this->setCharset($options['charset'] ?? 'UTF-8');
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
@@ -147,14 +136,6 @@ class Environment
$this->addExtension(new OptimizerExtension($options['optimizations']));
}
/**
* @internal
*/
public function useYield(): bool
{
return $this->useYield;
}
/**
* Enables debugging mode.
*/
@@ -864,8 +845,7 @@ class Environment
\PHP_MINOR_VERSION,
self::VERSION,
(int) $this->debug,
(int) $this->strictVariables,
$this->useYield ? '1' : '0',
(int) $this->strictVariables
]);
}
}
+1 -1
View File
@@ -39,7 +39,7 @@ class BlockNode extends Node
->subcompile($this->getNode('body'))
;
if (!$this->getNode('body') instanceof NodeOutputInterface && $compiler->getEnvironment()->useYield()) {
if (!$this->getNode('body') instanceof NodeOutputInterface) {
// needed when body doesn't yield anything
$compiler->write("yield '';\n");
}
+4 -11
View File
@@ -28,16 +28,9 @@ class BlockReferenceNode extends Node implements NodeOutputInterface
public function compile(Compiler $compiler): void
{
if ($compiler->getEnvironment()->useYield()) {
$compiler
->addDebugInfo($this)
->write(sprintf("yield from \$this->unwrap()->yieldBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
;
} else {
$compiler
->addDebugInfo($this)
->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
;
}
$compiler
->addDebugInfo($this)
->write(sprintf("yield from \$this->unwrap()->yieldBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
;
}
}
+9 -46
View File
@@ -27,62 +27,25 @@ class CaptureNode extends Node
public function compile(Compiler $compiler): void
{
if ($compiler->getEnvironment()->useYield()) {
if ($this->getAttribute('raw')) {
$compiler->raw("implode('', iterator_to_array(");
} else {
$compiler->raw("('' === \$tmp = implode('', iterator_to_array(");
}
if ($this->getAttribute('with_blocks')) {
$compiler->raw("(function () use (&\$context, \$macros, \$blocks) {\n");
} else {
$compiler->raw("(function () use (&\$context, \$macros) {\n");
}
$compiler
->indent()
->subcompile($this->getNode('body'))
->outdent()
->write("})() ?? new \EmptyIterator()))")
;
if (!$this->getAttribute('raw')) {
$compiler->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())");
}
$compiler->raw(";");
return;
if ($this->getAttribute('raw')) {
$compiler->raw("implode('', iterator_to_array(");
} else {
$compiler->raw("('' === \$tmp = implode('', iterator_to_array(");
}
if ($this->getAttribute('with_blocks')) {
$compiler->raw("(function () use (&\$context, \$macros, \$blocks) {\n");
} else {
$compiler->raw("(function () use (&\$context, \$macros) {\n");
}
$compiler->indent();
if ($compiler->getEnvironment()->isDebug()) {
$compiler->write("ob_start();\n");
} else {
$compiler->write("ob_start(function () { return ''; });\n");
}
$compiler
->write("try {\n")
->indent()
->subcompile($this->getNode('body'))
->raw("\n")
->outdent()
->write("})() ?? new \EmptyIterator()))")
;
if ($this->getAttribute('raw')) {
$compiler->write("return ob_get_contents();\n");
} else {
$compiler->write("return ('' === \$tmp = ob_get_contents()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n");
if (!$this->getAttribute('raw')) {
$compiler->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())");
}
$compiler
->outdent()
->write("} finally {\n")
->indent()
->write("ob_end_clean();\n")
->outdent()
->write("}\n")
->outdent()
->write('})();')
;
$compiler->raw(";");
}
}
@@ -38,18 +38,13 @@ class BlockReferenceExpression extends AbstractExpression
$this->compileTemplateCall($compiler, 'hasBlock');
} else {
if ($this->getAttribute('output')) {
$compiler->addDebugInfo($this);
if ($compiler->getEnvironment()->useYield()) {
$compiler->write('yield from ');
$this
->compileTemplateCall($compiler, 'yieldBlock')
->raw(";\n");
} else {
$this
->compileTemplateCall($compiler, 'displayBlock')
->raw(";\n");
}
$compiler
->addDebugInfo($this)
->write('yield from ')
;
$this
->compileTemplateCall($compiler, 'yieldBlock')
->raw(";\n");
} else {
$this->compileTemplateCall($compiler, 'renderBlock');
}
@@ -72,11 +67,10 @@ class BlockReferenceExpression extends AbstractExpression
;
}
if ($compiler->getEnvironment()->useYield()) {
$compiler->raw('->unwrap()');
}
$compiler->raw(sprintf('->%s', $method));
$compiler
->raw('->unwrap()')
->raw(sprintf('->%s', $method))
;
return $this->compileBlockArguments($compiler);
}
+4 -14
View File
@@ -26,19 +26,9 @@ final class InlinePrint extends AbstractExpression
public function compile(Compiler $compiler): void
{
if ($compiler->getEnvironment()->useYield()) {
$compiler
->raw('yield ')
->subcompile($this->getNode('node'))
;
} else {
$compiler
->checkForOutput(false)
->raw('print(')
->checkForOutput(true)
->subcompile($this->getNode('node'))
->raw(')')
;
}
$compiler
->raw('yield ')
->subcompile($this->getNode('node'))
;
}
}
+12 -29
View File
@@ -28,36 +28,19 @@ class ParentExpression extends AbstractExpression
public function compile(Compiler $compiler): void
{
if ($compiler->getEnvironment()->useYield()) {
if ($this->getAttribute('output')) {
$compiler
->addDebugInfo($this)
->write('yield from $this->yieldParentBlock(')
->string($this->getAttribute('name'))
->raw(", \$context, \$blocks);\n")
;
} else {
$compiler
->raw('$this->renderParentBlock(')
->string($this->getAttribute('name'))
->raw(', $context, $blocks)')
;
}
if ($this->getAttribute('output')) {
$compiler
->addDebugInfo($this)
->write('yield from $this->yieldParentBlock(')
->string($this->getAttribute('name'))
->raw(", \$context, \$blocks);\n")
;
} else {
if ($this->getAttribute('output')) {
$compiler
->addDebugInfo($this)
->write('$this->displayParentBlock(')
->string($this->getAttribute('name'))
->raw(", \$context, \$blocks);\n")
;
} else {
$compiler
->raw('$this->renderParentBlock(')
->string($this->getAttribute('name'))
->raw(', $context, $blocks)')
;
}
$compiler
->raw('$this->renderParentBlock(')
->string($this->getAttribute('name'))
->raw(', $context, $blocks)')
;
}
}
}
+5 -20
View File
@@ -58,18 +58,9 @@ class IncludeNode extends Node implements NodeOutputInterface
->write("}\n")
->write(sprintf("if ($%s) {\n", $template))
->indent()
->write(sprintf('yield from $%s->unwrap()->yield(', $template))
;
if ($compiler->getEnvironment()->useYield()) {
$compiler
->write(sprintf('yield from $%s->unwrap()->yield(', $template))
;
} else {
$compiler
->write(sprintf('$%s->display(', $template))
;
}
$this->addTemplateArguments($compiler);
$compiler
->raw(");\n")
@@ -77,19 +68,13 @@ class IncludeNode extends Node implements NodeOutputInterface
->write("}\n")
;
} else {
if ($compiler->getEnvironment()->useYield()) {
$compiler
->write('yield from ')
;
}
$compiler
->write('yield from ')
;
$this->addGetTemplate($compiler);
if ($compiler->getEnvironment()->useYield()) {
$compiler->raw('->unwrap()->yield(');
} else {
$compiler->raw('->display(');
}
$compiler->raw('->unwrap()->yield(');
$this->addTemplateArguments($compiler);
$compiler->raw(");\n");
+5 -13
View File
@@ -151,14 +151,14 @@ final class ModuleNode extends Node
->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n")
->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n")
->write("use Twig\Source;\n")
->write(sprintf("use Twig\%s;\n\n", $compiler->getEnvironment()->useYield() ? 'YieldingTemplate' : 'Template'))
->write("use Twig\YieldingTemplate;\n\n")
;
}
$compiler
// if the template name contains */, add a blank to avoid a PHP parse error
->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n")
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index')))
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->useYield() ? 'YieldingTemplate' : 'Template'))
->raw(" extends YieldingTemplate\n")
->write("{\n")
->indent()
->write("private Source \$source;\n")
@@ -326,23 +326,15 @@ final class ModuleNode extends Node
->raw(");\n")
;
}
if ($compiler->getEnvironment()->useYield()) {
$compiler->write('yield from ');
} else {
$compiler->write('');
}
$compiler->write('yield from ');
if ($parent instanceof ConstantExpression) {
$compiler->raw('$this->parent');
} else {
$compiler->raw('$this->getParent($context)');
}
if ($compiler->getEnvironment()->useYield()) {
$compiler->raw("->unwrap()->yield(\$context, array_merge(\$this->blocks, \$blocks));\n");
} else {
$compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
}
} elseif ($compiler->getEnvironment()->useYield() && !$this->hasNodeOutputNodes($this->getNode('body'))) {
$compiler->raw("->unwrap()->yield(\$context, array_merge(\$this->blocks, \$blocks));\n");
} elseif (!$this->hasNodeOutputNodes($this->getNode('body'))) {
// ensure at least one yield call even for templates with no output
$compiler->write("yield '';\n");
}
+2 -12
View File
@@ -29,19 +29,9 @@ class PrintNode extends Node implements NodeOutputInterface
public function compile(Compiler $compiler): void
{
$compiler->addDebugInfo($this);
if ($compiler->getEnvironment()->useYield()) {
$compiler->write('yield ');
} else {
$compiler
->checkForOutput(false)
->write('echo ')
->checkForOutput(true)
;
}
$compiler
->addDebugInfo($this)
->write('yield ')
->subcompile($this->getNode('expr'))
->raw(";\n")
;
+2 -12
View File
@@ -28,19 +28,9 @@ class TextNode extends Node implements NodeOutputInterface
public function compile(Compiler $compiler): void
{
$compiler->addDebugInfo($this);
if ($compiler->getEnvironment()->useYield()) {
$compiler->write('yield ');
} else {
$compiler
->checkForOutput(false)
->write('echo ')
->checkForOutput(true)
;
}
$compiler
->addDebugInfo($this)
->write('yield ')
->string($this->getAttribute('data'))
->raw(";\n")
;
+3 -3
View File
@@ -70,16 +70,16 @@ abstract class NodeTestCase extends TestCase
protected function getEchoOrYield(): string
{
return ($this->currentEnv ?? $this->getEnvironment())->useYield() ? 'yield' : 'echo';
return 'yield';
}
protected function getDisplayOrYield(string $expr): string
{
return sprintf(($this->currentEnv ?? $this->getEnvironment())->useYield() ? 'yield from %s->unwrap()->yield' : '%s->display', $expr);
return sprintf('yield from %s->unwrap()->yield', $expr);
}
protected function getDisplayOrYieldBlock(string $expr): string
{
return sprintf(($this->currentEnv ?? $this->getEnvironment())->useYield() ? 'yield from %s->unwrap()->yieldBlock' : '%s->displayBlock', $expr);
return sprintf('yield from %s->unwrap()->yieldBlock', $expr);
}
}
+2 -16
View File
@@ -32,20 +32,7 @@ class BlockTest extends NodeTestCase
public function getTests()
{
$tests = [];
if (!$this->getEnvironment()->useYield()) {
$tests[] = [new BlockNode('foo', new TextNode('foo', 1), 1), <<<EOF
// line 1
public function block_foo(\$context, array \$blocks = [])
{
\$macros = \$this->macros;
echo "foo";
}
EOF
, new Environment(new ArrayLoader())
];
} else {
$tests[] = [new BlockNode('foo', new TextNode('foo', 1), 1), <<<EOF
$tests[] = [new BlockNode('foo', new TextNode('foo', 1), 1), <<<EOF
// line 1
public function block_foo(\$context, array \$blocks = [])
{
@@ -65,8 +52,7 @@ public function block_foo(\$context, array \$blocks = [])
}
EOF
, new Environment(new ArrayLoader())
];
}
];
return $tests;
}
+2 -35
View File
@@ -45,8 +45,7 @@ class MacroTest extends NodeTestCase
$body = new TextNode('foo', 1);
$node = new MacroNode('foo', $body, $arguments, 1);
if ($this->getEnvironment()->useYield()) {
$text[] = [$node, <<<EOF
$text[] = [$node, <<<EOF
// line 1
public function macro_foo(\$__foo__ = null, \$__bar__ = "Foo", ...\$__varargs__)
{
@@ -65,39 +64,7 @@ public function macro_foo(\$__foo__ = null, \$__bar__ = "Foo", ...\$__varargs__)
}
EOF
, new Environment(new ArrayLoader()),
];
} else {
$body = new TextNode('foo', 1);
$node = new MacroNode('foo', $body, $arguments, 1);
$tests[] = [$node, <<<EOF
// line 1
public function macro_foo(\$__foo__ = null, \$__bar__ = "Foo", ...\$__varargs__)
{
\$macros = \$this->macros;
\$context = \$this->env->mergeGlobals([
"foo" => \$__foo__,
"bar" => \$__bar__,
"varargs" => \$__varargs__,
]);
\$blocks = [];
return (function () use (&\$context, \$macros) {
ob_start(function () { return ''; });
try {
echo "foo";
return ('' === \$tmp = ob_get_contents()) ? '' : new Markup(\$tmp, \$this->env->getCharset());
} finally {
ob_end_clean();
}
})();
}
EOF
, new Environment(new ArrayLoader()),
];
}
];
return $tests;
}
+6 -9
View File
@@ -55,7 +55,6 @@ class ModuleTest extends NodeTestCase
$macros = new Node();
$traits = new Node();
$source = new Source('{{ foo }}', 'foo.twig');
$parentTemplate = $this->getEnvironment()->useYield() ? 'YieldingTemplate' : 'Template';
$displayStmt = $this->getEchoOrYield();
$node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source);
@@ -73,10 +72,10 @@ use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\\{$parentTemplate};
use Twig\YieldingTemplate;
/* foo.twig */
class __TwigTemplate_%x extends $parentTemplate
class __TwigTemplate_%x extends YieldingTemplate
{
private Source \$source;
private array \$macros = [];
@@ -128,7 +127,6 @@ EOF
$body = new Node([$import]);
$extends = new ConstantExpression('layout.twig', 1);
$parentTemplate = $this->getEnvironment()->useYield() ? 'YieldingTemplate' : 'Template';
$node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source);
$tests[] = [$node, <<<EOF
@@ -145,10 +143,10 @@ use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\\{$parentTemplate};
use Twig\YieldingTemplate;
/* foo.twig */
class __TwigTemplate_%x extends $parentTemplate
class __TwigTemplate_%x extends YieldingTemplate
{
private Source \$source;
private array \$macros = [];
@@ -219,7 +217,6 @@ EOF
new ConstantExpression('foo', 2),
2
);
$parentTemplate = $this->getEnvironment()->useYield() ? 'YieldingTemplate' : 'Template';
$twig = new Environment($this->createMock(LoaderInterface::class), ['debug' => true]);
$node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source);
@@ -237,10 +234,10 @@ use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\\{$parentTemplate};
use Twig\YieldingTemplate;
/* foo.twig */
class __TwigTemplate_%x extends $parentTemplate
class __TwigTemplate_%x extends YieldingTemplate
{
private Source \$source;
private array \$macros = [];
+2 -20
View File
@@ -53,32 +53,14 @@ EOF
$values = new Node([new PrintNode(new ConstantExpression('foo', 1), 1)], [], 1);
$node = new SetNode(true, $names, $values, 1);
if ($this->getEnvironment()->useYield()) {
$tests[] = [$node, <<<EOF
$tests[] = [$node, <<<EOF
// line 1
\$context["foo"] = ('' === \$tmp = implode('', iterator_to_array((function () use (&\$context, \$macros, \$blocks) {
yield "foo";
})() ?? new \EmptyIterator()))) ? '' : new Markup(\$tmp, \$this->env->getCharset());
EOF
, new Environment(new ArrayLoader()),
];
} else {
$tests[] = [$node, <<<EOF
// line 1
\$context["foo"] = (function () use (&\$context, \$macros, \$blocks) {
ob_start(function () { return ''; });
try {
echo "foo";
return ('' === \$tmp = ob_get_contents()) ? '' : new Markup(\$tmp, \$this->env->getCharset());
} finally {
ob_end_clean();
}
})();
EOF
, new Environment(new ArrayLoader()),
];
}
];
$names = new Node([new AssignNameExpression('foo', 1)], [], 1);
$values = new TextNode('foo', 1);
-20
View File
@@ -53,24 +53,4 @@ class TemplateWrapperTest extends TestCase
$wrapper = $twig->load('index');
$this->assertEquals('FOOBAR', $wrapper->renderBlock('foo', ['foo' => 'FOO']));
}
public function testDisplayBlock()
{
$twig = new Environment(new ArrayLoader([
'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}',
]));
if (!$twig->useYield()) {
$twig->addGlobal('bar', 'BAR');
$wrapper = $twig->load('index');
ob_start();
$wrapper->displayBlock('foo', ['foo' => 'FOO']);
$this->assertEquals('FOOBAR', ob_get_clean());
} else {
$this->markTestSkipped('yield not used.');
}
}
}