Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support yield rendering strategy in Twig 3.9+ #33

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions bundles/LayoutsBundle/Templating/Twig/Node/DefaultContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@

namespace Netgen\Bundle\LayoutsBundle\Templating\Twig\Node;

use Twig\Attribute\YieldReady;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Node;

#[YieldReady]
final class DefaultContext extends Node
{
public function __construct(AbstractExpression $expr, int $line = 0, ?string $tag = null)
public function __construct(AbstractExpression $expr, int $line = 0)
{
parent::__construct(['expr' => $expr], [], $line, $tag);
parent::__construct(['expr' => $expr], [], $line);
}

public function compile(Compiler $compiler): void
Expand Down
21 changes: 17 additions & 4 deletions bundles/LayoutsBundle/Templating/Twig/Node/RenderZone.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,25 @@
use Netgen\Layouts\API\Values\Layout\Zone;
use Netgen\Layouts\View\Twig\ContextualizedTwigTemplate;
use Netgen\Layouts\View\ViewInterface;
use Twig\Attribute\YieldReady;
use Twig\Compiler;
use Twig\Environment;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Node;

use const PHP_EOL;

#[YieldReady]
final class RenderZone extends Node
{
public function __construct(AbstractExpression $zone, ?AbstractExpression $context = null, int $line = 0, ?string $tag = null)
public function __construct(AbstractExpression $zone, ?AbstractExpression $context = null, int $line = 0)
{
$nodes = ['zone' => $zone];
if ($context instanceof AbstractExpression) {
$nodes['context'] = $context;
}

parent::__construct($nodes, [], $line, $tag);
parent::__construct($nodes, [], $line);
}

public function compile(Compiler $compiler): void
Expand All @@ -36,9 +39,8 @@ public function compile(Compiler $compiler): void
->write('$nglZoneIdentifier = $nglZone instanceof ' . Zone::class . ' ? $nglZone->getIdentifier() : $nglZone;' . PHP_EOL);

$this->compileContextNode($compiler);

$compiler->write('$nglTemplate = new ' . ContextualizedTwigTemplate::class . '($this, $context, $blocks);' . PHP_EOL);
$compiler->write('$this->env->getRuntime("' . RenderingRuntime::class . '")->displayZone($context["nglayouts"]->getLayout(), $nglZoneIdentifier, $nglContext, $nglTemplate);' . PHP_EOL);
$this->compileRenderNode($compiler);
}

/**
Expand All @@ -62,4 +64,15 @@ private function compileContextNode(Compiler $compiler): void

$compiler->write('$nglContext = ' . ViewInterface::class . '::CONTEXT_DEFAULT;' . PHP_EOL);
}

private function compileRenderNode(Compiler $compiler): void
{
if (Environment::VERSION_ID >= 30900) {
$compiler->write('yield $this->env->getRuntime("' . RenderingRuntime::class . '")->renderZone($context["nglayouts"]->getLayout(), $nglZoneIdentifier, $nglContext, $nglTemplate);' . PHP_EOL);

return;
}

$compiler->write('echo $this->env->getRuntime("' . RenderingRuntime::class . '")->renderZone($context["nglayouts"]->getLayout(), $nglZoneIdentifier, $nglContext, $nglTemplate);' . PHP_EOL);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
use Ramsey\Uuid\Uuid;
use Throwable;
use Twig\Environment;
use Twig\Extension\CoreExtension;

use function array_unshift;
use function is_string;
use function method_exists;
use function twig_date_converter;

final class HelpersRuntime
Expand Down Expand Up @@ -121,7 +123,11 @@ public function getCountryFlag(string $countryCode): string
*/
public function formatDateTime(Environment $twig, $dateTime, string $dateFormat = 'medium', string $timeFormat = 'medium'): string
{
$dateTime = twig_date_converter($twig, $dateTime);
$coreExtension = $twig->getExtension(CoreExtension::class);

$dateTime = method_exists($coreExtension, 'convertDate') ?
$coreExtension->convertDate($dateTime) :
twig_date_converter($twig, $dateTime);

$formatValues = [
'none' => IntlDateFormatter::NONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ public function renderValue(array $context, $value, array $parameters = [], ?str
}

/**
* Displays the provided zone.
* Renders the provided zone.
*/
public function displayZone(Layout $layout, string $zoneIdentifier, string $viewContext, ContextualizedTwigTemplate $twigTemplate): void
public function renderZone(Layout $layout, string $zoneIdentifier, string $viewContext, ContextualizedTwigTemplate $twigTemplate): string
{
$locales = null;

Expand All @@ -178,7 +178,7 @@ public function displayZone(Layout $layout, string $zoneIdentifier, string $view
$locales,
);

echo $this->renderValue(
return $this->renderValue(
[],
new ZoneReference($layout, $zoneIdentifier),
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function parse(Token $token): Node

$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);

return new DefaultContextNode($expression, $token->getLine(), $this->getTag());
return new DefaultContextNode($expression, $token->getLine());
}

public function getTag(): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function parse(Token $token): Node

$stream->expect(Token::BLOCK_END_TYPE);

return new RenderZoneNode($zone, $context, $token->getLine(), $this->getTag());
return new RenderZoneNode($zone, $context, $token->getLine());
}

public function getTag(): string
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"symfony/twig-bundle": "^3.4.47 || ^5.4 || ^6.2",
"symfony/validator": "^3.4.47 || ^5.4 || ^6.2",
"symfony/yaml": "^3.4.47 || ^5.4 || ^6.2",
"twig/twig": "^2.15 || ^3.4",
"twig/twig": "^2.15 || ^3.9",
"sensio/framework-extra-bundle": "^5.4 || ^6.2",
"doctrine/dbal": "^2.13 || ^3.5",
"doctrine/doctrine-bundle": "^1.12 || ^2.7",
Expand Down
5 changes: 1 addition & 4 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ parameters:
treatPhpDocTypesAsCertain: false
dynamicConstantNames:
- Symfony\Component\HttpKernel\Kernel::VERSION_ID
- Twig\Environment::VERSION_ID

ignoreErrors:
# Doctrine DBAL
Expand Down Expand Up @@ -49,10 +50,6 @@ parameters:
- "#Call to function method_exists\\(\\) with Symfony\\\\Component\\\\HttpFoundation\\\\Request and 'getContentTypeFormat' will always evaluate to true.#"
- "#Call to function method_exists\\(\\) with Symfony\\\\Component\\\\DependencyInjection\\\\ContainerBuilder and 'registerAttributeFo…' will always evaluate to true.#"

-
message: '#twig_date_converter not found.#'
path: bundles/LayoutsBundle/Templating/Twig/Runtime/HelpersRuntime.php

# Netgen Layouts specifics

- "#Call to function method_exists\\(\\) with Netgen\\\\Layouts\\\\Layout\\\\Resolver\\\\(Condition|Target)TypeInterface and '(export|import)' will always evaluate to true.#"
Expand Down
3 changes: 3 additions & 0 deletions phpstan.tests.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ parameters:
treatPhpDocTypesAsCertain: false
dynamicConstantNames:
- Symfony\Component\HttpKernel\Kernel::VERSION_ID
- Twig\Environment::MAJOR_VERSION

excludePaths:
- tests/application/public/bundles/
Expand Down Expand Up @@ -53,6 +54,8 @@ parameters:
message: '#Undefined variable: \$this#'
path: tests/lib/Transfer/Output/Visitor/Integration

- "#Call to function method_exists\\(\\) with .* and 'setNodeTag' will always evaluate to true.#"

-
message: "#Offset 'db' does not exist on array#"
path: tests/lib/Persistence/Doctrine/DatabaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected function setUp(): void
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::displayZone
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::renderZone
*
* @dataProvider getTests
*
Expand All @@ -74,7 +74,7 @@ public function testIntegration($file, $message, $condition, $templates, $except
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::displayZone
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::renderZone
*
* @dataProvider getTests
*
Expand All @@ -97,7 +97,7 @@ public function testIntegrationWithLocale($file, $message, $condition, $template
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::displayZone
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::renderZone
*
* @dataProvider getLegacyTests
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Netgen\Bundle\LayoutsBundle\Tests\Templating\Twig\Node;

use Netgen\Bundle\LayoutsBundle\Templating\Twig\Node\DefaultContext;
use Twig\Environment;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\NameExpression;

Expand All @@ -13,6 +14,13 @@
*/
final class DefaultContextTest extends NodeTestBase
{
protected function setUp(): void
{
if (Environment::MAJOR_VERSION === 2) {
self::markTestSkipped('Test requires twig/twig 3.9 to run');
}
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Node\DefaultContext::__construct
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,24 @@
use Netgen\Layouts\API\Values\Layout\Zone;
use Netgen\Layouts\View\Twig\ContextualizedTwigTemplate;
use Netgen\Layouts\View\ViewInterface;
use Twig\Environment;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\NameExpression;

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Node\RenderZone::compile
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Node\RenderZone::compileContextNode
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Node\RenderZone::compileRenderNode
*/
final class RenderZoneTest extends NodeTestBase
{
protected function setUp(): void
{
if (Environment::MAJOR_VERSION === 2) {
self::markTestSkipped('Test requires twig/twig 3.9 to run');
}
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Node\RenderZone::__construct
*/
Expand Down Expand Up @@ -69,7 +78,7 @@ public static function getTests(): array
\$nglZoneIdentifier = \$nglZone instanceof {$zoneClass} ? \$nglZone->getIdentifier() : \$nglZone;
\$nglContext = {$contextNodeGetter};
\$nglTemplate = new {$templateClass}(\$this, \$context, \$blocks);
\$this->env->getRuntime("{$runtimeClass}")->displayZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
yield \$this->env->getRuntime("{$runtimeClass}")->renderZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
EOT,
$environment,
],
Expand All @@ -81,7 +90,7 @@ public static function getTests(): array
\$nglZoneIdentifier = \$nglZone instanceof {$zoneClass} ? \$nglZone->getIdentifier() : \$nglZone;
\$nglContext = {$contextNodeGetter};
\$nglTemplate = new {$templateClass}(\$this, \$context, \$blocks);
\$this->env->getRuntime("{$runtimeClass}")->displayZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
yield \$this->env->getRuntime("{$runtimeClass}")->renderZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
EOT,
$environment,
],
Expand All @@ -93,7 +102,7 @@ public static function getTests(): array
\$nglZoneIdentifier = \$nglZone instanceof {$zoneClass} ? \$nglZone->getIdentifier() : \$nglZone;
\$nglContext = {$viewInterface}::CONTEXT_DEFAULT;
\$nglTemplate = new {$templateClass}(\$this, \$context, \$blocks);
\$this->env->getRuntime("{$runtimeClass}")->displayZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
yield \$this->env->getRuntime("{$runtimeClass}")->renderZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
EOT,
$environment,
],
Expand All @@ -105,7 +114,7 @@ public static function getTests(): array
\$nglZoneIdentifier = \$nglZone instanceof {$zoneClass} ? \$nglZone->getIdentifier() : \$nglZone;
\$nglContext = {$viewInterface}::CONTEXT_DEFAULT;
\$nglTemplate = new {$templateClass}(\$this, \$context, \$blocks);
\$this->env->getRuntime("{$runtimeClass}")->displayZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
yield \$this->env->getRuntime("{$runtimeClass}")->renderZone(\$context["nglayouts"]->getLayout(), \$nglZoneIdentifier, \$nglContext, \$nglTemplate);
EOT,
$environment,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@

namespace Netgen\Bundle\LayoutsBundle\Tests\Templating\Twig\Runtime;

use Doctrine\Common\Collections\ArrayCollection;
use Exception;
use Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime;
use Netgen\Layouts\API\Service\BlockService;
use Netgen\Layouts\API\Values\Block\Block;
use Netgen\Layouts\API\Values\Block\BlockList;
use Netgen\Layouts\API\Values\Block\Placeholder;
use Netgen\Layouts\API\Values\Collection\Item;
use Netgen\Layouts\API\Values\Collection\Slot;
use Netgen\Layouts\API\Values\Layout\Layout;
use Netgen\Layouts\API\Values\Layout\Zone;
use Netgen\Layouts\API\Values\LayoutResolver\RuleCondition;
use Netgen\Layouts\Block\BlockDefinition;
use Netgen\Layouts\Collection\Result\ManualItem;
Expand All @@ -21,6 +25,7 @@
use Netgen\Layouts\Tests\Stubs\ErrorHandler;
use Netgen\Layouts\View\RendererInterface;
use Netgen\Layouts\View\Twig\ContextualizedTwigTemplate;
use Netgen\Layouts\View\View\ZoneView\ZoneReference;
use Netgen\Layouts\View\ViewInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -60,6 +65,54 @@ protected function setUp(): void
);
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::__construct
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::getViewContext
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::renderZone
*/
public function testRenderZone(): void
{
$zone = Zone::fromArray([]);
$blocks = new BlockList();
$layout = Layout::fromArray(['zones' => new ArrayCollection(['zone' => $zone])]);

$twigTemplate = new ContextualizedTwigTemplate($this->createMock(Template::class));

$this->blockServiceMock
->expects(self::once())
->method('loadZoneBlocks')
->with(
self::identicalTo($zone),
self::isNull(),
)
->willReturn($blocks);

$this->rendererMock
->expects(self::once())
->method('renderValue')
->with(
self::isInstanceOf(ZoneReference::class),
self::identicalTo(ViewInterface::CONTEXT_DEFAULT),
self::identicalTo(
[
'blocks' => $blocks,
'twig_template' => $twigTemplate,
],
),
)
->willReturn('rendered zone');

self::assertSame(
'rendered zone',
$this->runtime->renderZone(
$layout,
'zone',
ViewInterface::CONTEXT_DEFAULT,
$twigTemplate,
),
);
}

/**
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::__construct
* @covers \Netgen\Bundle\LayoutsBundle\Templating\Twig\Runtime\RenderingRuntime::getViewContext
Expand Down
Loading
Loading