bug #14640 [DebugBundle] Allow alternative destination for dumps (nicolas-grekas)
This PR was merged into the 2.6 branch. Discussion ---------- [DebugBundle] Allow alternative destination for dumps | Q | A | ------------- | --- | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #14608 | License | MIT | Doc PR | - This PR fixes #14608 by adding a new `debug.dump_destination` configuration option to give users control over a stream destination where dumps will be written to. In HTTP mode, dumps are still/also collected in the toolbar. This supersedes #14627, #14631 and #14373 Commits -------5f255e5
[DebugBundle] Allow alternative destination for dumps5368483
[DebugBundle] Use output mechanism of dumpers instead of echoing8cb2abb
[DebugBundle] Always collect dumps
This commit is contained in:
commit
525c149f92
@ -14,7 +14,6 @@ namespace Symfony\Bundle\DebugBundle;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -31,7 +30,7 @@ class DebugBundle extends Bundle
|
||||
// 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));
|
||||
|
@ -41,6 +41,11 @@ class Configuration implements ConfigurationInterface
|
||||
->min(-1)
|
||||
->defaultValue(-1)
|
||||
->end()
|
||||
->scalarNode('dump_destination')
|
||||
->info('A stream URL where dumps should be written to')
|
||||
->example('php://stderr')
|
||||
->defaultNull()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Bundle\DebugBundle\DependencyInjection;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -37,6 +38,15 @@ class DebugExtension extends Extension
|
||||
$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'))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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">
|
||||
@ -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>
|
||||
|
@ -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(
|
||||
@ -123,11 +126,11 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
|
||||
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');
|
||||
}
|
||||
@ -136,7 +139,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
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;
|
||||
}
|
||||
|
||||
@ -154,13 +157,9 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +173,9 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->data = array();
|
||||
$this->dataCount = 0;
|
||||
$this->isCollected = true;
|
||||
$this->dumper = null;
|
||||
if (!$this->dumperIsInjected) {
|
||||
$this->dumper = null;
|
||||
}
|
||||
|
||||
return $ser;
|
||||
}
|
||||
@ -250,20 +251,33 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -71,7 +71,13 @@ class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||
$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()
|
||||
@ -83,12 +89,23 @@ class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||
$collector->dump($data);
|
||||
$line = __LINE__ - 1;
|
||||
$file = __FILE__;
|
||||
$xOutput = <<<EOTXT
|
||||
|
||||
<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>
|
||||
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>
|
||||
|
||||
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();
|
||||
@ -99,6 +116,8 @@ EOTXT;
|
||||
$output = preg_replace('/sf-dump-\d+/', 'sf-dump', $output);
|
||||
|
||||
$this->assertSame($xOutput, $output);
|
||||
$this->assertSame(1, $collector->getDumpsCount());
|
||||
$collector->serialize();
|
||||
}
|
||||
|
||||
public function testFlush()
|
||||
@ -110,6 +129,10 @@ EOTXT;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user