Skip to content

Commit

Permalink
feature #4199 Do not hide unnecessary escape characters (ruudk)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 4.x branch.

Discussion
----------

Do not hide unnecessary escape characters

Follow up of #4176, #4123 and #2712.

Now that we have deprecated unnecessary escape in v3, we can change the behavior in v4.

With this change, unnecessary will no longer be ignored, but handled like any other character.

This allows for writing fully qualified class names like this:
```twig
{{ constant('App\Entity\User::SOME_CONSTANT') }}
```

Instead of having to escape the `\` in v3:
```twig
{{ constant('App\\Entity\\User::SOME_CONSTANT') }}
```

/cc `@fabpot` `@stof`

Commits
-------

53c24bf Do not hide unnecessary escape characters
  • Loading branch information
fabpot committed Aug 21, 2024
2 parents 878d2a2 + 53c24bf commit 8da936a
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 60 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
* Change the compilation of `for` loops to throw an exception when a `loop.*` variable is not defined
* Make `Environment::getGlobals()` private
* Drop support for PHP < 8.2
* Escape characters are no longer ignored
10 changes: 2 additions & 8 deletions src/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,7 @@ private function stripcslashes(string $str, string $quoteType): string

if (isset(self::SPECIAL_CHARS[$nextChar])) {
$result .= self::SPECIAL_CHARS[$nextChar];
} elseif ('\\' === $nextChar) {
$result .= $nextChar;
} elseif ("'" === $nextChar || '"' === $nextChar) {
if ($nextChar !== $quoteType) {
trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.', $nextChar, $i + 1);
}
} elseif ($nextChar === '\\' || $nextChar === $quoteType) {
$result .= $nextChar;
} elseif ('#' === $nextChar && $i + 1 < $length && '{' === $str[$i + 1]) {
$result .= '#{';
Expand All @@ -451,8 +446,7 @@ private function stripcslashes(string $str, string $quoteType): string
}
$result .= \chr(octdec($octal));
} else {
trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.', $nextChar, $i + 1);
$result .= $nextChar;
$result .= '\\'.$nextChar;
}

++$i;
Expand Down
14 changes: 14 additions & 0 deletions tests/Fixtures/escape_characters.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
Exception with bad line number
--TEMPLATE--
{{ 'Foo\Bar' }}
{{ 'Foo\\Bar' }}
{{ 'Foo\\\Bar' }}
{{ 'Foo\\\\Bar' }}
--DATA--
return []
--EXPECT--
Foo\Bar
Foo\Bar
Foo\\Bar
Foo\\Bar
10 changes: 0 additions & 10 deletions tests/Fixtures/functions/enum_cases/invalid_enum_escaping.test

This file was deleted.

9 changes: 7 additions & 2 deletions tests/Fixtures/functions/enum_cases/valid.test
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
{% for c in enum_cases('Twig\\Tests\\DummyBackedEnum') %}
{{~ c.name }}: {{ c.value }}
{% endfor %}
{% for c in enum_cases('Twig\\Tests\\DummyUnitEnum') %}
{% for c in enum_cases('Twig\Tests\DummyBackedEnum') %}
{{~ c.name }}: {{ c.value }}
{% endfor %}
{% for c in enum_cases('Twig\Tests\DummyUnitEnum') %}
{{~ c.name }}
{% endfor %}
{% set from_variable='Twig\\Tests\\DummyUnitEnum' %}
{% set from_variable='Twig\Tests\DummyUnitEnum' %}
{% for c in enum_cases(from_variable) %}
{{~ c.name }}
{% endfor %}
Expand All @@ -18,6 +21,8 @@ return []
--EXPECT--
FOO: foo
BAR: bar
FOO: foo
BAR: bar
BAR
BAZ
BAR
Expand Down
52 changes: 12 additions & 40 deletions tests/LexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/

use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Twig\Environment;
use Twig\Error\SyntaxError;
use Twig\Lexer;
Expand All @@ -22,8 +21,6 @@

class LexerTest extends TestCase
{
use ExpectDeprecationTrait;

public function testNameLabelForTag()
{
$template = '{% § %}';
Expand Down Expand Up @@ -195,6 +192,18 @@ public function testStringWithEscapedDelimiter(string $template, string $expecte

public function getStringWithEscapedDelimiter()
{
yield '{{ \'App\Test\' }} => App\Test' => [
'{{ \'App\\Test\' }}',
'App\Test',
];
yield '{{ "foo \\\' bar" }} => foo \' bar' => [
'{{ "foo \\\' bar" }}',
"foo \' bar",
];
yield '{{ \'foo \" bar\' }} => foo \" bar' => [
'{{ \'foo \\" bar\' }}',
'foo \" bar',
];
yield '{{ \'\x6\' }} => \x6' => [
'{{ \'\x6\' }}',
"\x6",
Expand Down Expand Up @@ -229,43 +238,6 @@ public function getStringWithEscapedDelimiter()
];
}

/**
* @group legacy
* @dataProvider getStringWithEscapedDelimiterProducingDeprecation
*/
public function testStringWithEscapedDelimiterProducingDeprecation(string $template, string $expected, string $expectedDeprecation)
{
$this->expectDeprecation($expectedDeprecation);

$lexer = new Lexer(new Environment(new ArrayLoader()));
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, $expected);

// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
}

public function getStringWithEscapedDelimiterProducingDeprecation()
{
yield '{{ \'App\Test\' }} => AppTest' => [
'{{ \'App\\Test\' }}',
'AppTest',
'Since twig/twig 3.12: Character "T" at position 5 should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.',
];
yield '{{ "foo \\\' bar" }} => foo \' bar' => [
'{{ "foo \\\' bar" }}',
'foo \' bar',
'Since twig/twig 3.12: Character "\'" at position 6 should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.',
];
yield '{{ \'foo \" bar\' }} => foo " bar' => [
'{{ \'foo \\" bar\' }}',
'foo " bar',
'Since twig/twig 3.12: Character """ at position 6 should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.',
];
}

public function testStringWithInterpolation()
{
$template = 'foo {{ "bar #{ baz + 1 }" }}';
Expand Down

0 comments on commit 8da936a

Please sign in to comment.