Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a1d168

Browse files
committed
[DI] Case sensitive parameter names
1 parent eeaea83 commit 8a1d168

20 files changed

+285
-56
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* deprecated service auto-registration while autowiring
88
* deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method
99
* deprecated support for top-level anonymous services in XML
10+
* deprecated case insensitivity of parameter names
1011

1112
3.3.0
1213
-----

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

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,11 +1056,15 @@ private function addDefaultParametersMethod()
10561056

10571057
$php = array();
10581058
$dynamicPhp = array();
1059+
$normalizedParams = array();
10591060

10601061
foreach ($this->container->getParameterBag()->all() as $key => $value) {
10611062
if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) {
10621063
throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey));
10631064
}
1065+
if ($key !== $lcKey = strtolower($key)) {
1066+
$normalizedParams[] = sprintf(' %s => %s,', $this->export($lcKey), $this->export($key));
1067+
}
10641068
$export = $this->exportParameters(array($value));
10651069
$export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2);
10661070

@@ -1082,7 +1086,7 @@ private function addDefaultParametersMethod()
10821086
public function getParameter($name)
10831087
{
10841088
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
1085-
$name = strtolower($name);
1089+
$name = $this->normalizeParameterName($name);
10861090
10871091
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
10881092
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
@@ -1100,7 +1104,7 @@ public function getParameter($name)
11001104
*/
11011105
public function hasParameter($name)
11021106
{
1103-
$name = strtolower($name);
1107+
$name = $this->normalizeParameterName($name);
11041108
11051109
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
11061110
}
@@ -1170,6 +1174,26 @@ private function getDynamicParameter(\$name)
11701174
{$getDynamicParameter}
11711175
}
11721176
1177+
1178+
EOF;
1179+
1180+
$code .= ' private $normalizedParameterNames = '.($normalizedParams ? sprintf("array(\n%s\n );", implode("\n", $normalizedParams)) : 'array();')."\n";
1181+
$code .= <<<'EOF'
1182+
1183+
private function normalizeParameterName($name)
1184+
{
1185+
if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) {
1186+
$normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName;
1187+
if ((string) $name !== $normalizedName) {
1188+
@trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
1189+
}
1190+
} else {
1191+
$normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name;
1192+
}
1193+
1194+
return $normalizedName;
1195+
}
1196+
11731197
EOF;
11741198
} elseif ($dynamicPhp) {
11751199
throw new RuntimeException('You cannot dump a not-frozen container with dynamic parameters.');
@@ -1555,10 +1579,10 @@ private function dumpValue($value, $interpolate = true)
15551579
if (preg_match('/^%([^%]+)%$/', $value, $match)) {
15561580
// we do this to deal with non string values (Boolean, integer, ...)
15571581
// the preg_replace_callback converts them to strings
1558-
return $this->dumpParameter(strtolower($match[1]));
1582+
return $this->dumpParameter($match[1]);
15591583
} else {
15601584
$replaceParameters = function ($match) {
1561-
return "'.".$this->dumpParameter(strtolower($match[2])).".'";
1585+
return "'.".$this->dumpParameter($match[2]).".'";
15621586
};
15631587

15641588
$code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value)));
@@ -1604,8 +1628,6 @@ private function dumpLiteralClass($class)
16041628
*/
16051629
private function dumpParameter($name)
16061630
{
1607-
$name = strtolower($name);
1608-
16091631
if ($this->container->isCompiled() && $this->container->hasParameter($name)) {
16101632
$value = $this->container->getParameter($name);
16111633
$dumpedValue = $this->dumpValue($value, false);

src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,6 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase =
486486
$key = array_pop($keys);
487487
} else {
488488
$key = $arg->getAttribute('key');
489-
490-
// parameter keys are case insensitive
491-
if ('parameter' == $name && $lowercase) {
492-
$key = strtolower($key);
493-
}
494489
}
495490

496491
$onInvalid = $arg->getAttribute('on-invalid');

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public function resolve()
9191
parent::resolve();
9292

9393
foreach ($this->envPlaceholders as $env => $placeholders) {
94-
if (!isset($this->parameters[$name = strtolower("env($env)")])) {
94+
if (!$this->has($name = "env($env)")) {
9595
continue;
9696
}
9797
if (is_numeric($default = $this->parameters[$name])) {

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

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class ParameterBag implements ParameterBagInterface
2525
protected $parameters = array();
2626
protected $resolved = false;
2727

28+
private $normalizedNames = array();
29+
2830
/**
2931
* @param array $parameters An array of parameters
3032
*/
@@ -49,7 +51,7 @@ public function clear()
4951
public function add(array $parameters)
5052
{
5153
foreach ($parameters as $key => $value) {
52-
$this->parameters[strtolower($key)] = $value;
54+
$this->set($key, $value);
5355
}
5456
}
5557

@@ -66,7 +68,7 @@ public function all()
6668
*/
6769
public function get($name)
6870
{
69-
$name = strtolower($name);
71+
$name = $this->normalizeName($name);
7072

7173
if (!array_key_exists($name, $this->parameters)) {
7274
if (!$name) {
@@ -111,15 +113,15 @@ public function get($name)
111113
*/
112114
public function set($name, $value)
113115
{
114-
$this->parameters[strtolower($name)] = $value;
116+
$this->parameters[$this->normalizeName($name)] = $value;
115117
}
116118

117119
/**
118120
* {@inheritdoc}
119121
*/
120122
public function has($name)
121123
{
122-
return array_key_exists(strtolower($name), $this->parameters);
124+
return array_key_exists($this->normalizeName($name), $this->parameters);
123125
}
124126

125127
/**
@@ -129,7 +131,7 @@ public function has($name)
129131
*/
130132
public function remove($name)
131133
{
132-
unset($this->parameters[strtolower($name)]);
134+
unset($this->parameters[$this->normalizeName($name)]);
133135
}
134136

135137
/**
@@ -206,7 +208,7 @@ public function resolveString($value, array $resolving = array())
206208
// a non-string in a parameter value
207209
if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
208210
$key = $match[1];
209-
$lcKey = strtolower($key);
211+
$lcKey = strtolower($key); // strtolower() to be removed in 4.0
210212

211213
if (isset($resolving[$lcKey])) {
212214
throw new ParameterCircularReferenceException(array_keys($resolving));
@@ -224,7 +226,7 @@ public function resolveString($value, array $resolving = array())
224226
}
225227

226228
$key = $match[1];
227-
$lcKey = strtolower($key);
229+
$lcKey = strtolower($key); // strtolower() to be removed in 4.0
228230
if (isset($resolving[$lcKey])) {
229231
throw new ParameterCircularReferenceException(array_keys($resolving));
230232
}
@@ -288,4 +290,18 @@ public function unescapeValue($value)
288290

289291
return $value;
290292
}
293+
294+
private function normalizeName($name)
295+
{
296+
if (isset($this->normalizedNames[$normalizedName = strtolower($name)])) {
297+
$normalizedName = $this->normalizedNames[$normalizedName];
298+
if ((string) $name !== $normalizedName) {
299+
@trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
300+
}
301+
} else {
302+
$normalizedName = $this->normalizedNames[$normalizedName] = (string) $name;
303+
}
304+
305+
return $normalizedName;
306+
}
291307
}

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,21 @@ public function testPrivateServiceTriggersDeprecation()
11031103

11041104
$container->get('bar');
11051105
}
1106+
1107+
/**
1108+
* @group legacy
1109+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4.
1110+
*/
1111+
public function testParameterWithMixedCase()
1112+
{
1113+
$container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
1114+
$container->register('foo', 'stdClass')
1115+
->setProperty('foo', '%FOO%');
1116+
1117+
$container->compile();
1118+
1119+
$this->assertSame('bar', $container->get('foo')->foo);
1120+
}
11061121
}
11071122

11081123
class FooClass

src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,6 @@ public function testGetSetParameter()
125125
$sc->setParameter('foo', 'baz');
126126
$this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter');
127127

128-
$sc->setParameter('Foo', 'baz1');
129-
$this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase');
130-
$this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase');
131-
132128
try {
133129
$sc->getParameter('baba');
134130
$this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist');
@@ -138,6 +134,20 @@ public function testGetSetParameter()
138134
}
139135
}
140136

137+
/**
138+
* @group legacy
139+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4.
140+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4.
141+
*/
142+
public function testGetSetParameterWithMixedCase()
143+
{
144+
$sc = new Container(new ParameterBag(array('foo' => 'bar')));
145+
146+
$sc->setParameter('Foo', 'baz1');
147+
$this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase');
148+
$this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase');
149+
}
150+
141151
public function testGetServiceIds()
142152
{
143153
$sc = new Container();

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,4 +670,43 @@ public function testPrivateServiceTriggersDeprecation()
670670

671671
$container->get('bar');
672672
}
673+
674+
/**
675+
* @group legacy
676+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since version 3.4.
677+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "Foo" is deprecated since version 3.4.
678+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "bar" instead of "BAR" is deprecated since version 3.4.
679+
*/
680+
public function testParameterWithMixedCase()
681+
{
682+
$container = new ContainerBuilder(new ParameterBag(array('Foo' => 'bar', 'BAR' => 'foo')));
683+
$container->compile();
684+
685+
$dumper = new PhpDumper($container);
686+
eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case')));
687+
688+
$container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case();
689+
690+
$this->assertSame('bar', $container->getParameter('foo'));
691+
$this->assertSame('bar', $container->getParameter('FOO'));
692+
$this->assertSame('foo', $container->getParameter('bar'));
693+
$this->assertSame('foo', $container->getParameter('BAR'));
694+
}
695+
696+
/**
697+
* @group legacy
698+
* @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4.
699+
*/
700+
public function testParameterWithLowerCase()
701+
{
702+
$container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
703+
$container->compile();
704+
705+
$dumper = new PhpDumper($container);
706+
eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case')));
707+
708+
$container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case();
709+
710+
$this->assertSame('bar', $container->getParameter('FOO'));
711+
}
673712
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
55

66
$container = new ContainerBuilder(new ParameterBag(array(
7-
'FOO' => '%baz%',
7+
'foo' => '%baz%',
88
'baz' => 'bar',
99
'bar' => 'foo is %%foo bar',
1010
'escape' => '@escapeme',

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ protected function getTestService()
7878
public function getParameter($name)
7979
{
8080
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
81-
$name = strtolower($name);
81+
$name = $this->normalizeParameterName($name);
8282

8383
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
8484
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
@@ -96,7 +96,7 @@ public function getParameter($name)
9696
*/
9797
public function hasParameter($name)
9898
{
99-
$name = strtolower($name);
99+
$name = $this->normalizeParameterName($name);
100100

101101
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
102102
}
@@ -142,6 +142,22 @@ private function getDynamicParameter($name)
142142
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
143143
}
144144

145+
private $normalizedParameterNames = array();
146+
147+
private function normalizeParameterName($name)
148+
{
149+
if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) {
150+
$normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName;
151+
if ((string) $name !== $normalizedName) {
152+
@trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
153+
}
154+
} else {
155+
$normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name;
156+
}
157+
158+
return $normalizedName;
159+
}
160+
145161
/**
146162
* Gets the default parameters.
147163
*

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ protected function getTestService()
8282
public function getParameter($name)
8383
{
8484
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
85-
$name = strtolower($name);
85+
$name = $this->normalizeParameterName($name);
8686

8787
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
8888
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
@@ -100,7 +100,7 @@ public function getParameter($name)
100100
*/
101101
public function hasParameter($name)
102102
{
103-
$name = strtolower($name);
103+
$name = $this->normalizeParameterName($name);
104104

105105
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
106106
}
@@ -156,6 +156,22 @@ private function getDynamicParameter($name)
156156
return $this->dynamicParameters[$name] = $value;
157157
}
158158

159+
private $normalizedParameterNames = array();
160+
161+
private function normalizeParameterName($name)
162+
{
163+
if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) {
164+
$normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName;
165+
if ((string) $name !== $normalizedName) {
166+
@trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
167+
}
168+
} else {
169+
$normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name;
170+
}
171+
172+
return $normalizedName;
173+
}
174+
159175
/**
160176
* Gets the default parameters.
161177
*

0 commit comments

Comments
 (0)