[VarDumper] Some tweaks after Nicolas' commit & ServerDumperPlaceholderCommand

This commit is contained in:
Maxime Steinhausser 2018-03-22 23:33:06 +01:00 committed by Maxime Steinhausser
parent 088c52ed70
commit 138dad6440
12 changed files with 95 additions and 92 deletions

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\DebugBundle\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\VarDumper\Command\ServerDumpCommand;
use Symfony\Component\VarDumper\Server\DumpServer;
/**
* A placeholder command easing VarDumper server discovery.
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*
* @internal
*/
class ServerDumpPlaceholderCommand extends ServerDumpCommand
{
public function __construct(DumpServer $server = null, array $descriptors = array())
{
parent::__construct(new class() extends DumpServer {
public function __construct()
{
}
}, $descriptors);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
(new SymfonyStyle($input, $output))->getErrorStyle()->warning('In order to use the VarDumper server, set the "debug.dump_destination" config option to "tcp://%env(VAR_DUMPER_SERVER)%"');
return 8;
}
}

View File

@ -48,7 +48,7 @@ class Configuration implements ConfigurationInterface
->end()
->scalarNode('dump_destination')
->info('A stream URL where dumps should be written to')
->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the `server:dump` command')
->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the "server:dump" command')
->defaultNull()
->end()
->end()

View File

@ -11,11 +11,13 @@
namespace Symfony\Bundle\DebugBundle\DependencyInjection;
use Symfony\Bundle\DebugBundle\Command\ServerDumpPlaceholderCommand;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\VarDumper\Dumper\ServerDumper;
/**
* DebugExtension.
@ -43,11 +45,18 @@ class DebugExtension extends Extension
if (null === $config['dump_destination']) {
//no-op
} elseif (0 === strpos($config['dump_destination'], 'tcp://')) {
$serverDumperHost = $config['dump_destination'];
$container->getDefinition('debug.dump_listener')
->replaceArgument(1, new Reference('var_dumper.server_dumper'))
;
$container->getDefinition('var_dumper.command.server_dump')
->replaceArgument(1, new Reference('var_dumper.server_dumper'))
$container->getDefinition('data_collector.dump')
->replaceArgument(4, new Reference('var_dumper.server_dumper'))
;
$container->getDefinition('var_dumper.dump_server')
->replaceArgument(0, $serverDumperHost)
;
$container->getDefinition('var_dumper.server_dumper')
->replaceArgument(0, $serverDumperHost)
;
} else {
$container->getDefinition('var_dumper.cli_dumper')
@ -57,6 +66,13 @@ class DebugExtension extends Extension
->replaceArgument(4, new Reference('var_dumper.cli_dumper'))
;
}
if (!isset($serverDumperHost)) {
$container->getDefinition('var_dumper.command.server_dump')->setClass(ServerDumpPlaceholderCommand::class);
if (!class_exists(ServerDumper::class)) {
$container->removeDefinition('var_dumper.command.server_dump');
}
}
}
/**

View File

@ -4,11 +4,13 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="env(VAR_DUMPER_SERVER)">127.0.0.1:9912</parameter>
</parameters>
<services>
<defaults public="false" />
<parameter key="env(VAR_DUMPER_SERVER)">127.0.0.1:9912</parameter>
<service id="twig.extension.dump" class="Symfony\Bridge\Twig\Extension\DumpExtension">
<tag name="twig.extension" />
<argument type="service" id="var_dumper.cloner" />
@ -70,7 +72,14 @@
</argument>
</service>
<service id="var_dumper.dump_server" class="Symfony\Component\VarDumper\Server\DumpServer">
<argument /> <!-- server host -->
<argument type="service" id="logger" on-invalid="null" />
<tag name="monolog.logger" channel="debug" />
</service>
<service id="var_dumper.command.server_dump" class="Symfony\Component\VarDumper\Command\ServerDumpCommand">
<argument type="service" id="var_dumper.dump_server" />
<argument type="collection">
<argument type="service" key="cli">
<service class="Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor">
@ -83,9 +92,7 @@
</service>
</argument>
</argument>
<argument type="service" id="logger" on-invalid="null" />
<tag name="console.command" command="server:dump" />
<tag name="monolog.logger" channel="debug" />
</service>
</services>
</container>

View File

@ -58,7 +58,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
&$this->clonesCount,
);
$this->sourceContextProvider = $dumper instanceof ServerDumper ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
$this->sourceContextProvider = $dumper instanceof ServerDumper && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
}
public function __clone()

View File

@ -12,11 +12,10 @@
namespace Symfony\Component\HttpKernel\Tests\DataCollector;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
use Symfony\Component\VarDumper\Dumper\ServerDumper;
/**
@ -62,33 +61,11 @@ class DumpDataCollectorTest extends TestCase
$data = new Data(array(array(123)));
// Server is up, server dumper is used
$serverDumper = $this->getMockBuilder(ServerDumper::class)->getMock();
$serverDumper = $this->getMockBuilder(ServerDumper::class)->disableOriginalConstructor()->getMock();
$serverDumper->expects($this->once())->method('dump');
$serverDumper->method('isServerListening')->willReturn(true);
// configured dumper is never used
$dumper = $this->getMockBuilder(DataDumperInterface::class)->getMock();
$dumper->expects($this->never())->method('dump');
$collector = new DumpDataCollector(null, null, null, null, $dumper, $serverDumper);
$collector->dump($data);
// Collect doesn't re-trigger dump
ob_start();
$collector->collect(new Request(), new Response());
$this->assertEmpty(ob_get_clean());
$this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize());
// Server is down, server dumper is never used
$serverDumper = $this->getMockBuilder(ServerDumper::class)->getMock();
$serverDumper->expects($this->never())->method('dump');
$serverDumper->method('isServerListening')->willReturn(false);
// configured dumper is used
$dumper = $this->getMockBuilder(DataDumperInterface::class)->getMock();
$dumper->expects($this->exactly(2))->method('dump'); // called twice in doDump if not a CLiDumper instance
$collector = new DumpDataCollector(null, null, null, null, $dumper, $serverDumper);
$collector = new DumpDataCollector(null, null, null, null, $serverDumper);
$collector->dump($data);
// Collect doesn't re-trigger dump
@ -155,34 +132,4 @@ EOTXT;
$collector->__destruct();
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean());
}
public function testFlushWithServerDumper()
{
$data = new Data(array(array(456)));
// Server is up, server dumper is used
$serverDumper = $this->getMockBuilder(ServerDumper::class)->getMock();
$serverDumper->expects($this->once())->method('dump');
$serverDumper->method('isServerListening')->willReturn(true);
$collector = new DumpDataCollector(null, null, null, null, null, $serverDumper);
$collector->dump($data);
ob_start();
$collector->__destruct();
$this->assertEmpty(ob_get_clean());
// Server is down, buffered dump is flushed on destruct
$serverDumper = $this->getMockBuilder(ServerDumper::class)->getMock();
$serverDumper->expects($this->never())->method('dump');
$serverDumper->method('isServerListening')->willReturn(false);
$collector = new DumpDataCollector(null, null, null, null, null, $serverDumper);
$collector->dump($data);
$line = __LINE__ - 1;
ob_start();
$collector->__destruct();
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean());
}
}

View File

@ -7,7 +7,7 @@ CHANGELOG
* added a `ServerDumper` to send serialized Data clones to a server
* added a `ServerDumpCommand` and `DumpServer` to run a server collecting
and displaying dumps on a single place with multiple formats support
* added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` cli and html formats support
* added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support
4.0.0
-----

View File

@ -36,7 +36,7 @@ class CliDescriptor implements DumpDescriptorInterface
public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void
{
$io = new SymfonyStyle(new ArrayInput(array()), $output);
$io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput(array()), $output);
$rows = array(array('date', date('r', $context['timestamp'])));
$lastIdentifier = $this->lastIdentifier;

View File

@ -11,7 +11,6 @@
namespace Symfony\Component\VarDumper\Command;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
@ -37,14 +36,14 @@ class ServerDumpCommand extends Command
{
protected static $defaultName = 'server:dump';
private $logger;
private $server;
/** @var DumpDescriptorInterface[] */
private $descriptors;
public function __construct(array $descriptors = array(), LoggerInterface $logger = null)
public function __construct(DumpServer $server, array $descriptors = array())
{
$this->logger = $logger;
$this->server = $server;
$this->descriptors = $descriptors + array(
'cli' => new CliDescriptor(new CliDumper()),
'html' => new HtmlDescriptor(new HtmlDumper()),
@ -58,7 +57,7 @@ class ServerDumpCommand extends Command
$availableFormats = implode(', ', array_keys($this->descriptors));
$this
->addOption('format', null, InputOption::VALUE_REQUIRED, "The output format ($availableFormats)", 'cli')
->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', $availableFormats), 'cli')
->setDescription('Starts a dump server that collects and displays dumps in a single place')
->setHelp(<<<'EOF'
<info>%command.name%</info> starts a dump server that collects and displays
@ -88,14 +87,13 @@ EOF
$errorIo = $io->getErrorStyle();
$errorIo->title('Symfony Var Dumper Server');
$server = new DumpServer(null, $this->logger);
$server->start();
$this->server->start();
$errorIo->success(sprintf('Server listening on %s', $server->getHost()));
$errorIo->success(sprintf('Server listening on %s', $this->server->getHost()));
$errorIo->comment('Quit the server with CONTROL-C.');
$server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $output) {
$descriptor->describe($output, $data, $context, $clientId);
$this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) {
$descriptor->describe($io, $data, $context, $clientId);
});
}
}

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\VarDumper\Dumper;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
use Symfony\Component\VarDumper\Server\DumpServer;
/**
* ServerDumper forwards serialized Data clones to a server.
@ -43,7 +42,7 @@ class ServerDumper implements DataDumperInterface
$this->contextProviders = $contextProviders;
}
public function getContextProviders(): ?array
public function getContextProviders(): array
{
return $this->contextProviders;
}

View File

@ -21,21 +21,13 @@ use Symfony\Component\VarDumper\Dumper\ServerDumper;
class ServerDumperTest extends TestCase
{
public static function setUpBeforeClass()
{
putenv('VAR_DUMPER_SERVER=tcp://127.0.0.1:9913');
}
public static function tearDownAfterClass()
{
putenv('VAR_DUMPER_SERVER');
}
private const VAR_DUMPER_SERVER = 'tcp://127.0.0.1:9913';
public function testDumpForwardsToWrappedDumperWhenServerIsUnavailable()
{
$wrappedDumper = $this->getMockBuilder(DataDumperInterface::class)->getMock();
$dumper = new ServerDumper(null, $wrappedDumper);
$dumper = new ServerDumper(self::VAR_DUMPER_SERVER, $wrappedDumper);
$cloner = new VarCloner();
$data = $cloner->cloneVar('foo');
@ -47,7 +39,7 @@ class ServerDumperTest extends TestCase
public function testIsServerListening()
{
$dumper = new ServerDumper();
$dumper = new ServerDumper(self::VAR_DUMPER_SERVER);
$this->assertFalse($dumper->isServerListening());
@ -73,7 +65,7 @@ class ServerDumperTest extends TestCase
$cloner = new VarCloner();
$data = $cloner->cloneVar('foo');
$dumper = new ServerDumper(null, $wrappedDumper, array(
$dumper = new ServerDumper(self::VAR_DUMPER_SERVER, $wrappedDumper, array(
'foo_provider' => new class() implements ContextProviderInterface {
public function getContext(): ?array
{
@ -117,7 +109,7 @@ DUMP
{
$process = new PhpProcess(file_get_contents(__DIR__.'/../Fixtures/dump_server.php'), null, array(
'COMPONENT_ROOT' => __DIR__.'/../../',
'VAR_DUMPER_SERVER' => 'tcp://127.0.0.1:9913',
'VAR_DUMPER_SERVER' => self::VAR_DUMPER_SERVER,
));
$process->inheritEnvironmentVariables(true);

View File

@ -25,7 +25,7 @@ VarDumper::setHandler(function ($var) use ($cloner, $dumper) {
$dumper->dump($data);
});
$server = new DumpServer();
$server = new DumpServer(getenv('VAR_DUMPER_SERVER'));
$server->start();