Skip to content

Commit c871857

Browse files
Merge branch '4.1'
* 4.1: [VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper [HttpKernel] fix argument's error messages in ServiceValueResolver [DI] Avoid leaking unused env placeholders
2 parents df44236 + ac74c9a commit c871857

File tree

19 files changed

+315
-128
lines changed

19 files changed

+315
-128
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/DependencyInjection/Compiler/ValidateEnvPlaceholdersPass.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ public function process(ContainerBuilder $container)
8484
} finally {
8585
BaseNode::resetPlaceholders();
8686
}
87+
88+
$resolvingBag->clearUnusedEnvPlaceholders();
8789
}
8890

8991
private static function getType($value): string

src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public function getUnusedEnvPlaceholders(): array
8787
return $this->unusedEnvPlaceholders;
8888
}
8989

90+
public function clearUnusedEnvPlaceholders()
91+
{
92+
$this->unusedEnvPlaceholders = array();
93+
}
94+
9095
/**
9196
* Merges the env placeholders of another EnvPlaceholderParameterBag.
9297
*/

src/Symfony/Component/DependencyInjection/Tests/Compiler/ValidateEnvPlaceholdersPassTest.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,29 @@ public function testEnvWithVariableNode(): void
226226
public function testConfigurationWithoutRootNode(): void
227227
{
228228
$container = new ContainerBuilder();
229-
$container->registerExtension($ext = new EnvExtension(new EnvConfigurationWithoutRootNode()));
229+
$container->registerExtension(new EnvExtension(new EnvConfigurationWithoutRootNode()));
230230
$container->loadFromExtension('env_extension');
231231

232232
$this->doProcess($container);
233233

234234
$this->addToAssertionCount(1);
235235
}
236236

237+
public function testDiscardedEnvInConfig(): void
238+
{
239+
$container = new ContainerBuilder();
240+
$container->setParameter('env(BOOLISH)', '1');
241+
$container->setParameter('boolish', '%env(BOOLISH)%');
242+
$container->registerExtension(new EnvExtension());
243+
$container->prependExtensionConfig('env_extension', array(
244+
'array_node' => array('bool_force_cast' => '%boolish%'),
245+
));
246+
247+
$container->compile(true);
248+
249+
$this->assertSame('1', $container->getParameter('boolish'));
250+
}
251+
237252
private function doProcess(ContainerBuilder $container): void
238253
{
239254
(new MergeExtensionConfigurationPass())->process($container);
@@ -260,8 +275,19 @@ public function getConfigTreeBuilder()
260275
->ifTrue(function ($value) { return !is_array($value); })
261276
->then(function ($value) { return array('child_node' => $value); })
262277
->end()
278+
->beforeNormalization()
279+
->ifArray()
280+
->then(function (array $v) {
281+
if (isset($v['bool_force_cast'])) {
282+
$v['bool_force_cast'] = (bool) $v['bool_force_cast'];
283+
}
284+
285+
return $v;
286+
})
287+
->end()
263288
->children()
264289
->scalarNode('child_node')->end()
290+
->booleanNode('bool_force_cast')->end()
265291
->integerNode('int_unset_at_zero')
266292
->validate()
267293
->ifTrue(function ($value) { return 0 === $value; })

src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function resolve(Request $request, ArgumentMetadata $argument)
6868
yield $this->container->get($controller)->get($argument->getName());
6969
} catch (RuntimeException $e) {
7070
$what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller);
71-
$message = preg_replace('/service "service_locator\.[^"]++"/', $what, $e->getMessage());
71+
$message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage());
7272

7373
if ($e->getMessage() === $message) {
7474
$message = sprintf('Cannot resolve %s: %s', $what, $message);

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/Controller/ArgumentResolver/ServiceValueResolverTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
1516
use Symfony\Component\DependencyInjection\ServiceLocator;
1617
use Symfony\Component\HttpFoundation\Request;
1718
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver;
1819
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
20+
use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
1921

2022
class ServiceValueResolverTest extends TestCase
2123
{
@@ -85,6 +87,25 @@ public function testControllerNameIsAnArray()
8587
$this->assertYieldEquals(array(new DummyService()), $resolver->resolve($request, $argument));
8688
}
8789

90+
/**
91+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
92+
* @expectedExceptionMessage Cannot autowire argument $dummy of "Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver\DummyController::index()": it references class "Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver\DummyService" but no such service exists.
93+
*/
94+
public function testErrorIsTruncated()
95+
{
96+
$container = new ContainerBuilder();
97+
$container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
98+
99+
$container->register('argument_resolver.service', ServiceValueResolver::class)->addArgument(null)->setPublic(true);
100+
$container->register(DummyController::class)->addTag('controller.service_arguments')->setPublic(true);
101+
102+
$container->compile();
103+
104+
$request = $this->requestWithAttributes(array('_controller' => array(DummyController::class, 'index')));
105+
$argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null);
106+
$container->get('argument_resolver.service')->resolve($request, $argument)->current();
107+
}
108+
88109
private function requestWithAttributes(array $attributes)
89110
{
90111
$request = Request::create('/');
@@ -110,3 +131,10 @@ private function assertYieldEquals(array $expected, \Generator $generator)
110131
class DummyService
111132
{
112133
}
134+
135+
class DummyController
136+
{
137+
public function index(DummyService $dummy)
138+
{
139+
}
140+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy