Skip to content

Commit 4324804

Browse files
Merge branch '3.3' into 3.4
* 3.3: [DI] Handle root namespace in service definitions Use rawurlencode() to transform the Cookie into a string [Process] Fix parsing args on Windows [HttpKernel][VarDumper] Truncate profiler data & optim perf [Security] Fix authentication.failure event not dispatched on AccountStatusException
2 parents ab8ac13 + 6b5d35f commit 4324804

File tree

16 files changed

+196
-101
lines changed

16 files changed

+196
-101
lines changed

src/Symfony/Component/BrowserKit/Cookie.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function __construct($name, $value, $expires = null, $path = null, $domai
6262
$this->rawValue = $value;
6363
} else {
6464
$this->value = $value;
65-
$this->rawValue = urlencode($value);
65+
$this->rawValue = rawurlencode($value);
6666
}
6767
$this->name = $name;
6868
$this->path = empty($path) ? '/' : $path;

src/Symfony/Component/BrowserKit/Tests/CookieTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@
1616

1717
class CookieTest extends TestCase
1818
{
19+
public function testToString()
20+
{
21+
$cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
22+
$this->assertEquals('foo=bar; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
23+
24+
$cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
25+
$this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
26+
27+
$cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
28+
$this->assertEquals('foo=; expires=Thu, 01 Jan 1970 00:00:01 GMT; domain=.myfoodomain.com; path=/admin/; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
29+
30+
$cookie = new Cookie('foo', 'bar', 0, '/', '');
31+
$this->assertEquals('foo=bar; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; httponly', (string) $cookie);
32+
}
33+
1934
/**
2035
* @dataProvider getTestsForToFromString
2136
*/

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -397,15 +397,9 @@ private function addServiceReturn($id, $isSimpleInstance)
397397
*/
398398
private function addServiceInstance($id, Definition $definition, $isSimpleInstance)
399399
{
400-
$class = $definition->getClass();
401-
402-
if ('\\' === substr($class, 0, 1)) {
403-
$class = substr($class, 1);
404-
}
405-
406-
$class = $this->dumpValue($class);
400+
$class = $this->dumpValue($definition->getClass());
407401

408-
if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
402+
if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
409403
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
410404
}
411405

@@ -1566,11 +1560,13 @@ private function dumpLiteralClass($class)
15661560
if (false !== strpos($class, '$')) {
15671561
return sprintf('${($_ = %s) && false ?: "_"}', $class);
15681562
}
1569-
if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
1563+
if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
15701564
throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
15711565
}
15721566

1573-
return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1);
1567+
$class = substr(str_replace('\\\\', '\\', $class), 1, -1);
1568+
1569+
return 0 === strpos($class, '\\') ? $class : '\\'.$class;
15741570
}
15751571

15761572
/**

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,18 @@ public function testArrayParameters()
598598

599599
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace('\\\\Dumper', '/Dumper', $dumper->dump(array('file' => self::$fixturesPath.'/php/services_array_params.php'))));
600600
}
601+
602+
public function testDumpHandlesLiteralClassWithRootNamespace()
603+
{
604+
$container = new ContainerBuilder();
605+
$container->register('foo', '\\stdClass');
606+
$container->compile();
607+
608+
$dumper = new PhpDumper($container);
609+
eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace')));
610+
611+
$container = new \Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace();
612+
613+
$this->assertInstanceOf('stdClass', $container->get('foo'));
614+
}
601615
}

src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php

Lines changed: 25 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@
2020
use Symfony\Component\Validator\ConstraintViolationInterface;
2121
use Symfony\Component\VarDumper\Caster\Caster;
2222
use Symfony\Component\VarDumper\Caster\ClassStub;
23-
use Symfony\Component\VarDumper\Caster\CutStub;
24-
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
25-
use Symfony\Component\VarDumper\Cloner\Data;
2623
use Symfony\Component\VarDumper\Cloner\Stub;
27-
use Symfony\Component\VarDumper\Cloner\VarCloner;
2824

2925
/**
3026
* Data collector for {@link FormInterface} instances.
@@ -77,11 +73,6 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
7773
*/
7874
private $valueExporter;
7975

80-
/**
81-
* @var ClonerInterface
82-
*/
83-
private $cloner;
84-
8576
private $hasVarDumper;
8677

8778
public function __construct(FormDataExtractorInterface $dataExtractor)
@@ -255,61 +246,33 @@ public function serialize()
255246
/**
256247
* {@inheritdoc}
257248
*/
258-
protected function cloneVar($var, $isClass = false)
249+
protected function getCasters()
259250
{
260-
if ($var instanceof Data) {
261-
return $var;
262-
}
263-
if (null === $this->cloner) {
264-
if ($this->hasVarDumper) {
265-
$this->cloner = new VarCloner();
266-
$this->cloner->setMaxItems(-1);
267-
$this->cloner->addCasters(array(
268-
'*' => function ($v, array $a, Stub $s, $isNested) {
269-
foreach ($a as &$v) {
270-
if (is_object($v) && !$v instanceof \DateTimeInterface) {
271-
$v = new CutStub($v);
272-
}
273-
}
274-
275-
return $a;
276-
},
277-
\Exception::class => function (\Exception $e, array $a, Stub $s) {
278-
if (isset($a[$k = "\0Exception\0previous"])) {
279-
unset($a[$k]);
280-
++$s->cut;
281-
}
282-
283-
return $a;
284-
},
285-
FormInterface::class => function (FormInterface $f, array $a) {
286-
return array(
287-
Caster::PREFIX_VIRTUAL.'name' => $f->getName(),
288-
Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())),
289-
);
290-
},
291-
ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) {
292-
return array(
293-
Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(),
294-
Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(),
295-
Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(),
296-
);
297-
},
298-
));
299-
} else {
300-
@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);
301-
$this->cloner = false;
302-
}
303-
}
304-
if (false !== $this->cloner) {
305-
return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE);
306-
}
307-
308-
if (null === $this->valueExporter) {
309-
$this->valueExporter = new ValueExporter();
310-
}
251+
return parent::getCasters() + array(
252+
\Exception::class => function (\Exception $e, array $a, Stub $s) {
253+
foreach (array("\0Exception\0previous", "\0Exception\0trace") as $k) {
254+
if (isset($a[$k])) {
255+
unset($a[$k]);
256+
++$s->cut;
257+
}
258+
}
311259

312-
return $this->valueExporter->exportValue($var);
260+
return $a;
261+
},
262+
FormInterface::class => function (FormInterface $f, array $a) {
263+
return array(
264+
Caster::PREFIX_VIRTUAL.'name' => $f->getName(),
265+
Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())),
266+
);
267+
},
268+
ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) {
269+
return array(
270+
Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(),
271+
Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(),
272+
Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(),
273+
);
274+
},
275+
);
313276
}
314277

315278
private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash)

src/Symfony/Component/Form/composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"symfony/dependency-injection": "~3.3|~4.0",
3030
"symfony/config": "~2.7|~3.0|~4.0",
3131
"symfony/http-foundation": "~2.8|~3.0|~4.0",
32-
"symfony/http-kernel": "~2.8|~3.0|~4.0",
32+
"symfony/http-kernel": "^3.3.5|~4.0",
3333
"symfony/security-csrf": "~2.8|~3.0|~4.0",
3434
"symfony/translation": "~2.8|~3.0|~4.0",
3535
"symfony/var-dumper": "~3.3|~4.0"
@@ -39,8 +39,8 @@
3939
"symfony/dependency-injection": "<3.3",
4040
"symfony/doctrine-bridge": "<2.7",
4141
"symfony/framework-bundle": "<2.7",
42-
"symfony/twig-bridge": "<2.7",
43-
"symfony/var-dumper": "<3.3"
42+
"symfony/http-kernel": "<3.3.5",
43+
"symfony/twig-bridge": "<2.7"
4444
},
4545
"suggest": {
4646
"symfony/validator": "For form validation.",

src/Symfony/Component/HttpFoundation/Cookie.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public function __toString()
145145
if ('' === (string) $this->getValue()) {
146146
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001';
147147
} else {
148-
$str .= $this->isRaw() ? $this->getValue() : urlencode($this->getValue());
148+
$str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue());
149149

150150
if (0 !== $this->getExpiresTime()) {
151151
$str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; max-age='.$this->getMaxAge();

src/Symfony/Component/HttpFoundation/Tests/CookieTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ public function testToString()
164164
$cookie = new Cookie('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
165165
$this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; max-age='.($expire - time()).'; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
166166

167+
$cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
168+
$this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
169+
167170
$cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
168171
$this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; max-age='.($expire - time()).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
169172

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

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
namespace Symfony\Component\HttpKernel\DataCollector;
1313

1414
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
15-
use Symfony\Component\VarDumper\Caster\ClassStub;
15+
use Symfony\Component\VarDumper\Caster\CutStub;
1616
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
1717
use Symfony\Component\VarDumper\Cloner\Data;
18+
use Symfony\Component\VarDumper\Cloner\Stub;
1819
use Symfony\Component\VarDumper\Cloner\VarCloner;
1920

2021
/**
@@ -37,7 +38,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
3738
/**
3839
* @var ClonerInterface
3940
*/
40-
private static $cloner;
41+
private $cloner;
4142

4243
public function serialize()
4344
{
@@ -61,24 +62,28 @@ public function unserialize($data)
6162
*/
6263
protected function cloneVar($var)
6364
{
64-
if (null === self::$cloner) {
65-
if (class_exists(ClassStub::class)) {
66-
self::$cloner = new VarCloner();
67-
self::$cloner->setMaxItems(-1);
65+
if ($var instanceof Data) {
66+
return $var;
67+
}
68+
if (null === $this->cloner) {
69+
if (class_exists(CutStub::class)) {
70+
$this->cloner = new VarCloner();
71+
$this->cloner->setMaxItems(-1);
72+
$this->cloner->addCasters(self::getCasters());
6873
} else {
6974
@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);
70-
self::$cloner = false;
75+
$this->cloner = false;
7176
}
7277
}
73-
if (false === self::$cloner) {
78+
if (false === $this->cloner) {
7479
if (null === $this->valueExporter) {
7580
$this->valueExporter = new ValueExporter();
7681
}
7782

7883
return $this->valueExporter->exportValue($var);
7984
}
8085

81-
return self::$cloner->cloneVar($var);
86+
return $this->cloner->cloneVar($var);
8287
}
8388

8489
/**
@@ -100,4 +105,24 @@ protected function varToString($var)
100105

101106
return $this->valueExporter->exportValue($var);
102107
}
108+
109+
/**
110+
* @return callable[] The casters to add to the cloner
111+
*/
112+
protected function getCasters()
113+
{
114+
return array(
115+
'*' => function ($v, array $a, Stub $s, $isNested) {
116+
if (!$v instanceof Stub) {
117+
foreach ($a as $k => $v) {
118+
if (is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) {
119+
$a[$k] = new CutStub($v);
120+
}
121+
}
122+
}
123+
124+
return $a;
125+
},
126+
);
127+
}
103128
}

src/Symfony/Component/Process/Process.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,14 +1633,17 @@ private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env
16331633
$varCount = 0;
16341634
$varCache = array();
16351635
$cmd = preg_replace_callback(
1636-
'/"(
1636+
'/"(?:(
16371637
[^"%!^]*+
16381638
(?:
16391639
(?: !LF! | "(?:\^[%!^])?+" )
16401640
[^"%!^]*+
16411641
)++
1642-
)"/x',
1642+
) | [^"]*+ )"/x',
16431643
function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) {
1644+
if (!isset($m[1])) {
1645+
return $m[0];
1646+
}
16441647
if (isset($varCache[$m[0]])) {
16451648
return $varCache[$m[0]];
16461649
}

0 commit comments

Comments
 (0)