Skip to content

Commit d1a186c

Browse files
committed
[HttpKernel] Use VarDumper in the profiler
1 parent ba4fa98 commit d1a186c

File tree

8 files changed

+121
-19
lines changed

8 files changed

+121
-19
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.2.0
5+
-----
6+
7+
* deprecated `DataCollector::varToString()`, use `cloneVar()` instead
8+
49
3.1.0
510
-----
611
* deprecated passing objects as URI attributes to the ESI and SSI renderers

DataCollector/DataCollector.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
namespace Symfony\Component\HttpKernel\DataCollector;
1313

1414
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
15+
use Symfony\Component\VarDumper\Caster\ClassStub;
16+
use Symfony\Component\VarDumper\Caster\LinkStub;
17+
use Symfony\Component\VarDumper\Caster\StubCaster;
18+
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
19+
use Symfony\Component\VarDumper\Cloner\Data;
20+
use Symfony\Component\VarDumper\Cloner\Stub;
21+
use Symfony\Component\VarDumper\Cloner\VarCloner;
1522

1623
/**
1724
* DataCollector.
@@ -30,6 +37,11 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
3037
*/
3138
private $valueExporter;
3239

40+
/**
41+
* @var ClonerInterface
42+
*/
43+
private $cloner;
44+
3345
public function serialize()
3446
{
3547
return serialize($this->data);
@@ -40,19 +52,88 @@ public function unserialize($data)
4052
$this->data = unserialize($data);
4153
}
4254

55+
/**
56+
* Converts the variable into a serializable Data instance.
57+
*
58+
* This array can be displayed in the template using
59+
* the VarDumper component.
60+
*
61+
* @param mixed $var
62+
*
63+
* @return Data
64+
*/
65+
protected function cloneVar($var)
66+
{
67+
if (null === $this->cloner) {
68+
if (class_exists(ClassStub::class)) {
69+
$this->cloner = new VarCloner();
70+
$this->cloner->addCasters(array(
71+
Stub::class => function (Stub $v, array $a, Stub $s, $isNested) {
72+
return $isNested ? $a : StubCaster::castStub($v, $a, $s, true);
73+
},
74+
));
75+
} else {
76+
@trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED);
77+
$this->cloner = false;
78+
}
79+
}
80+
if (false === $this->cloner) {
81+
if (null === $this->valueExporter) {
82+
$this->valueExporter = new ValueExporter();
83+
}
84+
85+
return $this->valueExporter->exportValue($var);
86+
}
87+
88+
return $this->cloner->cloneVar($this->decorateVar($var));
89+
}
90+
4391
/**
4492
* Converts a PHP variable to a string.
4593
*
4694
* @param mixed $var A PHP variable
4795
*
4896
* @return string The string representation of the variable
97+
*
98+
* @deprecated Deprecated since version 3.2, to be removed in 4.0. Use cloneVar() instead.
4999
*/
50100
protected function varToString($var)
51101
{
102+
@trigger_error(sprintf('The %() method is deprecated since version 3.2 and will be removed in 4.0. Use cloneVar() instead.', __METHOD__), E_USER_DEPRECATED);
103+
52104
if (null === $this->valueExporter) {
53105
$this->valueExporter = new ValueExporter();
54106
}
55107

56108
return $this->valueExporter->exportValue($var);
57109
}
110+
111+
private function decorateVar($var)
112+
{
113+
if (is_array($var)) {
114+
if (isset($var[0], $var[1]) && is_callable($var)) {
115+
return ClassStub::wrapCallable($var);
116+
}
117+
foreach ($var as $k => $v) {
118+
if ($v !== $d = $this->decorateVar($v)) {
119+
$var[$k] = $d;
120+
}
121+
}
122+
123+
return $var;
124+
}
125+
if (is_string($var)) {
126+
if (false !== strpos($var, '\\')) {
127+
$c = (false !== $i = strpos($var, '::')) ? substr($var, 0, $i) : $var;
128+
if (class_exists($c, false) || interface_exists($c, false) || trait_exists($c, false)) {
129+
return new ClassStub($var);
130+
}
131+
}
132+
if (false !== strpos($var, DIRECTORY_SEPARATOR) && file_exists($var)) {
133+
return new LinkStub($var);
134+
}
135+
}
136+
137+
return $var;
138+
}
58139
}

DataCollector/RequestDataCollector.php

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,16 @@ public function collect(Request $request, Response $response, \Exception $except
5252

5353
// attributes are serialized and as they can be anything, they need to be converted to strings.
5454
$attributes = array();
55+
$route = '';
5556
foreach ($request->attributes->all() as $key => $value) {
5657
if ('_route' === $key && is_object($value)) {
57-
$attributes[$key] = $this->varToString($value->getPath());
58-
} elseif ('_route_params' === $key) {
59-
// we need to keep route params as an array (see getRouteParams())
60-
foreach ($value as $k => $v) {
61-
$value[$k] = $this->varToString($v);
62-
}
63-
$attributes[$key] = $value;
58+
$attributes[$key] = $this->cloneVar($value->getPath());
6459
} else {
65-
$attributes[$key] = $this->varToString($value);
60+
$attributes[$key] = $this->cloneVar($value);
61+
}
62+
63+
if ('_route' === $key) {
64+
$route = is_object($value) ? $value->getPath() : $value;
6665
}
6766
}
6867

@@ -98,12 +97,13 @@ public function collect(Request $request, Response $response, \Exception $except
9897
'content_type' => $response->headers->get('Content-Type', 'text/html'),
9998
'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
10099
'status_code' => $statusCode,
101-
'request_query' => $request->query->all(),
102-
'request_request' => $request->request->all(),
100+
'request_query' => array_map(array($this, 'cloneVar'), $request->query->all()),
101+
'request_request' => array_map(array($this, 'cloneVar'), $request->request->all()),
103102
'request_headers' => $request->headers->all(),
104103
'request_server' => $request->server->all(),
105104
'request_cookies' => $request->cookies->all(),
106105
'request_attributes' => $attributes,
106+
'route' => $route,
107107
'response_headers' => $responseHeaders,
108108
'session_metadata' => $sessionMetadata,
109109
'session_attributes' => $sessionAttributes,
@@ -247,7 +247,12 @@ public function getLocale()
247247
*/
248248
public function getRoute()
249249
{
250-
return isset($this->data['request_attributes']['_route']) ? $this->data['request_attributes']['_route'] : '';
250+
return $this->data['route'];
251+
}
252+
253+
public function getIdentifier()
254+
{
255+
return $this->data['route'] ?: (is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
251256
}
252257

253258
/**
@@ -259,7 +264,7 @@ public function getRoute()
259264
*/
260265
public function getRouteParams()
261266
{
262-
return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : array();
267+
return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : $this->cloneVar(array());
263268
}
264269

265270
/**

DataCollector/Util/ValueExporter.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111

1212
namespace Symfony\Component\HttpKernel\DataCollector\Util;
1313

14+
@trigger_error('The '.__NAMESPACE__.'\ValueExporter class is deprecated since version 3.2 and will be removed in 4.0. Use the VarDumper component instead.', E_USER_DEPRECATED);
15+
1416
/**
1517
* @author Bernhard Schussek <[email protected]>
18+
*
19+
* @deprecated since version 3.2, to be removed in 4.0. Use the VarDumper component instead.
1620
*/
1721
class ValueExporter
1822
{

Tests/DataCollector/DumpDataCollectorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function testCollectHtml()
8282
$line = __LINE__ - 1;
8383
$file = __FILE__;
8484
$xOutput = <<<EOTXT
85-
<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>:
85+
<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>:
8686
<span class=sf-dump-num>123</span>
8787
</pre>
8888

Tests/DataCollector/RequestDataCollectorTest.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@
2323
use Symfony\Component\HttpFoundation\Response;
2424
use Symfony\Component\HttpFoundation\Cookie;
2525
use Symfony\Component\EventDispatcher\EventDispatcher;
26+
use Symfony\Component\VarDumper\Cloner\Data;
27+
use Symfony\Component\VarDumper\Cloner\VarCloner;
2628

2729
class RequestDataCollectorTest extends \PHPUnit_Framework_TestCase
2830
{
2931
public function testCollect()
3032
{
3133
$c = new RequestDataCollector();
3234

33-
$c->collect($this->createRequest(), $this->createResponse());
35+
$c->collect($request = $this->createRequest(), $this->createResponse());
3436

37+
$cloner = new VarCloner();
3538
$attributes = $c->getRequestAttributes();
3639

3740
$this->assertSame('request', $c->getName());
@@ -42,12 +45,12 @@ public function testCollect()
4245
$this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestRequest());
4346
$this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestQuery());
4447
$this->assertSame('html', $c->getFormat());
45-
$this->assertSame('foobar', $c->getRoute());
46-
$this->assertSame(array('name' => 'foo'), $c->getRouteParams());
48+
$this->assertEquals('foobar', $c->getRoute());
49+
$this->assertEquals($cloner->cloneVar(array('name' => 'foo')), $c->getRouteParams());
4750
$this->assertSame(array(), $c->getSessionAttributes());
4851
$this->assertSame('en', $c->getLocale());
49-
$this->assertRegExp('/Resource\(stream#\d+\)/', $attributes->get('resource'));
50-
$this->assertSame('Object(stdClass)', $attributes->get('object'));
52+
$this->assertEquals($cloner->cloneVar($request->attributes->get('resource')), $attributes->get('resource'));
53+
$this->assertEquals($cloner->cloneVar($request->attributes->get('object')), $attributes->get('object'));
5154

5255
$this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag', $c->getResponseHeaders());
5356
$this->assertSame('OK', $c->getStatusText());

Tests/DataCollector/Util/ValueExporterTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
1515

16+
/**
17+
* @group legacy
18+
*/
1619
class ValueExporterTest extends \PHPUnit_Framework_TestCase
1720
{
1821
/**

Tests/Profiler/ProfilerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpKernel\Profiler\Profiler;
1717
use Symfony\Component\HttpFoundation\Request;
1818
use Symfony\Component\HttpFoundation\Response;
19+
use Symfony\Component\VarDumper\Cloner\Data;
1920

2021
class ProfilerTest extends \PHPUnit_Framework_TestCase
2122
{
@@ -35,7 +36,7 @@ public function testCollect()
3536

3637
$this->assertSame(204, $profile->getStatusCode());
3738
$this->assertSame('GET', $profile->getMethod());
38-
$this->assertEquals(array('foo' => 'bar'), $profiler->get('request')->getRequestQuery()->all());
39+
$this->assertInstanceOf(Data::class, $profiler->get('request')->getRequestQuery()->all()['foo']);
3940
}
4041

4142
public function testFindWorksWithDates()

0 commit comments

Comments
 (0)