Skip to content

Commit

Permalink
See #11. (#12)
Browse files Browse the repository at this point in the history
Remove obsolete deferred blocks on error, improve template compilation

See #11.
  • Loading branch information
rybakit committed Sep 17, 2021
1 parent f9c62d2 commit 0c96515
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/DeferredBlockNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function compile(Compiler $compiler) : void
$compiler
->write("public function block_$name(\$context, array \$blocks = [])\n", "{\n")
->indent()
->write("\$this->env->getExtension('".DeferredExtension::class."')->defer(\$this, '$name');\n")
->write("\$this->deferred->defer(\$this, '$name');\n")
->outdent()
->write("}\n\n")
;
Expand All @@ -35,7 +35,7 @@ public function compile(Compiler $compiler) : void
->write("public function block_{$name}_deferred(\$context, array \$blocks = [])\n", "{\n")
->indent()
->subcompile($this->getNode('body'))
->write("\$this->env->getExtension('".DeferredExtension::class."')->resolve(\$this, \$context, \$blocks);\n")
->write("\$this->deferred->resolve(\$this, \$context, \$blocks);\n")
->outdent()
->write("}\n\n")
;
Expand Down
8 changes: 7 additions & 1 deletion src/DeferredExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ public function defer(Template $template, string $blockName) : void
{
$templateName = $template->getTemplateName();
$this->blocks[$templateName][] = $blockName;
\ob_start();
$index = \count($this->blocks[$templateName]) - 1;

\ob_start(function (string $buffer) use ($index, $templateName) {
unset($this->blocks[$templateName][$index]);

return $buffer;
});
}

public function resolve(Template $template, array $context, array $blocks) : void
Expand Down
4 changes: 2 additions & 2 deletions src/DeferredNode.php → src/DeferredExtensionNode.php
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
use Twig\Compiler;
use Twig\Node\Node;

final class DeferredNode extends Node
final class DeferredExtensionNode extends Node
{
public function compile(Compiler $compiler) : void
{
$compiler
->write("\$this->env->getExtension('".DeferredExtension::class."')->resolve(\$this, \$context, \$blocks);\n")
->write("\$this->deferred = \$this->env->getExtension('".DeferredExtension::class."');\n")
;
}
}
3 changes: 2 additions & 1 deletion src/DeferredNodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public function enterNode(Node $node, Environment $env) : Node
public function leaveNode(Node $node, Environment $env) : ?Node
{
if ($this->hasDeferred && $node instanceof ModuleNode) {
$node->setNode('display_end', new Node([new DeferredNode(), $node->getNode('display_end')]));
$node->setNode('constructor_end', new Node([new DeferredExtensionNode(), $node->getNode('constructor_end')]));
$node->setNode('display_end', new Node([new DeferredResolveNode(), $node->getNode('display_end')]));
$this->hasDeferred = false;
}

Expand Down
27 changes: 27 additions & 0 deletions src/DeferredResolveNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* This file is part of the rybakit/twig-deferred-extension package.
*
* (c) Eugene Leonovich <gen.work@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Twig\DeferredExtension;

use Twig\Compiler;
use Twig\Node\Node;

final class DeferredResolveNode extends Node
{
public function compile(Compiler $compiler) : void
{
$compiler
->write("\$this->deferred->resolve(\$this, \$context, \$blocks);\n")
;
}
}
47 changes: 47 additions & 0 deletions tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
namespace Twig\DeferredExtension\Tests;

use Twig\DeferredExtension\DeferredExtension;
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Extension\StringLoaderExtension;
use Twig\Loader\ArrayLoader;
use Twig\Test\IntegrationTestCase;
use Twig\TwigFunction;

final class IntegrationTest extends IntegrationTestCase
{
Expand All @@ -32,4 +36,47 @@ public function getFixturesDir() : string
{
return __DIR__.'/Fixtures';
}

public function testDeferredBlockGetRemovedOnError() : void
{
$loader = new ArrayLoader([
'base' => '
{%- block foo deferred -%}*{%- endblock -%}
{{- block("foo") -}}
{{- block("foo") -}}
{% block content "base content" -%}
',
'page_that_triggers_error' => '
{% extends "base" %}
{% block content %}{{ error() }}{% endblock %}
',
'fallback_page' => '
{% extends "base" %}
{% block content "fallback content" %}
',
]);

$twig = new Environment($loader, [
'cache' => false,
'strict_variables' => true,
]);

$twig->addExtension(new DeferredExtension());
$twig->addFunction(new TwigFunction('error', static function () {
throw new \RuntimeException('Oops');
}));

try {
$result = $twig->render('page_that_triggers_error');
} catch (RuntimeError $e) {
self::assertSame(
'An exception has been thrown during the rendering of a template ("Oops").',
$e->getRawMessage()
);

$result = $twig->render('fallback_page');
}

self::assertSame('***fallback content', $result);
}
}

0 comments on commit 0c96515

Please sign in to comment.