Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f2768dc

Browse files
committed
feature #19973 Added a default ide file link web view (jeremyFreeAgent)
This PR was merged into the 3.2-dev branch. Discussion ---------- Added a default ide file link web view | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - When having no `framework.ide` configured or `framework.ide = symfony` the file link open the source in a web view (eg `_profiler/open?file=/src/AppBundle/Controller/DefaultController.php&line=50#line50`). ![](https://cl.ly/2Z0W2J020p43/feature_ide.png) Commits ------- ba6bcca Added a default ide file link web view
2 parents fdb7834 + ba6bcca commit f2768dc

File tree

19 files changed

+360
-107
lines changed

19 files changed

+360
-107
lines changed

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

Lines changed: 24 additions & 25 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,18 +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 = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f);
37-
$fileLinkFormat = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
38-
}
39-
$this->fileLinkFormat = $fileLinkFormat;
36+
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4037
$this->rootDir = str_replace('/', DIRECTORY_SEPARATOR, dirname($rootDir)).DIRECTORY_SEPARATOR;
4138
$this->charset = $charset;
4239
}
@@ -128,27 +125,36 @@ public function formatArgsAsText($args)
128125
/**
129126
* Returns an excerpt of a code file around the given line number.
130127
*
131-
* @param string $file A file path
132-
* @param int $line The selected line number
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
133131
*
134132
* @return string An HTML string
135133
*/
136-
public function fileExcerpt($file, $line)
134+
public function fileExcerpt($file, $line, $srcContext = 3)
137135
{
138136
if (is_readable($file)) {
139137
// highlight_file could throw warnings
140138
// see https://bugs.php.net/bug.php?id=25725
141139
$code = @highlight_file($file, true);
142140
// remove main code/span tags
143141
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
144-
$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+
$content = explode('<br />', $code);
145147

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

151-
return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
157+
return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
152158
}
153159
}
154160

@@ -195,15 +201,8 @@ public function formatFile($file, $line, $text = null)
195201
*/
196202
public function getFileLink($file, $line)
197203
{
198-
if ($this->fileLinkFormat && file_exists($file)) {
199-
for ($i = 1; isset($this->fileLinkFormat[$i]); ++$i) {
200-
if (0 === strpos($file, $k = $this->fileLinkFormat[$i++])) {
201-
$file = substr_replace($file, $this->fileLinkFormat[$i], 0, strlen($k));
202-
break;
203-
}
204-
}
205-
206-
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);
207206
}
208207

209208
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&'.substr(__FILE__, 0, 5).'>foobar', '/root', 'UTF-8');
68+
return new CodeExtension(new FileLinkFormatter('proto://%f#&line=%l&'.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: 2 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" id="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,7 +38,7 @@
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" id="debug.file_link_formatter"></argument>
4242
</argument>
4343
</call>
4444
</service>

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" id="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" id="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 & 18 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,18 +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 = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f);
39-
$fileLinkFormat = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
40-
}
41-
$this->fileLinkFormat = $fileLinkFormat;
37+
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4238
$this->rootDir = str_replace('\\', '/', $rootDir).'/';
4339
$this->charset = $charset;
4440
}
@@ -190,15 +186,8 @@ public function formatFile($file, $line, $text = null)
190186
*/
191187
public function getFileLink($file, $line)
192188
{
193-
if ($this->fileLinkFormat && is_file($file)) {
194-
for ($i = 1; isset($this->fileLinkFormat[$i]); ++$i) {
195-
if (0 === strpos($file, $k = $this->fileLinkFormat[$i++])) {
196-
$file = substr_replace($path, $this->fileLinkFormat[$i], 0, strlen($k));
197-
break;
198-
}
199-
}
200-
201-
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);
202191
}
203192

204193
return false;

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

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

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

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

Lines changed: 37 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 $baseDir;
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 $baseDir The project 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, $baseDir = 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->baseDir = $baseDir;
5659
}
5760

5861
/**
@@ -394,6 +397,39 @@ 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->baseDir) {
410+
throw new NotFoundHttpException('The base dir should be set.');
411+
}
412+
413+
if ($this->profiler) {
414+
$this->profiler->disable();
415+
}
416+
417+
$file = $request->query->get('file');
418+
$line = $request->query->get('line');
419+
420+
$filename = $this->baseDir.DIRECTORY_SEPARATOR.$file;
421+
422+
if (preg_match("'(^|[/\\\\])\.\.?([/\\\\]|$)'", $file) || !is_readable($filename)) {
423+
throw new NotFoundHttpException(sprintf('The file "%s" cannot be opened.', $file));
424+
}
425+
426+
return new Response($this->twig->render('@WebProfiler/Profiler/open.html.twig', array(
427+
'filename' => $filename,
428+
'file' => $file,
429+
'line' => $line,
430+
)), 200, array('Content-Type' => 'text/html'));
431+
}
432+
397433
/**
398434
* Gets the Template Manager.
399435
*

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ public function load(array $configs, ContainerBuilder $container)
5252
$container->setParameter('web_profiler.debug_toolbar.intercept_redirects', $config['intercept_redirects']);
5353
$container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED);
5454
}
55+
56+
$baseDir = array();
57+
$rootDir = $container->getParameter('kernel.root_dir');
58+
$rootDir = explode(DIRECTORY_SEPARATOR, realpath($rootDir) ?: $rootDir);
59+
$bundleDir = explode(DIRECTORY_SEPARATOR, __DIR__);
60+
for ($i = 0; isset($rootDir[$i], $bundleDir[$i]); ++$i) {
61+
if ($rootDir[$i] !== $bundleDir[$i]) {
62+
break;
63+
}
64+
$baseDir[] = $rootDir[$i];
65+
}
66+
$baseDir = implode(DIRECTORY_SEPARATOR, $baseDir);
67+
68+
$profilerController = $container->getDefinition('web_profiler.controller.profiler');
69+
$profilerController->replaceArgument(6, $baseDir);
70+
71+
$fileLinkFormatter = $container->getDefinition('debug.file_link_formatter');
72+
$fileLinkFormatter->replaceArgument(2, $baseDir);
5573
}
5674

5775
/**

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>null</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" id="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>null</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="_profiler_open_file" 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)