Skip to content

Commit

Permalink
Merge pull request #15 from victorwelling/master
Browse files Browse the repository at this point in the history
Fixes partial output from optional tags
  • Loading branch information
victorwelling committed Nov 22, 2018
2 parents b12e826 + 6268bb0 commit b0c8335
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 19 deletions.
6 changes: 1 addition & 5 deletions README.md
Expand Up @@ -178,11 +178,7 @@ and the presentation model assigned to the template.

It will fetch the necessary data from the database, look up the correct route to the author's profile and return the
presentation model updated with its variables set. Shoot then assigns these variables to the template, and Twig takes
care of rendering it. Job done!

## Limitations
* Do not define a model for templates from which you intend to extend. Due to how Twig renders its templates, it causes
the presentation model of a child template to be overwritten by its parent. This is probably not what you want.
care of rendering it. Job done!

## Changelog
Please see the [changelog][link-changelog] for more information on what has changed recently.
Expand Down
12 changes: 7 additions & 5 deletions src/Twig/Node/DisplayEndNode.php
Expand Up @@ -4,6 +4,7 @@
namespace Shoot\Shoot\Twig\Node;

use Shoot\Shoot\Extension;
use Shoot\Shoot\SuppressedException;
use Shoot\Shoot\View;
use Twig_Compiler as Compiler;
use Twig_Node as Node;
Expand Down Expand Up @@ -43,13 +44,14 @@ public function compile(Compiler $compiler)
return;
}

$extension = Extension::class;
$extensionClass = Extension::class;
$suppressedExceptionClass = SuppressedException::class;
$templateName = $this->getTemplateName();
$view = View::class;
$viewClass = View::class;

$compiler
->raw("\n")
->write("if (\$suppressedException instanceof Shoot\\Shoot\\SuppressedException) {\n")
->write("if (\$suppressedException instanceof {$suppressedExceptionClass}) {\n")
->indent()
->write("throw \$suppressedException;\n")
->outdent()
Expand All @@ -58,8 +60,8 @@ public function compile(Compiler $compiler)
->write("};\n\n")
->write("\$this->env\n")
->indent()
->write("->getExtension({$extension}::class)\n")
->write("->process(new {$view}('{$templateName}', \$presentationModel, \$callback));\n")
->write("->getExtension({$extensionClass}::class)\n")
->write("->process(new {$viewClass}('{$templateName}', \$presentationModel, \$callback));\n")
->outdent();
}
}
13 changes: 11 additions & 2 deletions src/Twig/Node/OptionalNode.php
Expand Up @@ -3,7 +3,9 @@

namespace Shoot\Shoot\Twig\Node;

use Shoot\Shoot\SuppressedException;
use Twig_Compiler as Compiler;
use Twig_Error_Runtime as RuntimeError;
use Twig_Node as Node;

/**
Expand All @@ -30,19 +32,26 @@ public function __construct(Node $body, int $lineNumber, string $tag)
*/
public function compile(Compiler $compiler)
{
$runtimeErrorClass = RuntimeError::class;
$suppressedExceptionClass = SuppressedException::class;

$compiler
->write("try {\n")
->indent()
->write("ob_start();\n\n")
->subcompile($this->getNode('body'))
->raw("\n")
->write("echo ob_get_clean();\n")
->outdent()
->write("} catch (Twig_Error_Runtime \$exception) {\n")
->write("} catch ({$runtimeErrorClass} \$exception) {\n")
->indent()
->write("ob_end_clean();\n\n")
->write("if (\$exception->getPrevious() === null) {\n")
->indent()
->write("throw \$exception;\n")
->outdent()
->write("}\n\n")
->write("\$suppressedException = new Shoot\\Shoot\\SuppressedException(\$exception->getPrevious());\n")
->write("\$suppressedException = new {$suppressedExceptionClass}(\$exception->getPrevious());\n")
->outdent()
->write("}\n\n");
}
Expand Down
34 changes: 29 additions & 5 deletions tests/Integration/ErrorSuppression/ErrorSuppressionTest.php
Expand Up @@ -10,9 +10,15 @@ final class ErrorSuppressionTest extends IntegrationTestCase
/** @var string */
protected $templateDirectory = __DIR__ . '/Templates';

protected function setUp()
public function testTemplateShouldRenderIfNoExceptionIsThrown()
{
parent::setUp();
$output = $this->renderTemplate('page.twig');

$this->assertContains('<h1>page_title</h1>', $output);
$this->assertContains('<!-- before -->', $output);
$this->assertContains('<p>item</p>', $output);
$this->assertContains('<!-- after -->', $output);
$this->assertContains('<p>page_footer</p>', $output);
}

/**
Expand All @@ -22,6 +28,13 @@ public function testIncludedTemplateShouldThrowAnException()
{
$this->expectExceptionMessage('item_exception');

$this->request
->method('getAttribute')
->will($this->returnValueMap([
['throw_logic_exception', 'n', 'n'],
['throw_runtime_exception', 'n', 'y'],
]));

$this->renderTemplate('item.twig');
}

Expand All @@ -30,10 +43,19 @@ public function testIncludedTemplateShouldThrowAnException()
*/
public function testOptionalBlocksShouldDiscardTheirContentsOnRuntimeExceptions()
{
$this->request
->method('getAttribute')
->will($this->returnValueMap([
['throw_logic_exception', 'n', 'n'],
['throw_runtime_exception', 'n', 'y'],
]));

$output = $this->renderTemplate('page.twig');

$this->assertContains('<h1>page_title</h1>', $output);
$this->assertNotContains('<!-- hidden -->', $output);
$this->assertNotContains('<!-- before -->', $output);
$this->assertNotContains('<p>item</p>', $output);
$this->assertNotContains('<!-- after -->', $output);
$this->assertContains('<p>page_footer</p>', $output);
}

Expand All @@ -46,8 +68,10 @@ public function testOptionalBlocksShouldNotSuppressLogicExceptions()

$this->request
->method('getAttribute')
->with('throw_logic_exception')
->willReturn('y');
->will($this->returnValueMap([
['throw_logic_exception', 'n', 'y'],
['throw_runtime_exception', 'n', 'n'],
]));

$this->renderTemplate('page.twig');
}
Expand Down
Expand Up @@ -25,8 +25,10 @@ public function present(ServerRequestInterface $request, PresentationModel $pres
return $presentationModel->withVariables([
'throw_logic_exception' => true,
]);
} elseif ($request->getAttribute('throw_runtime_exception', 'n') === 'y') {
throw new RuntimeException('item_exception');
}

throw new RuntimeException('item_exception');
return $presentationModel;
}
}
1 change: 1 addition & 0 deletions tests/Integration/ErrorSuppression/Templates/item.twig
Expand Up @@ -2,3 +2,4 @@
{% if throw_logic_exception %}
{{ unknown_variable }}
{% endif %}
<p>item</p>
3 changes: 2 additions & 1 deletion tests/Integration/ErrorSuppression/Templates/page.twig
Expand Up @@ -7,8 +7,9 @@
<body>
<h1>page_title</h1>
{% optional %}
<!-- before -->
{% include 'item.twig' %}
<!-- hidden -->
<!-- after -->
{% endoptional %}
<p>page_footer</p>
</body>
Expand Down

0 comments on commit b0c8335

Please sign in to comment.