8000 bug #14478 [DebugBundle] Fix dump() output in API / No-Toolbar contex… · symfony/symfony@c486748 · GitHub
[go: up one dir, main page]

Skip to content

Commit c486748

Browse files
committed
bug #14478 [DebugBundle] Fix dump() output in API / No-Toolbar context (nicolas-grekas)
This PR was merged into the 2.6 branch. Discussion ---------- [DebugBundle] Fix dump() output in API / No-Toolbar context | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - With this PR, dumps are written as plain text when the main content-type is not HTML. With HTML, dumps are inlined when the web debug toolbar is not enabled. Commits ------- 62f8469 [DebugBundle] Fix dump() output in API/No-Toolbar context
2 parents b11ea0a + 62f8469 commit c486748

File tree

6 files changed

+160
-28
lines changed

6 files changed

+160
-28
lines changed

src/Symfony/Bundle/DebugBundle/DependencyInjection/Compiler/DumpDataCollectorPass.php

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

1212
namespace Symfony\Bundle\DebugBundle\DependencyInjection\Compiler;
1313

14+
use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener;
1415
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617

@@ -35,5 +36,9 @@ public function process(ContainerBuilder $container)
3536
if ($container->hasParameter('templating.helper.code.file_link_format')) {
3637
$definition->replaceArgument(1, $container->getParameter('templating.helper.code.file_link_format'));
3738
}
39+
40+
if (!$container->hasParameter('web_profiler.debug_toolbar.mode') || WebDebugToolbarListener::DISABLED === $container->getParameter('web_profiler.debug_toolbar.mode')) {
41+
$definition->replaceArgument(3, null);
42+
}
3843
}
3944
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
1616
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
1717
<argument>%kernel.charset%</argument>
18+
<argument type="service" id="request_stack" />
1819
</service>
1920

2021
<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">

src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
namespace Symfony\Bundle\DebugBundle\Tests\DependencyInjection\Compiler;
1313

1414
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
15+
use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\Definition;
18+
use Symfony\Component\HttpFoundation\RequestStack;
1719

1820
class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
1921
{
@@ -23,7 +25,7 @@ public function testProcessWithFileLinkFormatParameter()
2325
$container->addCompilerPass(new DumpDataCollectorPass());
2426
$container->setParameter('templating.helper.code.file_link_format', 'file-link-format');
2527

26-
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null));
28+
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, null));
2729
$container->setDefinition('data_collector.dump', $definition);
2830

2931
$container->compile();
@@ -36,11 +38,53 @@ public function testProcessWithoutFileLinkFormatParameter()
3638
$container = new ContainerBuilder();
3739
$container->addCompilerPass(new DumpDataCollectorPass());
3840

39-
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null));
41+
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, null));
4042
$container->setDefinition('data_collector.dump', $definition);
4143

4244
$container->compile();
4345

4446
$this->assertNull($definition->getArgument(1));
4547
}
48+
49+
public function testProcessWithToolbarEnabled()
50+
{
51+
$container = new ContainerBuilder();
52+
$container->addCompilerPass(new DumpDataCollectorPass());
53+
$requestStack = new RequestStack();
54+
55+
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, $requestStack));
56+
$container->setDefinition('data_collector.dump', $definition);
57+
$container->setParameter('web_profiler.debug_toolbar.mode', WebDebugToolbarListener::ENABLED);
58+
59+
$container->compile();
60+
61+
$this->assertSame($requestStack, $definition->getArgument(3));
62+
}
63+
64+
public function testProcessWithToolbarDisabled()
65+
{
66+
$container = new ContainerBuilder();
67+
$container->addCompilerPass(new DumpDataCollectorPass());
68+
69+
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, new RequestStack()));
70+
$container->setDefinition('data_collector.dump', $definition);
71+
$container->setParameter('web_profiler.debug_toolbar.mode', WebDebugToolbarListener::DISABLED);
72+
73+
$container->compile();
74+
75+
$this->assertNull($definition->getArgument(3));
76+
}
77+
78+
public function testProcessWithoutToolbar()
79+
{
80+
$container = new ContainerBuilder();
81+
$container->addCompilerPass(new DumpDataCollectorPass());
82+
83+
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, new RequestStack()));
84+
$container->setDefinition('data_collector.dump', $definition);
85+
86+
$container->compile();
87+
88+
$this->assertNull($definition->getArgument(3));
89+
}
4690
}

src/Symfony/Bundle/DebugBundle/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"require-dev": {
2525
"symfony/phpunit-bridge": "~2.7",
2626
"symfony/config": "~2.3",
27-
"symfony/dependency-injection": "~2.3"
27+
"symfony/dependency-injection": "~2.3",
28+
"symfony/web-profiler-bundle": "~2.3"
2829
},
2930
"suggest": {
3031
"symfony/config": "For service container configuration",

src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\HttpKernel\DataCollector;
1313

1414
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\RequestStack;
1516
use Symfony\Component\HttpFoundation\Response;
1617
use Symfony\Component\Stopwatch\Stopwatch;
1718
use Symfony\Component\VarDumper\Cloner\Data;
@@ -33,12 +34,14 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
3334
private $clonesIndex = 0;
3435
private $rootRefs;
3536
private $charset;
37+
private $dumper;
3638

37-
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null)
39+
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null)
3840
{
3941
$this->stopwatch = $stopwatch;
4042
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4143
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
44+
$this->requestStack = $requestStack;
4245

4346
// All clones share these properties by reference:
4447
$this->rootRefs = array(
@@ -118,8 +121,12 @@ public function dump(Data $data)
118121
$name = substr($name, strrpos($name, '/') + 1);
119122
F438 }
120123

121-
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
122-
++$this->dataCount;
124+
if ($this->dumper) {
125+
$this->doDump($data, $name, $file, $line);
126+
} else {
127+
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
128+
++$this->dataCount;
129+
}
123130

124131
if ($this->stopwatch) {
125132
$this->stopwatch->stop('dump');
@@ -128,6 +135,33 @@ public function dump(Data $data)
128135

129136
public function collect(Request $request, Response $response, \Exception $exception = null)
130137
{
138+
if ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) {
139+
return;
140+
}
141+
142+
// In all conditions that remove the web debug toolbar, dumps are written on the output.
143+
if (!$this->requestStack
144+
|| $request->isXmlHttpRequest()
145+
|| !$response->headers->has('X-Debug-Token')
146+
|| $response->isRedirection()
147+
|| ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html'))
148+
|| 'html' !== $request->getRequestFormat()
149+
|| false === strripos($response->getContent(), '</body>')
150+
) {
151+
if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) {
152+
$this->dumper = new HtmlDumper('php://output', $this->charset);
153+
} else {
154+
$this->dumper = new CliDumper('php://output', $this->charset);
155+
}
156+
157+
foreach ($this->data as $i => $dump) {
158+
$this->data[$i] = null;
159+
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
160+
}
161+
162+
$this->data = array();
163+
$this->dataCount = 0;
164+
}
131165
}
132166

133167
public function serialize()
@@ -140,6 +174,7 @@ public function serialize()
140174
$this->data = array();
141175
$this->dataCount = 0;
142176
$this->isCollected = true;
177+
$this->dumper = null;
143178

144179
return $ser;
145180
}
@@ -198,38 +233,41 @@ public function __destruct()
198233
}
199234

200235
if ('cli' !== PHP_SAPI && stripos($h[$i], 'html')) {
201-
$dumper = new HtmlDumper('php://output', $this->charset);
236+
$this->dumper = new HtmlDumper('php://output', $this->charset);
202237
} else {
203-
$dumper = new CliDumper('php://output', $this->charset);
204-
$dumper->setColors(false);
238+
$this->dumper = new CliDumper('php://output', $this->charset);
205239
}
206240

207241
foreach ($this->data as $i => $dump) {
208242
$this->data[$i] = null;
209-
210-
if ($dumper instanceof HtmlDumper) {
211-
$dump['name'] = $this->htmlEncode($dump['name']);
212-
$dump['file'] = $this->htmlEncode($dump['file']);
213-
if ('' !== $dump['file']) {
214-
if ($this->fileLinkFormat) {
215-
$link = strtr($this->fileLinkFormat, array('%f' => $dump['file'], '%l' => $dump['line']));
216-
$dump['name'] = sprintf('<a href="%s" title="%s">%s</a>', $link, $dump['file'], $dump['name']);
217-
} else {
218-
$dump['name'] = sprintf('<abbr title="%s">%s</abbr>', $dump['file'], $dump['name']);
219-
}
220-
}
221-
echo "\n<span class=\"sf-dump-meta\">{$dump['name']} on line {$dump['line']}:</span>";
222-
} else {
223-
echo "{$dump['name']} on line {$dump['line']}:\n";
224-
}
225-
$dumper->dump($dump['data']);
243+
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
226244
}
227245

228246
$this->data = array();
229247
$this->dataCount = 0;
230248
}
231249
}
232250

251+
private function doDump($data, $name, $file, $line)
252+
{
253+
if ($this->dumper instanceof HtmlDumper) {
254+
$name = $this->htmlEncode($name);
255+
$file = $this->htmlEncode($file);
256+
if ('' !== $file) {
257+
if ($this->fileLinkFormat) {
258+
$link = strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
259+
$name = sprintf('<a href="%s" title="%s">%s</a>', $link, $file, $name);
260+
} else {
261+
$name = sprintf('<abbr title="%s">%s</abbr>', $file, $name);
262+
}
263+
}
264+
echo "\n<span class=\"sf-dump-meta\">{$name} on line {$line}:</span>";
265+
} else {
266+
echo "{$name} on line {$line}:\n";
267+
}
268+
$this->dumper->dump($data);
269+
}
270+
233271
private function htmlEncode($s)
234272
{
235273
$html = '';

src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
namespace Symfony\Component\HttpKernel\Tests\DataCollector;
1313

1414
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\Response;
1517
use Symfony\Component\VarDumper\Cloner\Data;
1618

1719
/**
18-
* DumpDataCollectorTest
19-
*
2020
* @author Nicolas Grekas <p@tchwork.com>
2121
*/
2222
class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
@@ -58,6 +58,49 @@ public function testDump()
5858
$this->assertSame('a:0:{}', $collector->serialize());
5959
}
6060

61+
public function testCollectDefault()
62+
{
63+
$data = new Data(array(array(123)));
64+
65+
$collector = new DumpDataCollector();
66+
67+
$collector->dump($data);
68+
$line = __LINE__ - 1;
69+
70+
ob_start();
71+
$collector->collect(new Request(), new Response());
72+
$output = ob_get_clean();
73+
74+
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output);
75+
}
76+
77+
public function testCollectHtml()
78+
{
79+
$data = new Data(array(array(123)));
80+
81+
$collector = new DumpDataCollector(null, 'test://%f:%l');
82+
83+
$collector->dump($data);
84+
$line = __LINE__ - 1;
85+
$file = __FILE__;
86+
$xOutput = <<<EOTXT
87+
88+
<span class="sf-dump-meta"><a href="test://{$file}:{$line}" title="{$file}">DumpDataCollectorTest.php</a> on line {$line}:</span> <pre class=sf-dump id=sf-dump data-indent-pad=" "><span class=sf-dump-num>123</span>
89+
</pre>
90+
91+
EOTXT;
92+
93+
ob_start();
94+
$response = new Response();
95+
$response->headers->set('Content-Type', 'text/html');
96+
$collector->collect(new Request(), $response);
97+
$output = ob_get_clean();
98+
$output = preg_replace('#<(script|style).*?</\1>#s', '', $output);
99+
$output = preg_replace('/sf-dump-\d+/', 'sf-dump', $output);
100+
101+
$this->assertSame($xOutput, $output);
102+
}
103+
61104
public function testFlush()
62105
{
63106
$data = new Data(array(array(456)));

0 commit comments

Comments
 (0)
0