8000 [VarDumper] Fix dumping by splitting Server/Connection out of Dumper/… · symfony/symfony@1435d67 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1435d67

Browse files
[VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper
1 parent 6e0818d commit 1435d67

File tree

14 files changed

+252
-126
lines changed

14 files changed

+252
-126
lines changed

src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use Symfony\Component\DependencyInjection\Extension\Extension;
1818
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
1919
use Symfony\Component\DependencyInjection\Reference;
20-
use Symfony\Component\VarDumper\Dumper\ServerDumper;
2120

2221
/**
2322
* DebugExtension.
@@ -43,20 +42,21 @@ public function load(array $configs, ContainerBuilder $container)
4342
->addMethodCall('setMaxString', array($config['max_string_length']));
4443

4544
if (null === $config['dump_destination']) {
46-
//no-op
45+
$container->getDefinition('var_dumper.command.server_dump')
46+
->setClass(ServerDumpPlaceholderCommand::class)
47+
;
4748
} elseif (0 === strpos($config['dump_destination'], 'tcp://')) {
48-
$serverDumperHost = $config['dump_destination'];
4949
$container->getDefinition('debug.dump_listener')
50-
->replaceArgument(1, new Reference('var_dumper.server_dumper'))
50+
->replaceArgument(2, new Reference('var_dumper.server_connection'))
5151
;
5252
$container->getDefinition('data_collector.dump')
53-
->replaceArgument(4, new Reference('var_dumper.server_dumper'))
53+
->replaceArgument(4, new Reference('var_dumper.server_connection'))
5454
;
5555
$container->getDefinition('var_dumper.dump_server')
56-
->replaceArgument(0, $serverDumperHost)
56+
->replaceArgument(0, $config['dump_destination'])
5757
;
58-
$container->getDefinition('var_dumper.server_dumper')
59-
->replaceArgument(0, $serverDumperHost)
58+
$container->getDefinition('var_dumper.server_connection')
59+
->replaceArgument(0, $config['dump_destination'])
6060
;
6161
} else {
6262
$container->getDefinition('var_dumper.cli_dumper')
@@ -65,13 +65,9 @@ public function load(array $configs, ContainerBuilder $container)
6565
$container->getDefinition('data_collector.dump')
6666
->replaceArgument(4, new Reference('var_dumper.cli_dumper'))
6767
;
68-
}
69-
70-
if (!isset($serverDumperHost)) {
71-
$container->getDefinition('var_dumper.command.server_dump')->setClass(ServerDumpPlaceholderCommand::class);
72-
if (!class_exists(ServerDumper::class)) {
73-
$container->removeDefinition('var_dumper.command.server_dump');
74-
}
68+
$container->getDefinition('var_dumper.command.server_dump')
69+
->setClass(ServerDumpPlaceholderCommand::class)
70+
;
7571
}
7672
}
7773

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
<argument type="service" id="debug.file_link_formatter" on-invalid="ignore"></argument>
2424
<argument>%kernel.charset%</argument>
2525
<argument type="service" id="request_stack" />
26-
<argument>null</argument><!-- var_dumper.cli_dumper or var_dumper.server_dumper when debug.dump_destination is set -->
26+
<argument>null</argument><!-- var_dumper.cli_dumper or var_dumper.server_connection when debug.dump_destination is set -->
2727
</service>
2828

2929
<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">
3030
<tag name="kernel.event_subscriber" />
3131
<argument type="service" id="var_dumper.cloner" />
3232
<argument type="service" id="var_dumper.cli_dumper" />
33+
<argument>null</argument>
3334
</service>
3435

3536
<service id="var_dumper.cloner" class="Symfony\Component\VarDumper\Cloner\VarCloner" public="true" />
@@ -50,9 +51,8 @@
5051
</call>
5152
</service>
5253

53-
<service id="var_dumper.server_dumper" class="Symfony\Component\VarDumper\Dumper\ServerDumper">
54-
<argument>null</argument> <!-- server host -->
55-
<argument type="service" id="var_dumper.cli_dumper" />
54+
<service id="var_dumper.server_connection" class="Symfony\Component\VarDumper\Server\Connection">
55+
<argument /> <!-- server host -->
5656
<argument type="collection">
5757
<argument type="service" key="source">
5858
<service class="Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider">

src/Symfony/Bundle/DebugBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"ext-xml": "*",
2121
"symfony/http-kernel": "~3.4|~4.0",
2222
"symfony/twig-bridge": "~3.4|~4.0",
23-
"symfony/var-dumper": "~4.1"
23+
"symfony/var-dumper": "^4.1.1"
2424
},
2525
"require-dev": {
2626
"symfony/config": "~3.4|~4.0",

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
2222
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
2323
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
24-
use Symfony\Component\VarDumper\Dumper\ServerDumper;
24+
use Symfony\Component\VarDumper\Server\Connection;
2525

2626
/**
2727
* @author Nicolas Grekas <p@tchwork.com>
@@ -38,17 +38,18 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
3838
private $charset;
3939
private $requestStack;
4040
private $dumper;
41-
private $dumperIsInjected;
4241
private $sourceContextProvider;
4342

44-
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, DataDumperInterface $dumper = null)
43+
/**
44+
* @param DataDumperInterface|Connection|null $dumper
45+
*/
46+
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null)
4547
{
4648
$this->stopwatch = $stopwatch;
4749
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
4850
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
4951
$this->requestStack = $requestStack;
5052
$this->dumper = $dumper;
51-
$this->dumperIsInjected = null !== $dumper;
5253

5354
// All clones share these properties by reference:
5455
$this->rootRefs = array(
@@ -58,7 +59,7 @@ public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null,
5859
&$this->clonesCount,
5960
);
6061

61-
$this->sourceContextProvider = $dumper instanceof ServerDumper && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
62+
$this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
6263
}
6364

6465
public function __clone()
@@ -71,14 +72,17 @@ public function dump(Data $data)
7172
if ($this->stopwatch) {
7273
$this->stopwatch->start('dump');
7374
}
74-
if ($this->isCollected && !$this->dumper) {
75-
$this->isCollected = false;
76-
}
7775

7876
list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext();
7977

80-
if ($this->dumper) {
78+
if ($this->dumper instanceof Connection) {
79+
if (!$this->dumper->write($data)) {
80+
$this->isCollected = false;
81+
}
82+
} elseif ($this->dumper) {
8183
$this->doDump($this->dumper, $data, $name, $file, $line);
84+
} else {
85+
$this->isCollected = false;
8286
}
8387

8488
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
@@ -141,9 +145,6 @@ public function serialize()
141145
$this->data = array();
142146
$this->dataCount = 0;
143147
$this->isCollected = true;
144-
if (!$this->dumperIsInjected) {
145-
$this->dumper = null;
146-
}
147148

148149
return $ser;
149150
}
@@ -245,7 +246,7 @@ private function doDump(DataDumperInterface $dumper, $data, $name, $file, $line)
245246
};
246247
$contextDumper = $contextDumper->bindTo($dumper, $dumper);
247248
$contextDumper($name, $file, $line, $this->fileLinkFormat);
248-
} elseif (!$dumper instanceof ServerDumper) {
249+
} else {
249250
$cloner = new VarCloner();
250251
$dumper->dump($cloner->cloneVar($name.' on line '.$line.':'));
251252
}

src/Symfony/Component/HttpKernel/EventListener/DumpListener.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
1616
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
1717
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
18+
use Symfony\Component\VarDumper\Server\Connection;
1819
use Symfony\Component\VarDumper\VarDumper;
1920

2021
/**
@@ -26,20 +27,27 @@ class DumpListener implements EventSubscriberInterface
2627
{
2728
private $cloner;
2829
private $dumper;
30+
private $connection;
2931

30-
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper)
32+
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null)
3133
{
3234
$this->cloner = $cloner;
3335
$this->dumper = $dumper;
36+
$this->connection = $connection;
3437
}
3538

3639
public function configure()
3740
{
3841
$cloner = $this->cloner;
3942
$dumper = $this->dumper;
43+
$connection = $this->connection;
4044

41-
VarDumper::setHandler(function ($var) use ($cloner, $dumper) {
42-
$dumper->dump($cloner->cloneVar($var));
45+
VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) {
46+
$data = $cloner->cloneVar($var);
47+
48+
if (!$connection || !$connection->write($data)) {
49+
$dumper->dump($data);
50+
}
4351
});
4452
}
4553

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
1818
use Symfony\Component\VarDumper\Cloner\Data;
1919
use Symfony\Component\VarDumper\Dumper\CliDumper;
20-
use Symfony\Component\VarDumper\Dumper\ServerDumper;
20+
use Symfony\Component\VarDumper\Server\Connection;
2121

2222
/**
2323
* @author Nicolas Grekas <p@tchwork.com>
@@ -57,13 +57,13 @@ public function testDump()
5757
$this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize());
5858
}
5959

60-
public function testDumpWithServerDumper()
60+
public function testDumpWithServerConnection()
6161
{
6262
$data = new Data(array(array(123)));
6363

6464
// Server is up, server dumper is used
65-
$serverDumper = $this->getMockBuilder(ServerDumper::class)->disableOriginalConstructor()->getMock();
66-
$serverDumper->expects($this->once())->method('dump');
65+
$serverDumper = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
66+
$serverDumper->expects($this->once())->method('write')->willReturn(true);
6767

6868
$collector = new DumpDataCollector(null, null, null, null, $serverDumper);
6969
$collector->dump($data);

src/Symfony/Component/HttpKernel/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"symfony/stopwatch": "~3.4|~4.0",
3838
"symfony/templating": "~3.4|~4.0",
3939
"symfony/translation": "~3.4|~4.0",
40-
"symfony/var-dumper": "~4.1",
40+
"symfony/var-dumper": "^4.1.1",
4141
"psr/cache": "~1.0"
4242
},
4343
"provide": {
@@ -46,7 +46,7 @@
4646
"conflict": {
4747
"symfony/config": "<3.4",
4848
"symfony/dependency-injection": "<4.1",
49-
"symfony/var-dumper": "<4.1",
49+
"symfony/var-dumper": "<4.1.1",
5050
"twig/twig": "<1.34|<2.4,>=2"
5151
},
5252
"suggest": {

src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public function dump(Data $data, $output = null)
164164
*/
165165
protected function dumpLine($depth)
166166
{
167-
call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
167+
\call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
168168
$this->line = '';
169169
}
170170

src/Symfony/Component/VarDumper/Dumper/ServerDumper.php

Lines changed: 7 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\VarDumper\Cloner\Data;
1515
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
16+
use Symfony\Component\VarDumper\Server\Connection;
1617

1718
/**
1819
* ServerDumper forwards serialized Data clones to a server.
@@ -21,10 +22,8 @@
2122
*/
2223
class ServerDumper implements DataDumperInterface
2324
{
24-
private $host;
25+
private $connection;
2526
private $wrappedDumper;
26-
private $contextProviders;
27-
private $socket;
2827

2928
/**
3029
* @param string $host The server host
@@ -33,83 +32,22 @@ class ServerDumper implements DataDumperInterface
3332
*/
3433
public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = array())
3534
{
36-
if (false === strpos($host, '://')) {
37-
$host = 'tcp://'.$host;
38-
}
39-
40-
$this->host = $host;
35+
$this->connection = new Connection($host, $contextProviders);
4136
$this->wrappedDumper = $wrappedDumper;
42-
$this->contextProviders = $contextProviders;
4337
}
4438

4539
public function getContextProviders(): array
4640
{
47-
return $this->contextProviders;
41+
return $this->connection->getContextProviders();
4842
}
4943

5044
/**
5145
* {@inheritdoc}
5246
*/
53-
public function dump(Data $data, $output = null): void
54-
{
55-
set_error_handler(array(self::class, 'nullErrorHandler'));
56-
57-
$failed = false;
58-
try {
59-
if (!$this->socket = $this->socket ?: $this->createSocket()) {
60-
$failed = true;
61-
62-
return;
63-
}
64-
} finally {
65-
restore_error_handler();
66-
if ($failed && $this->wrappedDumper) {
67-
$this->wrappedDumper->dump($data);
68-
}
69-
}
70-
71-
set_error_handler(array(self::class, 'nullErrorHandler'));
72-
73-
$context = array('timestamp' => time());
74-
foreach ($this->contextProviders as $name => $provider) {
75-
$context[$name] = $provider->getContext();
76-
}
77-
$context = array_filter($context);
78-
79-
$encodedPayload = base64_encode(serialize(array($data, $context)))."\n";
80-
$failed = false;
81-
82-
try {
83-
$retry = 3;
84-
while ($retry > 0 && $failed = (-1 === stream_socket_sendto($this->socket, $encodedPayload))) {
85-
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
86-
if ($failed = !$this->socket = $this->createSocket()) {
87-
break;
88-
}
89-
90-
--$retry;
91-
}
92-
} finally {
93-
restore_error_handler();
94-
if ($failed && $this->wrappedDumper) {
95-
$this->wrappedDumper->dump($data);
96-
}
97-
}
98-
}
99-
100-
private static function nullErrorHandler()
47+
public function dump(Data $data)
10148
{
102-
// noop
103-
}
104-
105-
private function createSocket()
106-
{
107-
$socket = stream_socket_client($this->host, $errno, $errstr, 1, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT);
108-
109-
if ($socket) {
110-
stream_set_blocking($socket, false);
49+
if (!$this->connection->write($data) && $this->wrappedDumper) {
50+
$this->wrappedDumper->dump($data);
11151
}
112-
113-
return $socket;
11452
}
11553
}

0 commit comments

Comments
 (0)
0