Skip to content

[DebugBundle] Allow alternative destination for dumps #14640

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/Symfony/Bundle/DebugBundle/DebugBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\VarDumper;

/**
Expand All @@ -31,7 +30,7 @@ public function boot()
// configuration for CLI mode is overridden in HTTP mode on
// 'kernel.request' event
VarDumper::setHandler(function ($var) use ($container) {
$dumper = new CliDumper();
$dumper = $container->get('var_dumper.cli_dumper');
$cloner = $container->get('var_dumper.cloner');
$handler = function ($var) use ($dumper, $cloner) {
$dumper->dump($cloner->cloneVar($var));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public function getConfigTreeBuilder()
->min(-1)
->defaultValue(-1)
->end()
->scalarNode('dump_destination')
->info('A stream URL where dumps should be written to')
->example('php://stderr')
->defaultNull()
->end()
->end()
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

/**
Expand All @@ -37,6 +38,15 @@ public function load(array $configs, ContainerBuilder $container)
$container->getDefinition('var_dumper.cloner')
->addMethodCall('setMaxItems', array($config['max_items']))
->addMethodCall('setMaxString', array($config['max_string_length']));

if (null !== $config['dump_destination']) {
$container->getDefinition('var_dumper.cli_dumper')
->replaceArgument(0, $config['dump_destination'])
;
$container->getDefinition('data_collector.dump')
->replaceArgument(4, new Reference('var_dumper.cli_dumper'))
;
}
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Bundle/DebugBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
<argument>%kernel.charset%</argument>
<argument type="service" id="request_stack" />
<argument>null</argument><!-- var_dumper.cli_dumper when debug.dump_destination is set -->
</service>

<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">
Expand All @@ -25,6 +26,10 @@
</service>

<service id="var_dumper.cloner" class="Symfony\Component\VarDumper\Cloner\VarCloner" />
<service id="var_dumper.cli_dumper" class="Symfony\Component\VarDumper\Dumper\CliDumper">
<argument>null</argument><!-- debug.dump_destination -->
<argument>%kernel.charset%</argument>
</service>
</services>

</container>
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
private $rootRefs;
private $charset;
private $dumper;
private $dumperIsInjected;

public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null)
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null, DataDumperInterface $dumper = null)
{
$this->stopwatch = $stopwatch;
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
$this->requestStack = $requestStack;
$this->dumper = $dumper;
$this->dumperIsInjected = null !== $dumper;

// All clones share these properties by reference:
$this->rootRefs = array(
Expand Down Expand Up @@ -123,11 +126,11 @@ public function dump(Data $data)

if ($this->dumper) {
$this->doDump($data, $name, $file, $line);
} else {
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
++$this->dataCount;
}

$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
++$this->dataCount;

if ($this->stopwatch) {
$this->stopwatch->stop('dump');
}
Expand All @@ -136,7 +139,7 @@ public function dump(Data $data)
public function collect(Request $request, Response $response, \Exception $exception = null)
{
// Sub-requests and programmatic calls stay in the collected profile.
if (($this->requestStack && $this->requestStack->getMasterRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) {
if ($this->dumper || ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) {
return;
}

Expand All @@ -154,13 +157,9 @@ public function collect(Request $request, Response $response, \Exception $except
$this->dumper = new CliDumper('php://output', $this->charset);
}

foreach ($this->data as $i => $dump) {
$this->data[$i] = null;
foreach ($this->data as $dump) {
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
}

$this->data = array();
$this->dataCount = 0;
}
}

Expand All @@ -174,7 +173,9 @@ public function serialize()
$this->data = array();
$this->dataCount = 0;
$this->isCollected = true;
$this->dumper = null;
if (!$this->dumperIsInjected) {
$this->dumper = null;
}

return $ser;
}
Expand Down Expand Up @@ -250,20 +251,33 @@ public function __destruct()

private function doDump($data, $name, $file, $line)
{
if ($this->dumper instanceof HtmlDumper) {
$name = $this->htmlEncode($name);
$file = $this->htmlEncode($file);
if ('' !== $file) {
if ($this->fileLinkFormat) {
$link = strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
$name = sprintf('<a href="%s" title="%s">%s</a>', $link, $file, $name);
if (PHP_VERSION_ID >= 50400 && $this->dumper instanceof CliDumper) {
$contextDumper = function ($name, $file, $line, $fileLinkFormat) {
if ($this instanceof HtmlDumper) {
if ('' !== $file) {
$s = $this->style('meta', '%s');
$name = strip_tags($this->style('', $name));
$file = strip_tags($this->style('', $file));
if ($fileLinkFormat) {
$link = strtr($fileLinkFormat, array('%f' => $file, '%l' => (int) $line));
$name = sprintf('<a href="%s" title="%s">'.$s.'</a>', $link, $file, $name);
} else {
$name = sprintf('<abbr title="%s">'.$s.'</abbr>', $file, $name);
}
} else {
$name = $this->style('meta', $name);
}
$this->line = $name.' on line '.$this->style('meta', $line).':';
} else {
$name = sprintf('<abbr title="%s">%s</abbr>', $file, $name);
$this->line = $this->style('meta', $name).' on line '.$this->style('meta', $line).':';
}
}
echo "\n<span class=\"sf-dump-meta\">{$name} on line {$line}:</span>";
$this->dumpLine(0);
};
$contextDumper = $contextDumper->bindTo($this->dumper, $this->dumper);
$contextDumper($name, $file, $line, $this->fileLinkFormat);
} else {
echo "{$name} on line {$line}:\n";
$cloner = new VarCloner();
$this->dumper->dump($cloner->cloneVar($name.' on line '.$line.':'));
}
$this->dumper->dump($data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@ public function testCollectDefault()
$collector->collect(new Request(), new Response());
$output = ob_get_clean();

$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output);
if (PHP_VERSION_ID >= 50400) {
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output);
} else {
$this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n123\n", $output);
}
$this->assertSame(1, $collector->getDumpsCount());
$collector->serialize();
}

public function testCollectHtml()
Expand All @@ -83,12 +89,23 @@ public function testCollectHtml()
$collector->dump($data);
$line = __LINE__ - 1;
$file = __FILE__;
$xOutput = <<<EOTXT
if (PHP_VERSION_ID >= 50400) {
$xOutput = <<<EOTXT
<pre class=sf-dump id=sf-dump data-indent-pad=" "><a href="test://{$file}:{$line}" title="{$file}"><span class=sf-dump-meta>DumpDataCollectorTest.php</span></a> on line <span class=sf-dump-meta>{$line}</span>:
<span class=sf-dump-num>123</span>
</pre>

<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>
EOTXT;
} else {
$len = strlen("DumpDataCollectorTest.php on line {$line}:");
$xOutput = <<<EOTXT
<pre class=sf-dump id=sf-dump data-indent-pad=" ">"<span class=sf-dump-str title="{$len} characters">DumpDataCollectorTest.php on line {$line}:</span>"
</pre>
<pre class=sf-dump id=sf-dump data-indent-pad=" "><span class=sf-dump-num>123</span>
</pre>

EOTXT;
}

ob_start();
$response = new Response();
Expand All @@ -99,6 +116,8 @@ public function testCollectHtml()
$output = preg_replace('/sf-dump-\d+/', 'sf-dump', $output);

$this->assertSame($xOutput, $output);
$this->assertSame(1, $collector->getDumpsCount());
$collector->serialize();
}

public function testFlush()
Expand All @@ -110,6 +129,10 @@ public function testFlush()

ob_start();
$collector = null;
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean());
if (PHP_VERSION_ID >= 50400) {
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean());
} else {
$this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n456\n", ob_get_clean());
}
}
}