From d2de3b6de31e2b64060d0f5bd322565d275209de Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 31 Aug 2016 10:43:03 +0200 Subject: [PATCH] [FrameworkBundle] Add %kernel.file_link_format% with remapping for IDE links --- .../Bridge/Twig/Extension/CodeExtension.php | 26 +++++++++--- .../Tests/Extension/CodeExtensionTest.php | 4 +- .../Compiler/DumpDataCollectorPass.php | 4 -- .../DependencyInjection/DebugExtension.php | 6 +++ .../DebugBundle/Resources/config/services.xml | 14 ++++++- .../Compiler/DumpDataCollectorPassTest.php | 14 ------- .../FrameworkExtension.php | 36 ++++++++--------- .../Resources/config/debug_prod.xml | 2 +- .../Resources/config/templating_php.xml | 2 +- .../Templating/Helper/CodeHelper.php | 24 ++++++++--- .../FrameworkExtensionTest.php | 2 +- .../Compiler/ExtensionPass.php | 4 -- .../TwigBundle/Resources/config/twig.xml | 2 +- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- .../Resources/config/profiler.xml | 12 ++++++ .../WebProfilerExtensionTest.php | 2 + .../Bundle/WebProfilerBundle/composer.json | 3 +- .../Component/Debug/ExceptionHandler.php | 40 ++++++++++++++----- .../DataCollector/DumpDataCollector.php | 20 +++++++++- .../EventListener/DebugHandlersListener.php | 4 +- .../Component/VarDumper/Dumper/HtmlDumper.php | 31 +++++++------- 21 files changed, 164 insertions(+), 90 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 86313d02e7988..6eb5a08347637 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -25,13 +25,20 @@ class CodeExtension extends \Twig_Extension /** * Constructor. * - * @param string $fileLinkFormat The format for links to source files - * @param string $rootDir The project root directory - * @param string $charset The charset + * @param string|array $fileLinkFormat The format for links to source files + * @param string $rootDir The project root directory + * @param string $charset The charset */ public function __construct($fileLinkFormat, $rootDir, $charset) { - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + if ($fileLinkFormat && !is_array($fileLinkFormat)) { + $i = max(strpos($fileLinkFormat, '%f'), strpos($fileLinkFormat, '%l')); + $i = strpos($fileLinkFormat, '#', $i) ?: strlen($fileLinkFormat); + $fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1)); + parse_str($fileLinkFormat[1], $fileLinkFormat[1]); + } + $this->fileLinkFormat = $fileLinkFormat; $this->rootDir = str_replace('/', DIRECTORY_SEPARATOR, dirname($rootDir)).DIRECTORY_SEPARATOR; $this->charset = $charset; } @@ -190,8 +197,15 @@ public function formatFile($file, $line, $text = null) */ public function getFileLink($file, $line) { - if ($this->fileLinkFormat && is_file($file)) { - return strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line)); + if ($this->fileLinkFormat && file_exists($file)) { + foreach ($this->fileLinkFormat[1] as $k => $v) { + if (0 === strpos($file, $k)) { + $file = substr_replace($file, $v, 0, strlen($k)); + break; + } + } + + return strtr($this->fileLinkFormat[0], array('%f' => $file, '%l' => $line)); } return false; diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php index 5e4a9a307982d..e72ee4578b6e7 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php @@ -19,7 +19,7 @@ class CodeExtensionTest extends \PHPUnit_Framework_TestCase public function testFormatFile() { - $expected = sprintf('%s at line 25', __FILE__, __FILE__); + $expected = sprintf('%s at line 25', substr(__FILE__, 5), __FILE__); $this->assertEquals($expected, $this->getExtension()->formatFile(__FILE__, 25)); } @@ -64,6 +64,6 @@ public function testGetName() protected function getExtension() { - return new CodeExtension('txmt://open?url=file://%f&line=%l', '/root', 'UTF-8'); + return new CodeExtension('proto://%f#&line=%l#'.substr(__FILE__, 0, 5).'=foobar', '/root', 'UTF-8'); } } diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Compiler/DumpDataCollectorPass.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Compiler/DumpDataCollectorPass.php index 4dcb3908e9997..2579bf64eab13 100644 --- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Compiler/DumpDataCollectorPass.php +++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Compiler/DumpDataCollectorPass.php @@ -33,10 +33,6 @@ public function process(ContainerBuilder $container) $definition = $container->getDefinition('data_collector.dump'); - if ($container->hasParameter('templating.helper.code.file_link_format')) { - $definition->replaceArgument(1, $container->getParameter('templating.helper.code.file_link_format')); - } - if (!$container->hasParameter('web_profiler.debug_toolbar.mode') || WebDebugToolbarListener::DISABLED === $container->getParameter('web_profiler.debug_toolbar.mode')) { $definition->replaceArgument(3, null); } diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php index ce6d1b7c677e4..8e86942caa366 100644 --- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php +++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\VarDumper\Dumper\AbstractDumper; /** * DebugExtension. @@ -47,6 +48,11 @@ public function load(array $configs, ContainerBuilder $container) ->replaceArgument(4, new Reference('var_dumper.cli_dumper')) ; } + + if (defined(AbstractDumper::class.'::DUMP_LIGHT_ARRAY')) { + $container->getDefinition('var_dumper.cli_dumper')->replaceArgument(2, AbstractDumper::DUMP_LIGHT_ARRAY); + $container->getDefinition('var_dumper.html_dumper')->replaceArgument(2, AbstractDumper::DUMP_LIGHT_ARRAY); + } } /** diff --git a/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml b/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml index 38635b815a77e..2b80ee4b1feaf 100644 --- a/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml @@ -8,12 +8,13 @@ + - null + %kernel.file_link_format% %kernel.charset% null @@ -29,6 +30,17 @@ null %kernel.charset% + 0 + + + null + %kernel.charset% + 0 + + + %kernel.file_link_format% + + diff --git a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php index 6500a85a84302..4500fac7215b2 100644 --- a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php +++ b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php @@ -19,20 +19,6 @@ class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase { - public function testProcessWithFileLinkFormatParameter() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new DumpDataCollectorPass()); - $container->setParameter('templating.helper.code.file_link_format', 'file-link-format'); - - $definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, null)); - $container->setDefinition('data_collector.dump', $definition); - - $container->compile(); - - $this->assertSame('file-link-format', $definition->getArgument(1)); - } - public function testProcessWithoutFileLinkFormatParameter() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index be514be0820bd..45e522f47080f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -90,6 +90,21 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']); $container->setParameter('kernel.default_locale', $config['default_locale']); + if (!$container->hasParameter('kernel.file_link_format')) { + if (!$container->hasParameter('templating.helper.code.file_link_format')) { + $links = array( + 'textmate' => 'txmt://open?url=file://%%f&line=%%l', + 'macvim' => 'mvim://open?url=file://%%f&line=%%l', + 'emacs' => 'emacs://open?url=file://%%f&line=%%l', + 'sublime' => 'subl://open?url=file://%%f&line=%%l', + ); + $ide = $config['ide']; + + $container->setParameter('templating.helper.code.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide)); + } + $container->setParameter('kernel.file_link_format', '%templating.helper.code.file_link_format%'); + } + if (!empty($config['test'])) { $loader->load('test.xml'); } @@ -120,7 +135,7 @@ public function load(array $configs, ContainerBuilder $container) } if ($this->isConfigEnabled($container, $config['templating'])) { - $this->registerTemplatingConfiguration($config['templating'], $config['ide'], $container, $loader); + $this->registerTemplatingConfiguration($config['templating'], $container, $loader); } $this->registerValidationConfiguration($config['validation'], $container, $loader); @@ -431,11 +446,6 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con } $definition->replaceArgument(4, $debug); - - if ($container->hasParameter('templating.helper.code.file_link_format')) { - $definition->replaceArgument(5, '%templating.helper.code.file_link_format%'); - } - $definition->replaceArgument(6, $debug); } @@ -553,25 +563,13 @@ private function registerRequestConfiguration(array $config, ContainerBuilder $c * Loads the templating configuration. * * @param array $config A templating configuration array - * @param string $ide * @param ContainerBuilder $container A ContainerBuilder instance * @param XmlFileLoader $loader An XmlFileLoader instance */ - private function registerTemplatingConfiguration(array $config, $ide, ContainerBuilder $container, XmlFileLoader $loader) + private function registerTemplatingConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { $loader->load('templating.xml'); - if (!$container->hasParameter('templating.helper.code.file_link_format')) { - $links = array( - 'textmate' => 'txmt://open?url=file://%%f&line=%%l', - 'macvim' => 'mvim://open?url=file://%%f&line=%%l', - 'emacs' => 'emacs://open?url=file://%%f&line=%%l', - 'sublime' => 'subl://open?url=file://%%f&line=%%l', - ); - - $container->setParameter('templating.helper.code.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide)); - } - $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']); if ($container->getParameter('kernel.debug')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml index d4eb5b1762577..20421ba8711dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml @@ -17,7 +17,7 @@ -1 %debug.error_handler.throw_at% true - null + %kernel.file_link_format% true diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml index ba77ba93cbcb7..89bfbdc6db6db 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml @@ -44,7 +44,7 @@ - %templating.helper.code.file_link_format% + %kernel.file_link_format% %kernel.root_dir% %kernel.charset% diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 080103d5baef5..7e444abb62a13 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -27,13 +27,20 @@ class CodeHelper extends Helper /** * Constructor. * - * @param string $fileLinkFormat The format for links to source files - * @param string $rootDir The project root directory - * @param string $charset The charset + * @param string|array $fileLinkFormat The format for links to source files + * @param string $rootDir The project root directory + * @param string $charset The charset */ public function __construct($fileLinkFormat, $rootDir, $charset) { - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + if ($fileLinkFormat && !is_array($fileLinkFormat)) { + $i = max(strpos($fileLinkFormat, '%f'), strpos($fileLinkFormat, '%l')); + $i = strpos($fileLinkFormat, '#', $i) ?: strlen($fileLinkFormat); + $fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1)); + parse_str($fileLinkFormat[1], $fileLinkFormat[1]); + } + $this->fileLinkFormat = $fileLinkFormat; $this->rootDir = str_replace('\\', '/', $rootDir).'/'; $this->charset = $charset; } @@ -186,7 +193,14 @@ public function formatFile($file, $line, $text = null) public function getFileLink($file, $line) { if ($this->fileLinkFormat && is_file($file)) { - return strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line)); + foreach ($this->fileLinkFormat[1] as $k => $v) { + if (0 === strpos($file, $k)) { + $file = substr_replace($file, $v, 0, strlen($k)); + break; + } + } + + return strtr($this->fileLinkFormat[0], array('%f' => $file, '%l' => $line)); } return false; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index cbf60967e0f1d..696b3d398d117 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -359,7 +359,7 @@ public function testFileLinkFormat() { $container = $this->createContainerFromFile('full'); - $this->assertEquals('file%link%format', $container->getParameter('templating.helper.code.file_link_format')); + $this->assertEquals('file%link%format', $container->getParameter('kernel.file_link_format')); } public function testValidationAnnotations() diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 2aaf085a8809e..2dc0803d0ee36 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -55,10 +55,6 @@ public function process(ContainerBuilder $container) $container->getDefinition('twig.extension.httpfoundation')->addTag('twig.extension'); } - if ($container->hasParameter('templating.helper.code.file_link_format')) { - $container->getDefinition('twig.extension.code')->replaceArgument(0, $container->getParameter('templating.helper.code.file_link_format')); - } - if ($container->getParameter('kernel.debug')) { $container->getDefinition('twig.extension.profiler')->addTag('twig.extension'); $container->getDefinition('twig.extension.debug')->addTag('twig.extension'); diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index 55182c083abd5..b54b02a286b23 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -83,7 +83,7 @@ - + %kernel.file_link_format% %kernel.root_dir% %kernel.charset% diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index d17dbb4ec70f0..6e10104f5b2b1 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -31,7 +31,7 @@ "symfony/routing": "~2.8|~3.0", "symfony/templating": "~2.8|~3.0", "symfony/yaml": "~2.8|~3.0", - "symfony/framework-bundle": "~2.8|~3.0" + "symfony/framework-bundle": "~3.2" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml index 16d065aa7c02f..41e25ad6dfd78 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml @@ -34,6 +34,18 @@ + + + null + %kernel.charset% + Symfony\Component\VarDumper\Dumper\HtmlDumper::DUMP_LIGHT_ARRAY + + + %kernel.file_link_format% + + + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index f4424d0cc7d5c..d73ef751a6774 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -56,6 +56,8 @@ protected function setUp() $this->container->setParameter('kernel.cache_dir', __DIR__); $this->container->setParameter('kernel.debug', false); $this->container->setParameter('kernel.root_dir', __DIR__); + $this->container->setParameter('kernel.charset', 'UTF-8'); + $this->container->setParameter('kernel.file_link_format', null); $this->container->setParameter('profiler.class', array('Symfony\\Component\\HttpKernel\\Profiler\\Profiler')); $this->container->register('profiler', $this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\Profiler')) ->addArgument(new Definition($this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface'))); diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 20babd8c46fc9..07a877d8bff3d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -20,7 +20,8 @@ "symfony/http-kernel": "~3.1", "symfony/polyfill-php70": "~1.0", "symfony/routing": "~2.8|~3.0", - "symfony/twig-bridge": "~2.8|~3.0" + "symfony/twig-bridge": "~2.8|~3.0", + "symfony/var-dumper": "~3.2" }, "require-dev": { "symfony/config": "~2.8|~3.0", diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 6d05b4421918b..3c68bfbf79c68 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -37,9 +37,16 @@ class ExceptionHandler public function __construct($debug = true, $charset = null, $fileLinkFormat = null) { + $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + if ($fileLinkFormat && !is_array($fileLinkFormat)) { + $i = max(strpos($fileLinkFormat, '%f'), strpos($fileLinkFormat, '%l')); + $i = strpos($fileLinkFormat, '#', $i) ?: strlen($fileLinkFormat); + $fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1)); + parse_str($fileLinkFormat[1], $fileLinkFormat[1]); + } $this->debug = $debug; $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat; } /** @@ -82,14 +89,22 @@ public function setHandler(callable $handler = null) /** * Sets the format for links to source files. * - * @param string $format The format for links to source files + * @param string|array $format The format for links to source files * * @return string The previous file link format */ - public function setFileLinkFormat($format) + public function setFileLinkFormat($fileLinkFormat) { $old = $this->fileLinkFormat; - $this->fileLinkFormat = $format; + if ($fileLinkFormat && !is_array($fileLinkFormat)) { + $i = strpos($fileLinkFormat, '#') ?: strlen($fileLinkFormat); + $fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1)); + parse_str($fileLinkFormat[1], $fileLinkFormat[1]); + } + $this->fileLinkFormat = $fileLinkFormat; + if ($old) { + $old = $old[0].($old[1] ? '#'.http_build_query($old[1], '', '&') : ''); + } return $old; } @@ -350,16 +365,21 @@ private function formatClass($class) private function formatPath($path, $line) { - $path = $this->escapeHtml($path); - $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path; + $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path); - if ($linkFormat = $this->fileLinkFormat) { - $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line)); + if ($fileLinkFormat = $this->fileLinkFormat) { + foreach ($fileLinkFormat[1] as $k => $v) { + if (0 === strpos($path, $k)) { + $path = substr_replace($path, $v, 0, strlen($k)); + break; + } + } + $link = strtr($fileLinkFormat[0], array('%f' => $path, '%l' => (int) $line)); - return sprintf(' in %s line %d', $link, $file, $line); + return sprintf(' in %s line %d', $this->escapeHtml($link), $file, $line); } - return sprintf(' in %s line %d', $path, $file, $line); + return sprintf(' in %s line %d', $this->escapeHtml($path), $file, $line); } /** diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index 9e39e7493dab0..d2a89b0eaaa4b 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -40,8 +40,15 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null, DataDumperInterface $dumper = null) { + $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + if ($fileLinkFormat && !is_array($fileLinkFormat)) { + $i = max(strpos($fileLinkFormat, '%f'), strpos($fileLinkFormat, '%l')); + $i = strpos($fileLinkFormat, '#', $i) ?: strlen($fileLinkFormat); + $fileLinkFormat = array(substr($fileLinkFormat, 0, $i), substr($fileLinkFormat, $i + 1)); + parse_str($fileLinkFormat[1], $fileLinkFormat[1]); + } $this->stopwatch = $stopwatch; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat; $this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'; $this->requestStack = $requestStack; $this->dumper = $dumper; @@ -149,6 +156,7 @@ public function collect(Request $request, Response $response, \Exception $except ) { if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) { $this->dumper = new HtmlDumper('php://output', $this->charset); + $this->dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat)); } else { $this->dumper = new CliDumper('php://output', $this->charset); } @@ -198,6 +206,7 @@ public function getDumps($format, $maxDepthLimit = -1, $maxItemsPerDepth = -1) if ('html' === $format) { $dumper = new HtmlDumper($data, $this->charset); + $dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat)); } else { throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format)); } @@ -234,6 +243,7 @@ public function __destruct() if ('cli' !== PHP_SAPI && stripos($h[$i], 'html')) { $this->dumper = new HtmlDumper('php://output', $this->charset); + $dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat)); } else { $this->dumper = new CliDumper('php://output', $this->charset); } @@ -258,7 +268,13 @@ private function doDump($data, $name, $file, $line) $name = strip_tags($this->style('', $name)); $file = strip_tags($this->style('', $file)); if ($fileLinkFormat) { - $link = strtr(strip_tags($this->style('', $fileLinkFormat)), array('%f' => $file, '%l' => (int) $line)); + foreach ($fileLinkFormat[1] as $k => $v) { + if (0 === strpos($file, $k)) { + $file = substr_replace($file, $v, 0, strlen($k)); + break; + } + } + $link = strtr(strip_tags($this->style('', $fileLinkFormat[0])), array('%f' => $file, '%l' => (int) $line)); $name = sprintf(''.$s.'', $link, $file, $name); } else { $name = sprintf(''.$s.'', $file, $name); diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index b3415d8784f48..b4763d7e016c0 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -44,7 +44,7 @@ class DebugHandlersListener implements EventSubscriberInterface * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged - * @param string $fileLinkFormat The format for links to source files + * @param string|array $fileLinkFormat The format for links to source files * @param bool $scope Enables/disables scoping mode */ public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, $throwAt = E_ALL, $scream = true, $fileLinkFormat = null, $scope = true) @@ -54,7 +54,7 @@ public function __construct(callable $exceptionHandler = null, LoggerInterface $ $this->levels = null === $levels ? E_ALL : $levels; $this->throwAt = is_numeric($throwAt) ? (int) $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null)); $this->scream = (bool) $scream; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat; $this->scope = (bool) $scope; } diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index c43b208986e29..6b73e98c91304 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -190,7 +190,7 @@ function toggle(a, recursive) { options = {$options}, elt = root.getElementsByTagName('A'), len = elt.length, - i = 0, s, h, + i = 0, s, h, fmt, t = []; while (i < len) t.push(elt[i++]); @@ -198,6 +198,10 @@ function toggle(a, recursive) { for (i in x) { options[i] = x[i]; } + fmt = options.fileLinkFormat; + if (fmt && 'string' == typeof fmt) { + fmt = [fmt]; + } function a(e, f) { addEventListener(root, e, function (e) { @@ -218,20 +222,6 @@ function isCtrlKey(e) { refStyle.innerHTML = ''; } }); - if (options.fileLinkFormat) { - addEventListener(root, 'click', function (e) { - e = e.target; - while (root != e && 'CODE' != e.tagName) { - e = e.parentNode; - } - if ('CODE' == e.tagName) { - var f = e.getAttribute('data-file'), l = e.getAttribute('data-line'); - if (f && l) { - location.href = options.fileLinkFormat.replace('%f', f).replace('%l', l); - } - } - }); - } a('mouseover', function (a) { if (a = idRx.exec(a.className)) { try { @@ -332,6 +322,16 @@ function isCtrlKey(e) { } } } + } else if (fmt && (a = elt.getAttribute('data-file'))) { + if (fmt[1]) { + for (x in fmt[1]) { + if (0 === a.indexOf(x)) { + a = fmt[1][x] + a.substr(x.length); + break; + } + } + } + elt.href = fmt[0].replace('%l', elt.getAttribute('data-line')).replace('%f', a); } } @@ -387,6 +387,7 @@ function isCtrlKey(e) { cursor: pointer; border: 0; outline: none; + color: inherit; } pre.sf-dump .sf-dump-ellipsis { display: inline-block;