[DebugBundle] Fix dump() output in API/No-Toolbar context
This commit is contained in:
parent
dc86ff71e2
commit
62f8469f25
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Bundle\DebugBundle\DependencyInjection\Compiler;
|
namespace Symfony\Bundle\DebugBundle\DependencyInjection\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
|
||||||
@ -35,5 +36,9 @@ class DumpDataCollectorPass implements CompilerPassInterface
|
|||||||
if ($container->hasParameter('templating.helper.code.file_link_format')) {
|
if ($container->hasParameter('templating.helper.code.file_link_format')) {
|
||||||
$definition->replaceArgument(1, $container->getParameter('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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
|
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
|
||||||
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
|
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
|
||||||
<argument>%kernel.charset%</argument>
|
<argument>%kernel.charset%</argument>
|
||||||
|
<argument type="service" id="request_stack" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">
|
<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">
|
||||||
|
@ -12,8 +12,10 @@
|
|||||||
namespace Symfony\Bundle\DebugBundle\Tests\DependencyInjection\Compiler;
|
namespace Symfony\Bundle\DebugBundle\Tests\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
|
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
|
||||||
|
use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
|
||||||
class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
|
class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
@ -23,7 +25,7 @@ class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
|
|||||||
$container->addCompilerPass(new DumpDataCollectorPass());
|
$container->addCompilerPass(new DumpDataCollectorPass());
|
||||||
$container->setParameter('templating.helper.code.file_link_format', 'file-link-format');
|
$container->setParameter('templating.helper.code.file_link_format', 'file-link-format');
|
||||||
|
|
||||||
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null));
|
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, null));
|
||||||
$container->setDefinition('data_collector.dump', $definition);
|
$container->setDefinition('data_collector.dump', $definition);
|
||||||
|
|
||||||
$container->compile();
|
$container->compile();
|
||||||
@ -36,11 +38,53 @@ class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
|
|||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
$container->addCompilerPass(new DumpDataCollectorPass());
|
$container->addCompilerPass(new DumpDataCollectorPass());
|
||||||
|
|
||||||
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null));
|
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, null));
|
||||||
$container->setDefinition('data_collector.dump', $definition);
|
$container->setDefinition('data_collector.dump', $definition);
|
||||||
|
|
||||||
$container->compile();
|
$container->compile();
|
||||||
|
|
||||||
$this->assertNull($definition->getArgument(1));
|
$this->assertNull($definition->getArgument(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testProcessWithToolbarEnabled()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->addCompilerPass(new DumpDataCollectorPass());
|
||||||
|
$requestStack = new RequestStack();
|
||||||
|
|
||||||
|
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, $requestStack));
|
||||||
|
$container->setDefinition('data_collector.dump', $definition);
|
||||||
|
$container->setParameter('web_profiler.debug_toolbar.mode', WebDebugToolbarListener::ENABLED);
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
|
||||||
|
$this->assertSame($requestStack, $definition->getArgument(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithToolbarDisabled()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->addCompilerPass(new DumpDataCollectorPass());
|
||||||
|
|
||||||
|
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, new RequestStack()));
|
||||||
|
$container->setDefinition('data_collector.dump', $definition);
|
||||||
|
$container->setParameter('web_profiler.debug_toolbar.mode', WebDebugToolbarListener::DISABLED);
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
|
||||||
|
$this->assertNull($definition->getArgument(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessWithoutToolbar()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->addCompilerPass(new DumpDataCollectorPass());
|
||||||
|
|
||||||
|
$definition = new Definition('Symfony\Component\HttpKernel\DataCollector\DumpDataCollector', array(null, null, null, new RequestStack()));
|
||||||
|
$container->setDefinition('data_collector.dump', $definition);
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
|
||||||
|
$this->assertNull($definition->getArgument(3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/phpunit-bridge": "~2.7",
|
"symfony/phpunit-bridge": "~2.7",
|
||||||
"symfony/config": "~2.3",
|
"symfony/config": "~2.3",
|
||||||
"symfony/dependency-injection": "~2.3"
|
"symfony/dependency-injection": "~2.3",
|
||||||
|
"symfony/web-profiler-bundle": "~2.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/config": "For service container configuration",
|
"symfony/config": "For service container configuration",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Stopwatch\Stopwatch;
|
use Symfony\Component\Stopwatch\Stopwatch;
|
||||||
use Symfony\Component\VarDumper\Cloner\Data;
|
use Symfony\Component\VarDumper\Cloner\Data;
|
||||||
@ -33,12 +34,14 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
|||||||
private $clonesIndex = 0;
|
private $clonesIndex = 0;
|
||||||
private $rootRefs;
|
private $rootRefs;
|
||||||
private $charset;
|
private $charset;
|
||||||
|
private $dumper;
|
||||||
|
|
||||||
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null)
|
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null)
|
||||||
{
|
{
|
||||||
$this->stopwatch = $stopwatch;
|
$this->stopwatch = $stopwatch;
|
||||||
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
$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->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
|
||||||
|
$this->requestStack = $requestStack;
|
||||||
|
|
||||||
// All clones share these properties by reference:
|
// All clones share these properties by reference:
|
||||||
$this->rootRefs = array(
|
$this->rootRefs = array(
|
||||||
@ -118,8 +121,12 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
|||||||
$name = substr($name, strrpos($name, '/') + 1);
|
$name = substr($name, strrpos($name, '/') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->dumper) {
|
||||||
|
$this->doDump($data, $name, $file, $line);
|
||||||
|
} else {
|
||||||
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
|
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
|
||||||
++$this->dataCount;
|
++$this->dataCount;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->stopwatch) {
|
if ($this->stopwatch) {
|
||||||
$this->stopwatch->stop('dump');
|
$this->stopwatch->stop('dump');
|
||||||
@ -128,6 +135,33 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
|||||||
|
|
||||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||||
{
|
{
|
||||||
|
if ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In all conditions that remove the web debug toolbar, dumps are written on the output.
|
||||||
|
if (!$this->requestStack
|
||||||
|
|| $request->isXmlHttpRequest()
|
||||||
|
|| !$response->headers->has('X-Debug-Token')
|
||||||
|
|| $response->isRedirection()
|
||||||
|
|| ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html'))
|
||||||
|
|| 'html' !== $request->getRequestFormat()
|
||||||
|
|| false === strripos($response->getContent(), '</body>')
|
||||||
|
) {
|
||||||
|
if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) {
|
||||||
|
$this->dumper = new HtmlDumper('php://output', $this->charset);
|
||||||
|
} else {
|
||||||
|
$this->dumper = new CliDumper('php://output', $this->charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->data as $i => $dump) {
|
||||||
|
$this->data[$i] = null;
|
||||||
|
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->data = array();
|
||||||
|
$this->dataCount = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function serialize()
|
public function serialize()
|
||||||
@ -140,6 +174,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
|||||||
$this->data = array();
|
$this->data = array();
|
||||||
$this->dataCount = 0;
|
$this->dataCount = 0;
|
||||||
$this->isCollected = true;
|
$this->isCollected = true;
|
||||||
|
$this->dumper = null;
|
||||||
|
|
||||||
return $ser;
|
return $ser;
|
||||||
}
|
}
|
||||||
@ -198,31 +233,14 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('cli' !== PHP_SAPI && stripos($h[$i], 'html')) {
|
if ('cli' !== PHP_SAPI && stripos($h[$i], 'html')) {
|
||||||
$dumper = new HtmlDumper('php://output', $this->charset);
|
$this->dumper = new HtmlDumper('php://output', $this->charset);
|
||||||
} else {
|
} else {
|
||||||
$dumper = new CliDumper('php://output', $this->charset);
|
$this->dumper = new CliDumper('php://output', $this->charset);
|
||||||
$dumper->setColors(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->data as $i => $dump) {
|
foreach ($this->data as $i => $dump) {
|
||||||
$this->data[$i] = null;
|
$this->data[$i] = null;
|
||||||
|
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
|
||||||
if ($dumper instanceof HtmlDumper) {
|
|
||||||
$dump['name'] = $this->htmlEncode($dump['name']);
|
|
||||||
$dump['file'] = $this->htmlEncode($dump['file']);
|
|
||||||
if ('' !== $dump['file']) {
|
|
||||||
if ($this->fileLinkFormat) {
|
|
||||||
$link = strtr($this->fileLinkFormat, array('%f' => $dump['file'], '%l' => $dump['line']));
|
|
||||||
$dump['name'] = sprintf('<a href="%s" title="%s">%s</a>', $link, $dump['file'], $dump['name']);
|
|
||||||
} else {
|
|
||||||
$dump['name'] = sprintf('<abbr title="%s">%s</abbr>', $dump['file'], $dump['name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo "\n<span class=\"sf-dump-meta\">{$dump['name']} on line {$dump['line']}:</span>";
|
|
||||||
} else {
|
|
||||||
echo "{$dump['name']} on line {$dump['line']}:\n";
|
|
||||||
}
|
|
||||||
$dumper->dump($dump['data']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->data = array();
|
$this->data = array();
|
||||||
@ -230,6 +248,26 @@ 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);
|
||||||
|
} else {
|
||||||
|
$name = sprintf('<abbr title="%s">%s</abbr>', $file, $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "\n<span class=\"sf-dump-meta\">{$name} on line {$line}:</span>";
|
||||||
|
} else {
|
||||||
|
echo "{$name} on line {$line}:\n";
|
||||||
|
}
|
||||||
|
$this->dumper->dump($data);
|
||||||
|
}
|
||||||
|
|
||||||
private function htmlEncode($s)
|
private function htmlEncode($s)
|
||||||
{
|
{
|
||||||
$html = '';
|
$html = '';
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
namespace Symfony\Component\HttpKernel\Tests\DataCollector;
|
namespace Symfony\Component\HttpKernel\Tests\DataCollector;
|
||||||
|
|
||||||
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
|
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\VarDumper\Cloner\Data;
|
use Symfony\Component\VarDumper\Cloner\Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DumpDataCollectorTest
|
|
||||||
*
|
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
|
class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||||
@ -58,6 +58,49 @@ class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertSame('a:0:{}', $collector->serialize());
|
$this->assertSame('a:0:{}', $collector->serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCollectDefault()
|
||||||
|
{
|
||||||
|
$data = new Data(array(array(123)));
|
||||||
|
|
||||||
|
$collector = new DumpDataCollector();
|
||||||
|
|
||||||
|
$collector->dump($data);
|
||||||
|
$line = __LINE__ - 1;
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
$collector->collect(new Request(), new Response());
|
||||||
|
$output = ob_get_clean();
|
||||||
|
|
||||||
|
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCollectHtml()
|
||||||
|
{
|
||||||
|
$data = new Data(array(array(123)));
|
||||||
|
|
||||||
|
$collector = new DumpDataCollector(null, 'test://%f:%l');
|
||||||
|
|
||||||
|
$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>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
EOTXT;
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
$response = new Response();
|
||||||
|
$response->headers->set('Content-Type', 'text/html');
|
||||||
|
$collector->collect(new Request(), $response);
|
||||||
|
$output = ob_get_clean();
|
||||||
|
$output = preg_replace('#<(script|style).*?</\1>#s', '', $output);
|
||||||
|
$output = preg_replace('/sf-dump-\d+/', 'sf-dump', $output);
|
||||||
|
|
||||||
|
$this->assertSame($xOutput, $output);
|
||||||
|
}
|
||||||
|
|
||||||
public function testFlush()
|
public function testFlush()
|
||||||
{
|
{
|
||||||
$data = new Data(array(array(456)));
|
$data = new Data(array(array(456)));
|
||||||
|
Reference in New Issue
Block a user