Skip to content

Commit 8fe391d

Browse files
committed
bug #1312 [TwigComponent] Fix TwigPreLexer edge case (smnandre)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [TwigComponent] Fix TwigPreLexer edge case | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | Issues | Fix #1306 | License | MIT Quick fix to handle commented blocks in sublexer `@weaverryan` `@WebMamba` it may need a second look as i find weird the changes made do not have any other impacts... Commits ------- 5c0a30f [TwigComponent] Fix TwigPreLexer edge case
2 parents ed24f53 + 5c0a30f commit 8fe391d

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

src/TwigComponent/src/Twig/TwigPreLexer.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,6 @@ private function consumeAttributes(string $componentName): string
263263
*/
264264
private function consume(string $string): bool
265265
{
266-
if ($string[0] !== $this->input[$this->position]) {
267-
return false;
268-
}
269-
270266
$stringLength = \strlen($string);
271267
if (substr($this->input, $this->position, $stringLength) === $string) {
272268
$this->position += $stringLength;
@@ -405,16 +401,24 @@ private function consumeUntilEndBlock(): string
405401
$start = $this->position;
406402

407403
$depth = 1;
404+
$inComment = false;
408405
while ($this->position < $this->length) {
409-
if ('</twig:block' === substr($this->input, $this->position, 12)) {
406+
if ($inComment && '#}' === substr($this->input, $this->position, 2)) {
407+
$inComment = false;
408+
}
409+
if (!$inComment && '{#' === substr($this->input, $this->position, 2)) {
410+
$inComment = true;
411+
}
412+
413+
if (!$inComment && '</twig:block>' === substr($this->input, $this->position, 13)) {
410414
if (1 === $depth) {
411415
break;
412416
} else {
413417
--$depth;
414418
}
415419
}
416420

417-
if ('{% endblock %}' === substr($this->input, $this->position, 14)) {
421+
if (!$inComment && '{% endblock %}' === substr($this->input, $this->position, 14)) {
418422
if (1 === $depth) {
419423
// in this case, we want to advanced ALL the way beyond the endblock
420424
$this->position += 14;
@@ -424,11 +428,11 @@ private function consumeUntilEndBlock(): string
424428
}
425429
}
426430

427-
if ('<twig:block' === substr($this->input, $this->position, 11)) {
431+
if (!$inComment && '<twig:block' === substr($this->input, $this->position, 11)) {
428432
++$depth;
429433
}
430434

431-
if ('{% block' === substr($this->input, $this->position, 8)) {
435+
if (!$inComment && '{% block' === substr($this->input, $this->position, 8)) {
432436
++$depth;
433437
}
434438

src/TwigComponent/tests/Unit/TwigPreLexerTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\UX\TwigComponent\Twig\TwigPreLexer;
16+
use Twig\Error\SyntaxError;
1617

1718
final class TwigPreLexerTest extends TestCase
1819
{
@@ -25,6 +26,26 @@ public function testPreLex(string $input, string $expectedOutput): void
2526
$this->assertSame($expectedOutput, $lexer->preLexComponents($input));
2627
}
2728

29+
/**
30+
* @dataProvider getInvalidSyntaxTests
31+
*/
32+
public function testPreLexThrowsExceptionOnInvalidSyntax(string $input, string $expectedMessage): void
33+
{
34+
$this->expectException(SyntaxError::class);
35+
$this->expectExceptionMessage($expectedMessage);
36+
37+
$lexer = new TwigPreLexer();
38+
$lexer->preLexComponents($input);
39+
}
40+
41+
public static function getInvalidSyntaxTests(): iterable
42+
{
43+
yield 'component_with_unclosed_block' => [
44+
'<twig:foo name="bar">{% block a %}</twig:foo>',
45+
'Expected closing tag "</twig:foo>" not found at line 1.',
46+
];
47+
}
48+
2849
public static function getLexTests(): iterable
2950
{
3051
yield 'simple_component' => [
@@ -62,6 +83,11 @@ public static function getLexTests(): iterable
6283
'Hello {% block foo_block %}Foo{% endblock %}{{ component(\'foo\') }}{% block bar_block %}Bar{% endblock %}',
6384
];
6485

86+
yield 'component_with_commented_block' => [
87+
'<twig:foo name="bar">{# {% block baz %}#}</twig:foo>',
88+
'{% component \'foo\' with { name: \'bar\' } %}{# {% block baz %}#}{% endcomponent %}',
89+
];
90+
6591
yield 'component_with_component_inside_block' => [
6692
'<twig:foo><twig:block name="foo_block"><twig:bar /></twig:block></twig:foo>',
6793
'{% component \'foo\' %}{% block foo_block %}{{ component(\'bar\') }}{% endblock %}{% endcomponent %}',

0 commit comments

Comments
 (0)