8000 Added a default ide file link web view · symfony/symfony@41fc036 · GitHub
[go: up one dir, main page]

Skip to content

Commit 41fc036

Browse files
Added a default ide file link web view
1 parent 9362b8c commit 41fc036

File tree

19 files changed

+343
-119
lines changed

19 files changed

+343
-119
lines changed

src/Symfony/Bridge/Twig/Extension/CodeExtension.php

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Bridge\Twig\Extension;
1313

14+
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
15+
1416
/**
1517
* Twig extension relate to PHP code and used by the profiler and the default exception templates.
1618
*
@@ -25,20 +27,13 @@ class CodeExtension extends \Twig_Extension
2527
/**
2628
* Constructor.
2729
*
28-
* @param string|array $fileLinkFormat The format for links to source files
29-
* @param string $rootDir The project root directory
30-
* @param string $charset The charset
30+
* @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
31+
* @param string $rootDir The project root directory
32+
* @param string $charset The charset
3133
*/
3234
public function __construct($fileLinkFormat, $rootDir, $charset)
3335
{
34-
$fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
35-
if ($fileLinkFormat && !is_array($fileLinkFormat)) {
36-
$i = max(strpos($fileLinkFormat, '%f'), strpos($fileLinkFormat, '%l'));
37-
$i = strpos($fileLinkFormat, '#"', $i) ?: strlen($fileLinkFormat);
38-
$fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1));
39-
$fileLinkFormat[1] = @json_decode('{'.$fileLinkFormat[1].'}', true) ?: array();
40-
}
41-
$this->fileLinkFormat = $fileLinkFormat;
36+
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4237
$this->rootDir = str_replace('/', DIRECTORY_SEPARATOR, dirname($rootDir)).DIRECTORY_SEPARATOR;
4338
$this->charset = $charset;
4439
}
@@ -130,27 +125,36 @@ public function formatArgsAsText($args)
130125
/**
131126
* Returns an excerpt of a code file around the given line number.
132127
*
133-
* @param string $file A file path
134-
* @param int $line The selected line number
< 10000 /td>128+
* @param string $file A file path
129+
* @param int $line The selected line number
130+
* @param int $srcContext The number of displayed lines around or -1 for the whole file
135131
*
136132
* @return string An HTML string
137133
*/
138-
public function fileExcerpt($file, $line)
134+
public function fileExcerpt($file, $line, $srcContext = 3)
139135
{
140136
if (is_readable($file)) {
141137
// highlight_file could throw warnings
142138
// see https://bugs.php.net/bug.php?id=25725
143139
$code = @highlight_file($file, true);
144140
// remove main code/span tags
145141
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
146-
$content = preg_split('#<br />#', $code);
142+
// split multiline spans
143+
$code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) {
144+
return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>';
145+
}, $code);
146+
$code = explode('<br />', $code);
147147

148148
$lines = array();
149-
for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; ++$i) {
150-
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
149+
if (0 > $srcContext) {
150+
$srcContext = count($code);
151+
}
152+
153+
for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, count($code)); $i <= $max; ++$i) {
154+
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><div class="anchor" id="line'.$i.'"></div><code>'.self::fixCodeMarkup($code[$i - 1]).'</code></li>';
151155
}
152156

153-
return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
157+
return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
154158
}
155159
}
156160

@@ -197,15 +201,8 @@ public function formatFile($file, $line, $text = null)
197201
*/
198202
public function getFileLink($file, $line)
199203
{
200-
if ($this->fileLinkFormat && file_exists($file)) {
201-
foreach ($this->fileLinkFormat[1] as $k => $v) {
202-
if (0 === strpos($file, $k)) {
203-
$file = substr_replace($file, $v, 0, strlen($k));
204-
break;
205-
}
206-
}
207-
208-
return strtr($this->fileLinkFormat[0], array('%f' => $file, '%l' => $line));
204+
if ($fmt = $this->fileLinkFormat) {
205+
return is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line);
209206
}
210207

211208
return false;

src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Twig\Tests\Extension;
1313

1414
use Symfony\Bridge\Twig\Extension\CodeExtension;
15+
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
1516

1617
class CodeExtensionTest extends \PHPUnit_Framework_TestCase
1718
{
@@ -64,6 +65,6 @@ public function testGetName()
6465

6566
protected function getExtension()
6667
{
67-
return new CodeExtension('proto://%f#&line=%l#'.json_encode(substr(__FILE__, 0, 5)).':"foobar"', '/root', 'UTF-8');
68+
return new CodeExtension(new FileLinkFormatter('proto://%f#&line=%l#'.json_encode(substr(__FILE__, 0, 5)).':"foobar"'), '/root', 'UTF-8');
6869
}
6970
}

src/Symfony/Bridge/Twig/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"symfony/asset": "~2.8|~3.0",
2424
"symfony/finder": "~2.8|~3.0",
2525
"symfony/form": "~3.0.4",
26-
"symfony/http-kernel": "~2.8|~3.0",
26+
"symfony/http-kernel": "~3.2",
2727
"symfony/polyfill-intl-icu": "~1.0",
2828
"symfony/routing": "~2.8|~3.0",
2929
"symfony/templating": "~2.8|~3.0",

src/Symfony/Bundle/DebugBundle/Resources/config/services.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<service id="data_collector.dump" class="Symfony\Component\HttpKernel\DataCollector\DumpDataCollector">
1515
<tag name="data_collector" id="dump" template="@Debug/Profiler/dump.html.twig" priority="240" />
1616
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
17-
<argument>%debug.file_link_format%</argument>
17+
<argument type="service">debug.file_link_formatter</argument>
1818
<argument>%kernel.charset%</argument>
1919
<argument type="service" id="request_stack" />
2020
<argument>null</argument><!-- var_dumper.cli_dumper when debug.dump_destination is set -->
@@ -38,10 +38,11 @@
3838
<argument>0</argument> <!-- flags -->
3939
<call method="setDisplayOptions">
4040
<argument type="collection">
41-
<argument key="fileLinkFormat">%debug.file_link_format%</argument>
41+
<argument key="fileLinkFormat" type="service">debug.file_link_formatter</argument>
4242
</argument>
4343
</call>
4444
</service>
45+
4546
</services>
4647

4748
</container>

src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
<argument>-1</argument><!-- Log levels map for enabled error levels -->
1818
<argument>%debug.error_handler.throw_at%</argument>
1919
<argument>true</argument>
20-
<argument>%debug.file_link_format%</argument>
20+
<argument type="service">debug.file_link_formatter</argument>
2121
<argument>true</argument>
2222
</service>
2323

2424
<service id="debug.stopwatch" class="Symfony\Component\Stopwatch\Stopwatch" />
25+
26+
<service id="debug.file_link_formatter" class="Symfony\Component\HttpKernel\Debug\FileLinkFormatter" public="false">
27+
<argument>%debug.file_link_format%</argument>
28+
</service>
2529
</services>
2630
</container>

src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
<service id="templating.helper.code" class="Symfony\Bundle\FrameworkBundle\Templating\Helper\CodeHelper">
4646
<tag name="templating.helper" alias="code" />
47-
<argument>%debug.file_link_format%</argument>
47+
<argument type="service">debug.file_link_formatter</argument>
4848
<argument>%kernel.root_dir%</argument>
4949
<argument>%kernel.charset%</argument>
5050
</service>

src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
1313

14+
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
1415
use Symfony\Component\Templating\Helper\Helper;
1516

1617
/**
@@ -27,20 +28,13 @@ class CodeHelper extends Helper
2728
/**
2829
* Constructor.
2930
*
30-
* @param string|array $fileLinkFormat The format for links to source files
31-
* @param string $rootDir The project root directory
32-
* @param string $charset The charset
31+
* @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
32+
* @param string $rootDir The project root directory
33+
* @param string $charset The charset
3334
*/
3435
public function __construct($fileLinkFormat, $rootDir, $charset)
3536
{
36-
$fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
37-
if ($fileLinkFormat && !is_array($fileLinkFormat)) {
38-
$i = max(strpos($fileLinkFormat, '%f'), strpos($fileLinkFormat, '%l'));
39-
$i = strpos($fileLinkFormat, '#"', $i) ?: strlen($fileLinkFormat);
40-
$fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1));
41-
$fileLinkFormat[1] = @json_decode('{'.$fileLinkFormat[1].'}', true) ?: array();
42-
}
43-
$this->fileLinkFormat = $fileLinkFormat;
37+
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4438
$this->rootDir = str_replace('\\', '/', $rootDir).'/';
4539
$this->charset = $charset;
4640
}
@@ -192,15 +186,8 @@ public function formatFile($file, $line, $text = null)
192186
*/
193187
public function getFileLink($file, $line)
194188
{
195-
if ($this->fileLinkFormat && is_file($file)) {
196-
foreach ($this->fileLinkFormat[1] as $k => $v) {
197-
if (0 === strpos($file, $k)) {
198-
$file = substr_replace($file, $v, 0, strlen($k));
199-
break;
200-
}
201-
}
202-
203-
return strtr($this->fileLinkFormat[0], array('%f' => $file, '%l' => $line));
189+
if ($fmt = $this->fileLinkFormat) {
190+
return is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line);
204191
}
205192

206193
return false;

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"php": ">=5.5.9",
2020
"symfony/cache": "~3.2",
2121
"symfony/class-loader": "~3.2",
22+
"symfony/debug": "~3.2",
2223
"symfony/dependency-injection": "~3.2",
2324
"symfony/config": "~2.8|~3.0",
2425
"symfony/event-dispatcher": "~2.8|~3.0",

src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686

8787
<service id="twig.extension.code" class="Symfony\Bridge\Twig\Extension\CodeExtension" public="false">
8888
<tag name="twig.extension" />
89-
<argument>%debug.file_link_format%</argument>
89+
<argument type="service">debug.file_link_formatter</argument>
9090
<argument>%kernel.root_dir%</argument>
9191
<argument>%kernel.charset%</argument>
9292
</service>

src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ProfilerController
3535
private $templates;
3636
private $toolbarPosition;
3737
private $cspHandler;
38+
private $kernelRootDir;
3839

3940
/**
4041
* Constructor.
@@ -44,15 +45,17 @@ class ProfilerController
4445
* @param \Twig_Environment $twig The twig environment
4546
* @param array $templates The templates
4647
* @param string $toolbarPosition The toolbar position (top, bottom, normal, or null -- use the configuration)
48+
* @param string $kernelRootDir The Kernel root directory
4749
*/
48-
public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'normal', ContentSecurityPolicyHandler $cspHandler = null)
50+
public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'normal', ContentSecurityPolicyHandler $cspHandler = null, $kernelRootDir = null)
4951
{
5052
$this->generator = $generator;
5153
$this->profiler = $profiler;
5254
$this->twig = $twig;
5355
$this->templates = $templates;
5456
$this->toolbarPosition = $toolbarPosition;
5557
$this->cspHandler = $cspHandler;
58+
$this->kernelRootDir = $kernelRootDir;
5659
}
5760

5861
/**
@@ -394,6 +397,40 @@ public function phpinfoAction()
394397
return new Response($phpinfo, 200, array('Content-Type' => 'text/html'));
395398
}
396399

400+
/**
401+
* Displays the source of a file.
402+
*
403+
* @return Response A Response instance
404+
*
405+
* @throws NotFoundHttpException
406+
*/
407+
public function openAction(Request $request)
408+
{
409+
if (null === $this->kernelRootDir) {
410+
throw new NotFoundHttpException('KernelRootDir should be set.');
411+
}
412+
413+
if (null === $this->profiler) {
414+
throw new NotFoundHttpException('The profiler must be enabled.');
415+
}
416+
$this->profiler->disable();
417+
418+
$file = $request->query->get('file');
419+
$line = $request->query->get('line');
420+
421+
$filename = dirname($this->kernelRootDir).DIRECTORY_SEPARATOR.$file;
422+
423+
if (preg_match("'(^|[/\\\\])\.\.?([/\\\\]|$)'", $file) || !is_readable($filename)) {
424+
throw new NotFoundHttpException(sprintf('The file "%s" cannot be opened.', $file));
425+
}
426+
427+
return new Response($this->twig->render('@WebProfiler/Profiler/open.html.twig', array(
428+
'file' => $file,
429+
'filename' => $filename,
430+
'line' => $line,
431+
)), 200, array('Content-Type' => 'text/html'));
432+
}
433+
397434
/**
398435
* Gets the Template Manager.
399436
*

src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<argument>%data_collector.templates%</argument>
1313
<argument>%web_profiler.debug_toolbar.position%</argument>
1414
<argument type="service" id="web_profiler.csp.handler" />
15+
<argument>%kernel.root_dir%</argument>
1516
</service>
1617

1718
<service id="web_profiler.controller.router" class="Symfony\Bundle\WebProfilerBundle\Controller\RouterController">
@@ -41,11 +42,18 @@
4142
<argument type="constant">Symfony\Component\VarDumper\Dumper\HtmlDumper::DUMP_LIGHT_ARRAY</argument>
4243
<call method="setDisplayOptions">
4344
<argument type="collection">
44-
<argument key="fileLinkFormat">%debug.file_link_format%</argument>
45+
<argument key="fileLinkFormat" type="service">debug.file_link_formatter</argument>
4546
</argument>
4647
</call>
4748
</service>
4849
</argument>
4950
</service>
51+
52+
<service id="debug.file_link_formatter" class="Symfony\Component\HttpKernel\Debug\FileLinkFormatter" public="false">
53+
<argument>%debug.file_link_format%</argument>
54+
<argument type="service" id="request_stack" on-invalid="ignore" />
55+
<argument>%kernel.root_dir%</argument>
56+
<argument>/_profiler/open?file=%%f&amp;line=%%l#line%%l</argument>
57+
</service>
5058
</services>
5159
</container>

src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
<default key="_controller">web_profiler.controller.profiler:searchResultsAction</default>
2929
</route>
3030

31+
<route id="_open" path="/open">
32+
<default key="_controller">web_profiler.controller.profiler:openAction</default>
33+
</route>
34+
3135
<route id="_profiler" path="/{token}">
3236
<default key="_controller">web_profiler.controller.profiler:panelAction</default>
3337
</route>

0 commit comments

Comments
 (0)
0