Skip to content

Commit a303a03

Browse files
committed
don't use deprecated and internal Twig functions
1 parent 52839be commit a303a03

File tree

4 files changed

+86
-23
lines changed

4 files changed

+86
-23
lines changed

src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Twig\Node;
1313

1414
use Twig\Compiler;
15+
use Twig\Extension\CoreExtension;
1516
use Twig\Node\Expression\ArrayExpression;
1617
use Twig\Node\Expression\ConstantExpression;
1718
use Twig\Node\Expression\FunctionExpression;
@@ -50,7 +51,7 @@ public function compile(Compiler $compiler): void
5051
$labelIsExpression = false;
5152

5253
// Only insert the label into the array if it is not empty
53-
if (!twig_test_empty($label->getAttribute('value'))) {
54+
if (!self::isEmpty($label->getAttribute('value'))) {
5455
$originalVariables = $variables;
5556
$variables = new ArrayExpression([], $lineno);
5657
$labelKey = new ConstantExpression('label', $lineno);
@@ -97,7 +98,12 @@ public function compile(Compiler $compiler): void
9798

9899
// Check at runtime whether the label is empty.
99100
// If not, add it to the array at runtime.
100-
$compiler->raw('(twig_test_empty($_label_ = ');
101+
if (method_exists(CoreExtension::class, 'testEmpty')) {
102+
$compiler->raw('(Twig\Extension\CoreExtension::testEmpty($_label_ = ');
103+
} else {
104+
$compiler->raw('(twig_test_empty($_label_ = ');
105+
}
106+
101107
$compiler->subcompile($label);
102108
$compiler->raw(') ? [] : ["label" => $_label_])');
103109
}
@@ -107,4 +113,24 @@ public function compile(Compiler $compiler): void
107113

108114
$compiler->raw(')');
109115
}
116+
117+
/**
118+
* @see \Twig\Extension\CoreExtension::testEmpty()
119+
*/
120+
private static function isEmpty($value): bool
121+
{
122+
if ($value instanceof \Countable) {
123+
return 0 === \count($value);
124+
}
125+
126+
if ($value instanceof \Traversable) {
127+
return !iterator_count($value);
128+
}
129+
130+
if (\is_object($value) && method_exists($value, '__toString')) {
131+
return '' === (string) $value;
132+
}
133+
134+
return '' === $value || false === $value || null === $value || [] === $value;
135+
}
110136
}

src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode;
1616
use Twig\Compiler;
1717
use Twig\Environment;
18+
use Twig\Extension\CoreExtension;
1819
use Twig\Loader\LoaderInterface;
1920
use Twig\Node\Expression\ArrayExpression;
2021
use Twig\Node\Expression\ConditionalExpression;
@@ -224,13 +225,11 @@ public function testCompileLabelWithLabelThatEvaluatesToNull()
224225
// "label" => null must not be included in the output!
225226
// Otherwise the default label is overwritten with null.
226227
// https://github.com/symfony/symfony/issues/5029
227-
$this->assertEquals(
228-
sprintf(
229-
'$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))',
230-
$this->getVariableGetter('form')
231-
),
232-
trim($compiler->compile($node)->getSource())
233-
);
228+
if (method_exists(CoreExtension::class, 'testEmpty')) {
229+
$this->assertEquals(sprintf('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', (Twig\Extension\CoreExtension::testEmpty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))', $this->getVariableGetter('form')), trim($compiler->compile($node)->getSource()));
230+
} else {
231+
$this->assertEquals(sprintf('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))', $this->getVariableGetter('form')), trim($compiler->compile($node)->getSource()));
232+
}
234233
}
235234

236235
public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes()
@@ -261,13 +260,11 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes()
261260
// "label" => null must not be included in the output!
262261
// Otherwise the default label is overwritten with null.
263262
// https://github.com/symfony/symfony/issues/5029
264-
$this->assertEquals(
265-
sprintf(
266-
'$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["foo" => "bar", "label" => "value in attributes"] + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))',
267-
$this->getVariableGetter('form')
268-
),
269-
trim($compiler->compile($node)->getSource())
270-
);
263+
if (method_exists(CoreExtension::class, 'testEmpty')) {
264+
$this->assertEquals(sprintf('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["foo" => "bar", "label" => "value in attributes"] + (Twig\Extension\CoreExtension::testEmpty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))', $this->getVariableGetter('form')), trim($compiler->compile($node)->getSource()));
265+
} else {
266+
$this->assertEquals(sprintf('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["foo" => "bar", "label" => "value in attributes"] + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))', $this->getVariableGetter('form')), trim($compiler->compile($node)->getSource()));
267+
}
271268
}
272269

273270
protected function getVariableGetter($name)

src/Symfony/Bundle/WebProfilerBundle/Tests/Twig/WebProfilerExtensionTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
use Symfony\Bundle\WebProfilerBundle\Twig\WebProfilerExtension;
1616
use Symfony\Component\VarDumper\Cloner\VarCloner;
1717
use Twig\Environment;
18-
use Twig\Extension\CoreExtension;
19-
use Twig\Extension\EscaperExtension;
2018

2119
class WebProfilerExtensionTest extends TestCase
2220
{
@@ -25,9 +23,6 @@ class WebProfilerExtensionTest extends TestCase
2523
*/
2624
public function testDumpHeaderIsDisplayed(string $message, array $context, bool $dump1HasHeader, bool $dump2HasHeader)
2725
{
28-
class_exists(CoreExtension::class); // Load twig_convert_encoding()
29-
class_exists(EscaperExtension::class); // Load twig_escape_filter()
30-
3126
$twigEnvironment = $this->mockTwigEnvironment();
3227
$varCloner = new VarCloner();
3328

src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ public function dumpData(Environment $env, Data $data, int $maxDepth = 0)
8787

8888
public function dumpLog(Environment $env, string $message, Data $context = null)
8989
{
90-
$message = twig_escape_filter($env, $message);
90+
$message = self::escape($message, $env->getCharset());
9191
$message = preg_replace('/&quot;(.*?)&quot;/', '&quot;<b>$1</b>&quot;', $message);
9292

9393
$replacements = [];
9494
foreach ($context ?? [] as $k => $v) {
95-
$k = '{'.twig_escape_filter($env, $k).'}';
95+
$k = '{'.self::escape($k, $env->getCharset()).'}';
9696
if (str_contains($message, $k)) {
9797
$replacements[$k] = $v;
9898
}
@@ -116,4 +116,49 @@ public function getName()
116116
{
117117
return 'profiler';
118118
}
119+
120+
/**
121+
* @see \Twig\Extension\EscaperExtension::escape()
122+
*/
123+
private static function escape(string $s, string $charset): string
124+
{
125+
if ('' === $s) {
126+
return '';
127+
}
128+
129+
// see https://www.php.net/htmlspecialchars
130+
131+
// Using a static variable to avoid initializing the array
132+
// each time the function is called. Moving the declaration on the
133+
// top of the function slow downs other escaping strategies.
134+
static $htmlspecialcharsCharsets = [
135+
'ISO-8859-1' => true, 'ISO8859-1' => true,
136+
'ISO-8859-15' => true, 'ISO8859-15' => true,
137+
'utf-8' => true, 'UTF-8' => true,
138+
'CP866' => true, 'IBM866' => true, '866' => true,
139+
'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
140+
'1251' => true,
141+
'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
142+
'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
143+
'BIG5' => true, '950' => true,
144+
'GB2312' => true, '936' => true,
145+
'BIG5-HKSCS' => true,
146+
'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
147+
'EUC-JP' => true, 'EUCJP' => true,
148+
'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
149+
];
150+
151+
if (isset($htmlspecialcharsCharsets[$charset])) {
152+
return htmlspecialchars($s, \ENT_QUOTES | \ENT_SUBSTITUTE, $charset);
153+
}
154+
155+
if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
156+
// cache the lowercase variant for future iterations
157+
$htmlspecialcharsCharsets[$charset] = true;
158+
159+
return htmlspecialchars($s, \ENT_QUOTES | \ENT_SUBSTITUTE, $charset);
160+
}
161+
162+
return iconv('UTF-8', $charset, htmlspecialchars(iconv($s, $charset, 'UTF-8'), \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8'));
163+
}
119164
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy