diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 1fc26be27ea14..49e140de11796 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * deprecated service auto-registration while autowiring * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method * deprecated support for top-level anonymous services in XML + * deprecated case insensitivity of parameter names 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index cdcea02ed19d0..8a33b698c3bc2 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1056,11 +1056,15 @@ private function addDefaultParametersMethod() $php = array(); $dynamicPhp = array(); + $normalizedParams = array(); foreach ($this->container->getParameterBag()->all() as $key => $value) { if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) { throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey)); } + if ($key !== $lcKey = strtolower($key)) { + $normalizedParams[] = sprintf(' %s => %s,', $this->export($lcKey), $this->export($key)); + } $export = $this->exportParameters(array($value)); $export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2); @@ -1082,7 +1086,7 @@ private function addDefaultParametersMethod() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -1100,7 +1104,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -1170,6 +1174,26 @@ private function getDynamicParameter(\$name) {$getDynamicParameter} } + +EOF; + + $code .= ' private $normalizedParameterNames = '.($normalizedParams ? sprintf("array(\n%s\n );", implode("\n", $normalizedParams)) : 'array();')."\n"; + $code .= <<<'EOF' + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + EOF; } elseif ($dynamicPhp) { throw new RuntimeException('You cannot dump a not-frozen container with dynamic parameters.'); @@ -1555,10 +1579,10 @@ private function dumpValue($value, $interpolate = true) if (preg_match('/^%([^%]+)%$/', $value, $match)) { // we do this to deal with non string values (Boolean, integer, ...) // the preg_replace_callback converts them to strings - return $this->dumpParameter(strtolower($match[1])); + return $this->dumpParameter($match[1]); } else { $replaceParameters = function ($match) { - return "'.".$this->dumpParameter(strtolower($match[2])).".'"; + return "'.".$this->dumpParameter($match[2]).".'"; }; $code = str_replace('%%', '%', preg_replace_callback('/(?export($value))); @@ -1604,8 +1628,6 @@ private function dumpLiteralClass($class) */ private function dumpParameter($name) { - $name = strtolower($name); - if ($this->container->isCompiled() && $this->container->hasParameter($name)) { $value = $this->container->getParameter($name); $dumpedValue = $this->dumpValue($value, false); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index ebdc83d733c5f..69411114735f6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -486,11 +486,6 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase = $key = array_pop($keys); } else { $key = $arg->getAttribute('key'); - - // parameter keys are case insensitive - if ('parameter' == $name && $lowercase) { - $key = strtolower($key); - } } $onInvalid = $arg->getAttribute('on-invalid'); diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index d20e53531aa3b..fd859068be33c 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -91,7 +91,7 @@ public function resolve() parent::resolve(); foreach ($this->envPlaceholders as $env => $placeholders) { - if (!isset($this->parameters[$name = strtolower("env($env)")])) { + if (!$this->has($name = "env($env)")) { continue; } if (is_numeric($default = $this->parameters[$name])) { diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php index 83ba7e7076fc1..1a9ca6fa4d4fb 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php @@ -25,6 +25,8 @@ class ParameterBag implements ParameterBagInterface protected $parameters = array(); protected $resolved = false; + private $normalizedNames = array(); + /** * @param array $parameters An array of parameters */ @@ -49,7 +51,7 @@ public function clear() public function add(array $parameters) { foreach ($parameters as $key => $value) { - $this->parameters[strtolower($key)] = $value; + $this->set($key, $value); } } @@ -66,7 +68,7 @@ public function all() */ public function get($name) { - $name = strtolower($name); + $name = $this->normalizeName($name); if (!array_key_exists($name, $this->parameters)) { if (!$name) { @@ -111,7 +113,7 @@ public function get($name) */ public function set($name, $value) { - $this->parameters[strtolower($name)] = $value; + $this->parameters[$this->normalizeName($name)] = $value; } /** @@ -119,7 +121,7 @@ public function set($name, $value) */ public function has($name) { - return array_key_exists(strtolower($name), $this->parameters); + return array_key_exists($this->normalizeName($name), $this->parameters); } /** @@ -129,7 +131,7 @@ public function has($name) */ public function remove($name) { - unset($this->parameters[strtolower($name)]); + unset($this->parameters[$this->normalizeName($name)]); } /** @@ -206,7 +208,7 @@ public function resolveString($value, array $resolving = array()) // a non-string in a parameter value if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { $key = $match[1]; - $lcKey = strtolower($key); + $lcKey = strtolower($key); // strtolower() to be removed in 4.0 if (isset($resolving[$lcKey])) { throw new ParameterCircularReferenceException(array_keys($resolving)); @@ -224,7 +226,7 @@ public function resolveString($value, array $resolving = array()) } $key = $match[1]; - $lcKey = strtolower($key); + $lcKey = strtolower($key); // strtolower() to be removed in 4.0 if (isset($resolving[$lcKey])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } @@ -288,4 +290,18 @@ public function unescapeValue($value) return $value; } + + private function normalizeName($name) + { + if (isset($this->normalizedNames[$normalizedName = strtolower($name)])) { + $normalizedName = $this->normalizedNames[$normalizedName]; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 51397309b7dce..e854d394dee8b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1103,6 +1103,21 @@ public function testPrivateServiceTriggersDeprecation() $container->get('bar'); } + + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + */ + public function testParameterWithMixedCase() + { + $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); + $container->register('foo', 'stdClass') + ->setProperty('foo', '%FOO%'); + + $container->compile(); + + $this->assertSame('bar', $container->get('foo')->foo); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 75435cf5682f3..d49df4ec42975 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -125,10 +125,6 @@ public function testGetSetParameter() $sc->setParameter('foo', 'baz'); $this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter'); - $sc->setParameter('Foo', 'baz1'); - $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); - $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); - try { $sc->getParameter('baba'); $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist'); @@ -138,6 +134,20 @@ public function testGetSetParameter() } } + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + */ + public function testGetSetParameterWithMixedCase() + { + $sc = new Container(new ParameterBag(array('foo' => 'bar'))); + + $sc->setParameter('Foo', 'baz1'); + $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); + $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); + } + public function testGetServiceIds() { $sc = new Container(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index fc5a950af4709..495949674bc43 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -670,4 +670,43 @@ public function testPrivateServiceTriggersDeprecation() $container->get('bar'); } + + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "Foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "bar" instead of "BAR" is deprecated since version 3.4. + */ + public function testParameterWithMixedCase() + { + $container = new ContainerBuilder(new ParameterBag(array('Foo' => 'bar', 'BAR' => 'foo'))); + $container->compile(); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case'))); + + $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case(); + + $this->assertSame('bar', $container->getParameter('foo')); + $this->assertSame('bar', $container->getParameter('FOO')); + $this->assertSame('foo', $container->getParameter('bar')); + $this->assertSame('foo', $container->getParameter('BAR')); + } + + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + */ + public function testParameterWithLowerCase() + { + $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); + $container->compile(); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case'))); + + $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case(); + + $this->assertSame('bar', $container->getParameter('FOO')); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php index f0b4ca9330a38..1a4e5ab5c8d8d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php @@ -4,7 +4,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; $container = new ContainerBuilder(new ParameterBag(array( - 'FOO' => '%baz%', + 'foo' => '%baz%', 'baz' => 'bar', 'bar' => 'foo is %%foo bar', 'escape' => '@escapeme', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 19fe0206945cc..d8478d677f4ff 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -78,7 +78,7 @@ protected function getTestService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -96,7 +96,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -142,6 +142,22 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 77224a5b8f800..976c720768752 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -82,7 +82,7 @@ protected function getTestService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -100,7 +100,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -156,6 +156,22 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 5ec14c1026268..0998b23a75b9a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -80,7 +80,7 @@ protected function getTestService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -98,7 +98,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -152,6 +152,24 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } + private $normalizedParameterNames = array( + 'env(foo)' => 'env(FOO)', + ); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * @@ -160,7 +178,7 @@ private function getDynamicParameter($name) protected function getDefaultParameters() { return array( - 'env(foo)' => 'foo', + 'env(FOO)' => 'foo', ); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index f85e3251be8bd..1689a9658668a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -65,7 +65,7 @@ public function isFrozen() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -83,7 +83,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -129,6 +129,22 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 3b80a904d3e9d..2793610bae8ca 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -338,7 +338,7 @@ class Container%s extends Container public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -356,7 +356,7 @@ class Container%s extends Container */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -402,6 +402,22 @@ class Container%s extends Container throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index b01733cabfdd1..e77bc565792a8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -341,7 +341,7 @@ protected function getServiceFromStaticMethodService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -359,7 +359,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -405,6 +405,22 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 92db92cc4ef90..9e59a892e350d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -86,7 +86,7 @@ protected function getBarService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -104,7 +104,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -160,6 +160,22 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @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); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml index f1ac14dd5d343..0d2d6699490ba 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> a string - bar + bar 0 4 @@ -23,7 +23,7 @@ bar - + value PHP_EOL diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml index 7ab302bcb9f9a..e05d69d77e321 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml @@ -1,5 +1,5 @@ parameters: - FOO: bar + foo: bar values: - true - false @@ -9,5 +9,5 @@ parameters: bar: foo escape: '@@escapeme' foo_bar: '@foo_bar' - MixedCase: + mixedcase: MixedCaseKey: value diff --git a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php index 01fcd2c3ef10b..9abfb45d6ef9d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php @@ -115,18 +115,18 @@ public function testResolveEnvCastsIntToString() { $bag = new EnvPlaceholderParameterBag(); $bag->get('env(INT_VAR)'); - $bag->set('env(Int_Var)', 2); + $bag->set('env(INT_VAR)', 2); $bag->resolve(); - $this->assertSame('2', $bag->all()['env(int_var)']); + $this->assertSame('2', $bag->all()['env(INT_VAR)']); } public function testResolveEnvAllowsNull() { $bag = new EnvPlaceholderParameterBag(); $bag->get('env(NULL_VAR)'); - $bag->set('env(Null_Var)', null); + $bag->set('env(NULL_VAR)', null); $bag->resolve(); - $this->assertNull($bag->all()['env(null_var)']); + $this->assertNull($bag->all()['env(NULL_VAR)']); } /** @@ -137,7 +137,7 @@ public function testResolveThrowsOnBadDefaultValue() { $bag = new EnvPlaceholderParameterBag(); $bag->get('env(ARRAY_VAR)'); - $bag->set('env(Array_Var)', array()); + $bag->set('env(ARRAY_VAR)', array()); $bag->resolve(); } @@ -148,7 +148,7 @@ public function testGetEnvAllowsNull() $bag->get('env(NULL_VAR)'); $bag->resolve(); - $this->assertNull($bag->all()['env(null_var)']); + $this->assertNull($bag->all()['env(NULL_VAR)']); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php index 391e0eb3ff7de..3bac9ca64e20d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php @@ -46,8 +46,6 @@ public function testRemove() )); $bag->remove('foo'); $this->assertEquals(array('bar' => 'bar'), $bag->all(), '->remove() removes a parameter'); - $bag->remove('BAR'); - $this->assertEquals(array(), $bag->all(), '->remove() converts key to lowercase before removing'); } public function testGetSet() @@ -59,10 +57,6 @@ public function testGetSet() $bag->set('foo', 'baz'); $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter'); - $bag->set('Foo', 'baz1'); - $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); - $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); - try { $bag->get('baba'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); @@ -109,10 +103,33 @@ public function testHas() { $bag = new ParameterBag(array('foo' => 'bar')); $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); - $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined'); } + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "BAR" instead of "bar" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. + */ + public function testMixedCase() + { + $bag = new ParameterBag(array( + 'foo' => 'foo', + 'bar' => 'bar', + )); + + $bag->remove('BAR'); + $this->assertEquals(array('foo' => 'foo'), $bag->all(), '->remove() converts key to lowercase before removing'); + + $bag->set('Foo', 'baz1'); + $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); + $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); + + $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); + } + public function testResolveValue() { $bag = new ParameterBag(array());