Skip to content

Commit 5eb2fec

Browse files
committed
fix web profiler bundle file formatting: missing indent
1 parent d15ea08 commit 5eb2fec

File tree

4 files changed

+166
-26
lines changed

4 files changed

+166
-26
lines changed

src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -119,39 +119,85 @@ public function formatArgsAsText(array $args): string
119119
*/
120120
public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?string
121121
{
122-
if (is_file($file) && is_readable($file)) {
123-
// highlight_file could throw warnings
124-
// see https://bugs.php.net/25725
125-
$code = @highlight_file($file, true);
126-
if (\PHP_VERSION_ID >= 80300) {
127-
// remove main pre/code tags
128-
$code = preg_replace('#^<pre.*?>\s*<code.*?>(.*)</code>\s*</pre>#s', '\\1', $code);
129-
// split multiline span tags
130-
$code = preg_replace_callback('#<span ([^>]++)>((?:[^<\\n]*+\\n)++[^<]*+)</span>#', function ($m) {
131-
return "<span $m[1]>".str_replace("\n", "</span>\n<span $m[1]>", $m[2]).'</span>';
132-
}, $code);
133-
$content = explode("\n", $code);
134-
} else {
135-
// remove main code/span tags
136-
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
137-
// split multiline spans
138-
$code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', fn ($m) => "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>', $code);
139-
$content = explode('<br />', $code);
140-
}
122+
if (!is_file($file) || !is_readable($file)) {
123+
return null;
124+
}
125+
126+
$contents = file_get_contents($file);
127+
128+
if (!str_contains($contents, '<?php') && !str_contains($contents, '<?=')) {
129+
$lines = explode(\PHP_EOL, $contents);
141130

142-
$lines = [];
143131
if (0 > $srcContext) {
144-
$srcContext = \count($content);
132+
$srcContext = \count($lines);
145133
}
146134

147-
for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) {
148-
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><a class="anchor" id="line'.$i.'"></a><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
149-
}
135+
return $this->formatFileExcerpt(
136+
$this->extractExcerptLines($lines, $line, $srcContext),
137+
$line,
138+
$srcContext
139+
);
140+
}
150141

151-
return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
142+
// highlight_string could throw warnings
143+
// see https://bugs.php.net/25725
144+
$code = @highlight_string($contents, true);
145+
146+
if (\PHP_VERSION_ID >= 80300) {
147+
// remove main pre/code tags
148+
$code = preg_replace('#^<pre.*?>\s*<code.*?>(.*)</code>\s*</pre>#s', '\\1', $code);
149+
// split multiline span tags
150+
$code = preg_replace_callback(
151+
'#<span ([^>]++)>((?:[^<\\n]*+\\n)++[^<]*+)</span>#',
152+
static fn (array $m): string => "<span $m[1]>".str_replace("\n", "</span>\n<span $m[1]>", $m[2]).'</span>',
153+
$code
154+
);
155+
$lines = explode("\n", $code);
156+
} else {
157+
// remove main code/span tags
158+
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
159+
// split multiline spans
160+
$code = preg_replace_callback(
161+
'#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#',
162+
static fn (array $m): string => "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>',
163+
$code
164+
);
165+
$lines = explode('<br />', $code);
152166
}
153167

154-
return null;
168+
if (0 > $srcContext) {
169+
$srcContext = \count($lines);
170+
}
171+
172+
return $this->formatFileExcerpt(
173+
array_map(
174+
static fn (string $line): string => self::fixCodeMarkup($line),
175+
$this->extractExcerptLines($lines, $line, $srcContext),
176+
),
177+
$line,
178+
$srcContext
179+
);
180+
}
181+
182+
private function extractExcerptLines(array $lines, int $selectedLine, int $srcContext): array
183+
{
184+
return \array_slice(
185+
$lines,
186+
max($selectedLine - $srcContext, 0),
187+
min($srcContext * 2 + 1, \count($lines) - $selectedLine + $srcContext),
188+
true
189+
);
190+
}
191+
192+
private function formatFileExcerpt(array $lines, int $selectedLine, int $srcContext): string
193+
{
194+
$start = max($selectedLine - $srcContext, 1);
195+
196+
return "<ol start=\"{$start}\">".implode("\n", array_map(
197+
static fn (string $line, int $num): string => '<li'.(++$num === $selectedLine ? ' class="selected"' : '')."><a class=\"anchor\" id=\"line{$num}\"></a><code>{$line}</code></li>",
198+
$lines,
199+
array_keys($lines),
200+
)).'</ol>';
155201
}
156202

157203
/**
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
"Hello",
3+
"World!"
4+
]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
echo 'Hello';
4+
echo 'World!';

src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/CodeExtensionTest.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,92 @@ public function testFormatFileIntegration()
129129
$this->assertEquals($expected, $this->render($template));
130130
}
131131

132+
/**
133+
* @dataProvider fileExcerptIntegrationProvider
134+
*/
135+
public function testFileExcerptIntegration(string $expected, array $data): void
136+
{
137+
$template = <<<'TWIG'
138+
{{ file_path|file_excerpt(line, src_context) }}
139+
TWIG;
140+
141+
$this->assertEquals($expected, $this->render($template, $data));
142+
}
143+
144+
public static function fileExcerptIntegrationProvider(): \Generator
145+
{
146+
$fixturesPath = realpath(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'Fixtures');
147+
148+
yield 'file_except: php file' => [
149+
'expected' => <<<'HTML'
150+
<ol start="1"><li><a class="anchor" id="line1"></a><code><span style="color: #0000BB">&lt;?php</span></span></code></li>
151+
<li><a class="anchor" id="line2"></a><code><span style="color: #0000BB"></span></span></code></li>
152+
<li><a class="anchor" id="line3"></a><code><span style="color: #0000BB"></span><span style="color: #007700">echo </span><span style="color: #DD0000">'Hello'</span><span style="color: #007700">;</span></span></code></li>
153+
<li><a class="anchor" id="line4"></a><code><span style="color: #007700">echo </span><span style="color: #DD0000">'World!'</span><span style="color: #007700">;</span></span></code></li>
154+
<li><a class="anchor" id="line5"></a><code><span style="color: #007700"></span></span></code></li></ol>
155+
HTML,
156+
'data' => [
157+
'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php',
158+
'line' => 0,
159+
'src_context' => 3,
160+
],
161+
];
162+
163+
yield 'file_except: php file with selected line and no source context' => [
164+
'expected' => <<<'HTML'
165+
<ol start="1"><li class="selected"><a class="anchor" id="line1"></a><code><span style="color: #0000BB">&lt;?php</span></span></code></li>
166+
<li><a class="anchor" id="line2"></a><code><span style="color: #0000BB"></span></span></code></li>
167+
<li><a class="anchor" id="line3"></a><code><span style="color: #0000BB"></span><span style="color: #007700">echo </span><span style="color: #DD0000">'Hello'</span><span style="color: #007700">;</span></span></code></li>
168+
<li><a class="anchor" id="line4"></a><code><span style="color: #007700">echo </span><span style="color: #DD0000">'World!'</span><span style="color: #007700">;</span></span></code></li>
169+
<li><a class="anchor" id="line5"></a><code><span style="color: #007700"></span></span></code></li></ol>
170+
HTML,
171+
'data' => [
172+
'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php',
173+
'line' => 1,
174+
'src_context' => -1,
175+
],
176+
];
177+
178+
yield 'file_except: php file excerpt with selected line and custom source context' => [
179+
'expected' => <<<'HTML'
180+
<ol start="2"><li class="selected"><a class="anchor" id="line3"></a><code><span style="color: #0000BB"></span><span style="color: #007700">echo </span><span style="color: #DD0000">'Hello'</span><span style="color: #007700">;</span></span></code></li>
181+
<li><a class="anchor" id="line4"></a><code><span style="color: #007700">echo </span><span style="color: #DD0000">'World!'</span><span style="color: #007700">;</span></span></code></li>
182+
<li><a class="anchor" id="line5"></a><code><span style="color: #007700"></span></span></code></li></ol>
183+
HTML,
184+
'data' => [
185+
'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php',
186+
'line' => 3,
187+
'src_context' => 1,
188+
],
189+
];
190+
191+
yield 'file_except: php file excerpt with out of bound selected line' => [
192+
'expected' => <<<'HTML'
193+
<ol start="99"></ol>
194+
HTML,
195+
'data' => [
196+
'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php',
197+
'line' => 100,
198+
'src_context' => 1,
199+
],
200+
];
201+
202+
yield 'file_except: json file' => [
203+
'expected' => <<<'HTML'
204+
<ol start="1"><li><a class="anchor" id="line1"></a><code>[</code></li>
205+
<li><a class="anchor" id="line2"></a><code> "Hello",</code></li>
206+
<li><a class="anchor" id="line3"></a><code> "World!"</code></li>
207+
<li><a class="anchor" id="line4"></a><code>]</code></li>
208+
<li><a class="anchor" id="line5"></a><code></code></li></ol>
209+
HTML,
210+
'data' => [
211+
'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.json',
212+
'line' => 0,
213+
'src_context' => 3,
214+
],
215+
];
216+
}
217+
132218
public function testFormatFileFromTextIntegration()
133219
{
134220
$template = <<<'TWIG'

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