Skip to content

Commit

Permalink
[TwigHooks] Allow discarding hookable's context
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubtobiasz committed Apr 23, 2024
1 parent c4fb80f commit c502cf6
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 9 deletions.
7 changes: 6 additions & 1 deletion src/TwigHooks/src/Twig/Node/HookNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class HookNode extends Node
public function __construct (
Node $name,
?Node $context,
bool $only,
int $lineno,
string $tag = null
) {
Expand All @@ -22,7 +23,9 @@ public function __construct (
'name' => $name,
'hook_level_context' => $context ?? new ArrayExpression([], $lineno),
],
[],
[
'only' => $only,
],
$lineno,
$tag,
);
Expand All @@ -43,6 +46,8 @@ public function compile(Compiler $compiler): void
$compiler->subcompile($this->getNode('hook_level_context'));
$compiler->raw(', ');
$compiler->raw('$context["hookable_metadata"] ?? null');
$compiler->raw(', ');
$compiler->raw($this->getAttribute('only') ? 'true' : 'false');
$compiler->raw(");\n");
}
}
19 changes: 12 additions & 7 deletions src/TwigHooks/src/Twig/Runtime/HooksRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,16 @@ public function getHookableConfiguration(array $context): ParameterBagInterface
* @param string|array<string> $hookNames
* @param array<string, mixed> $hookContext
*/
public function renderHook(string|array $hookNames, array $hookContext = [], ?HookableMetadata $hookableMetadata = null): string
public function renderHook(
string|array $hookNames,
array $hookContext = [],
?HookableMetadata $hookableMetadata = null,
bool $only = false,
): string
{
$hookNames = is_string($hookNames) ? [$hookNames] : $hookNames;

$context = $this->getContext($hookContext, $hookableMetadata);
$context = $this->getContext($hookContext, $hookableMetadata, $only);
$prefixes = $this->getPrefixes($hookContext, $hookableMetadata);

if (false === $this->enableAutoprefixing || [] === $prefixes) {
Expand Down Expand Up @@ -105,14 +110,14 @@ private function getPrefixes(array $hookContext, ?HookableMetadata $hookableMeta
* @param array<string, mixed> $hookContext
* @return array<string, mixed>
*/
private function getContext(array $hookContext, ?HookableMetadata $hookableMetadata): array
private function getContext(array $hookContext, ?HookableMetadata $hookableMetadata, bool $only = false): array
{
$context = [];

if ($hookableMetadata !== null) {
$context = $hookableMetadata->context->all();
if ($only) {
return $hookContext;
}

$context = $hookableMetadata?->context->all() ?? [];

return array_merge($context, $hookContext);
}
}
7 changes: 6 additions & 1 deletion src/TwigHooks/src/Twig/TokenParser/HookTokenParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ public function parse(Token $token): Node
$hookContext = $this->parser->getExpressionParser()->parseMultitargetExpression();
}

$only = false;
if ($stream->nextIf(Token::NAME_TYPE, 'only')) {
$only = true;
}

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

return new HookNode($hooksNames, $hookContext, $lineno, $this->getTag());
return new HookNode($hooksNames, $hookContext, $only, $lineno, $this->getTag());
}

public function getTag(): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,21 @@ twig_hooks:
'hook_with_hookable':
hookable:
template: 'parsing_hook_tag_test/hook_with_hookables/hookable_with_hook.html.twig'

'restricting_context_scope.index':
with_only:
template: 'restricting_context_scope/index/with_only.html.twig'
context:
'other': 'data'
without_only:
template: 'restricting_context_scope/index/without_only.html.twig'
context:
'other': 'data'

'restricting_context_scope.index.with_only':
some:
template: 'restricting_context_scope/index/block/some.html.twig'

'restricting_context_scope.index.without_only':
some:
template: 'restricting_context_scope/index/block/some.html.twig'
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% hook 'restricting_context_scope.index' with {
some: 'data',
} %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% set hookable_context = get_hookable_context() %}

{{ hookable_context.get('title') }}

is "some" defined: {{ hookable_context.has('some') ? 'Yes' : 'No' }}
is "other" defined: {{ hookable_context.has('other') ? 'Yes' : 'No' }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% hook 'with_only' with {
title: 'Only',
} only %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% hook 'without_only' with {
title: 'Without only',
} %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Functional\Twig;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Twig\Environment as Twig;

/**
* @group kernel-required
*/
final class RestrictingContextScopeTest extends KernelTestCase
{
public function testItRendersSingleHookName(): void
{
$this->assertSame(
<<<EXPECTED
<!-- BEGIN HOOK | name: "restricting_context_scope.index" -->
<!-- BEGIN HOOKABLE | hook: "restricting_context_scope.index", type: "template", name: "with_only", target: "restricting_context_scope/index/with_only.html.twig", priority: 0 -->
<!-- BEGIN HOOK | name: "restricting_context_scope.index.with_only" -->
<!-- BEGIN HOOKABLE | hook: "restricting_context_scope.index.with_only", type: "template", name: "some", target: "restricting_context_scope/index/block/some.html.twig", priority: 0 -->
Only
is "some" defined: No
is "other" defined: No
<!-- END HOOKABLE | hook: "restricting_context_scope.index.with_only", type: "template", name: "some", target: "restricting_context_scope/index/block/some.html.twig", priority: 0 -->
<!-- END HOOK | name: "restricting_context_scope.index.with_only" -->
<!-- END HOOKABLE | hook: "restricting_context_scope.index", type: "template", name: "with_only", target: "restricting_context_scope/index/with_only.html.twig", priority: 0 -->
<!-- BEGIN HOOKABLE | hook: "restricting_context_scope.index", type: "template", name: "without_only", target: "restricting_context_scope/index/without_only.html.twig", priority: 0 -->
<!-- BEGIN HOOK | name: "restricting_context_scope.index.without_only" -->
<!-- BEGIN HOOKABLE | hook: "restricting_context_scope.index.without_only", type: "template", name: "some", target: "restricting_context_scope/index/block/some.html.twig", priority: 0 -->
Without only
is "some" defined: Yes
is "other" defined: Yes
<!-- END HOOKABLE | hook: "restricting_context_scope.index.without_only", type: "template", name: "some", target: "restricting_context_scope/index/block/some.html.twig", priority: 0 -->
<!-- END HOOK | name: "restricting_context_scope.index.without_only" -->
<!-- END HOOKABLE | hook: "restricting_context_scope.index", type: "template", name: "without_only", target: "restricting_context_scope/index/without_only.html.twig", priority: 0 -->
<!-- END HOOK | name: "restricting_context_scope.index" -->
EXPECTED,
$this->render('restricting_context_scope/index.html.twig'),
);
}

private function render(string $path): string
{
/** @var Twig $twig */
$twig = $this->getContainer()->get('twig');

return $twig->render($path);
}
}

0 comments on commit c502cf6

Please sign in to comment.