[Yaml] Recommend using quotes instead of PARSE_KEYS_AS_STRINGS

This commit is contained in:
Guilhem Niot 2017-05-29 22:10:45 +02:00 committed by Christian Flothmann
parent c0d99d13c0
commit b63c55c72c
13 changed files with 116 additions and 61 deletions

View File

@ -30,13 +30,13 @@ FrameworkBundle
require symfony/stopwatch` in your `dev` environment.
* Using the `KERNEL_DIR` environment variable or the automatic guessing based
on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4.
on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4.
Set the `KERNEL_CLASS` environment variable to the fully-qualified class name
of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable
will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()`
of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable
will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()`
or `KernelTestCase::getKernelClass()` method.
* The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()`
* The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()`
methods are deprecated since 3.4 and will be removed in 4.0.
* The `--no-prefix` option of the `translation:update` command is deprecated and
@ -83,7 +83,7 @@ TwigBridge
* deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer`
class from the Form component instead
* deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
* deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
to pass a command name as first argument
* deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability
@ -95,7 +95,7 @@ TwigBundle
* deprecated the `Symfony\Bundle\TwigBundle\Command\DebugCommand` class, use the `DebugCommand`
class from the Twig bridge instead
* deprecated relying on the `ContainerAwareInterface` implementation for
* deprecated relying on the `ContainerAwareInterface` implementation for
`Symfony\Bundle\TwigBundle\Command\LintCommand`
Validator
@ -111,3 +111,30 @@ Yaml
* Using the non-specific tag `!` is deprecated and will have a different
behavior in 4.0. Use a plain integer or `!!float` instead.
* Using the `Yaml::PARSE_KEYS_AS_STRINGS` flag is deprecated as it will be
removed in 4.0.
Before:
```php
$yaml = <<<YAML
null: null key
true: boolean true
2.0: float key
YAML;
Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS);
```
After:
```php
$yaml = <<<YAML
"null": null key
"true": boolean true
"2.0": float key
YAML;
Yaml::parse($yaml);
```

View File

@ -338,9 +338,9 @@ FrameworkBundle
class instead.
* Using the `KERNEL_DIR` environment variable and the automatic guessing based
on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()`
on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()`
method implementation. Set the `KERNEL_CLASS` environment variable to the
fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()`
fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()`
or `KernelTestCase::getKernelClass()` method instead.
* The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed.
@ -349,10 +349,10 @@ FrameworkBundle
* The `--no-prefix` option of the `translation:update` command has
been removed.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed.
Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed.
Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass`
@ -554,7 +554,7 @@ TwigBridge
* The `TwigRendererEngine::setEnvironment()` method has been removed.
Pass the Twig Environment as second argument of the constructor instead.
* Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
* Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
to pass a command name as first argument.
* Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability
@ -670,6 +670,32 @@ Yaml
Yaml::parse($yaml);
```
* Removed the `Yaml::PARSE_KEYS_AS_STRINGS` flag.
Before:
```php
$yaml = <<<YAML
null: null key
true: boolean true
2.0: float key
YAML;
Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS);
```
After:
```php
$yaml = <<<YAML
"null": null key
"true": boolean true
"2.0": float key
YAML;
Yaml::parse($yaml);
```
* Omitting the key of a mapping is not supported anymore and throws a `ParseException`.
* Mappings with a colon (`:`) that is not followed by a whitespace are not

View File

@ -609,7 +609,7 @@ class YamlFileLoader extends FileLoader
}
try {
$configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_KEYS_AS_STRINGS);
$configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS);
} catch (ParseException $e) {
throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e);
}

View File

@ -17,7 +17,6 @@ use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Yaml\Yaml;
/**
* YamlFileLoader loads Yaml routing files.
@ -59,7 +58,7 @@ class YamlFileLoader extends FileLoader
}
try {
$parsedConfig = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS);
$parsedConfig = $this->yamlParser->parse(file_get_contents($path));
} catch (ParseException $e) {
throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
}

View File

@ -15,7 +15,6 @@ use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Yaml;
/**
* YAML File Loader.
@ -114,7 +113,7 @@ class YamlFileLoader extends FileLoader
$this->yamlParser = new Parser();
}
$classes = $this->yamlParser->parse(file_get_contents($this->file), Yaml::PARSE_KEYS_AS_STRINGS);
$classes = $this->yamlParser->parse(file_get_contents($this->file));
if (empty($classes)) {
return array();

View File

@ -15,7 +15,6 @@ use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
/**
* YamlFileLoader loads translations from Yaml files.
@ -40,7 +39,7 @@ class YamlFileLoader extends FileLoader
}
try {
$messages = $this->yamlParser->parse(file_get_contents($resource), Yaml::PARSE_KEYS_AS_STRINGS);
$messages = $this->yamlParser->parse(file_get_contents($resource));
} catch (ParseException $e) {
throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e);
}

View File

@ -116,7 +116,7 @@ class YamlFileLoader extends FileLoader
private function parseFile($path)
{
try {
$classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS | Yaml::PARSE_CONSTANT);
$classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_CONSTANT);
} catch (ParseException $e) {
throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
}

View File

@ -490,7 +490,7 @@ class Inline
@trigger_error('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.', E_USER_DEPRECATED);
}
if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) {
if (!$isKeyQuoted) {
$evaluatedKey = self::evaluateScalar($key, $flags, $references);
if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) {

View File

@ -86,6 +86,10 @@ class Parser
}
}
if (Yaml::PARSE_KEYS_AS_STRINGS & $flags) {
@trigger_error('Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.', E_USER_DEPRECATED);
}
if (false === preg_match('//u', $value)) {
throw new ParseException('The YAML value does not appear to be valid UTF-8.');
}
@ -236,7 +240,7 @@ class Parser
throw $e;
}
if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) {
if (!is_string($key) && !is_int($key)) {
$keyType = is_numeric($key) ? 'numeric key' : 'non-string key';
@trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType), E_USER_DEPRECATED);
}

View File

@ -125,7 +125,7 @@ EOF;
// TODO
} else {
eval('$expected = '.trim($test['php']).';');
$this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10), Yaml::PARSE_KEYS_AS_STRINGS), $test['test']);
$this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']);
}
}
}

View File

@ -385,8 +385,8 @@ class InlineTest extends TestCase
array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
// mappings
array('{foo: bar,bar: foo,false: false,null: null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS),
array('{ foo : bar, bar : foo, false : false, null : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS),
array('{foo: bar,bar: foo,"false": false, "null": null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
array('{foo: \'bar\', bar: \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
@ -456,8 +456,8 @@ class InlineTest extends TestCase
array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
// mappings
array('{foo: bar,bar: foo,false: false,null: null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_KEYS_AS_STRINGS),
array('{ foo : bar, bar : foo, false : false, null : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_KEYS_AS_STRINGS),
array('{foo: bar,bar: foo,"false": false,"null": null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP),
array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP),
array('{foo: \'bar\', bar: \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', (object) array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
@ -538,7 +538,7 @@ class InlineTest extends TestCase
array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
// mappings
array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS),
array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
array('{ foo: bar, bar: \'foo: bar\' }', array('foo' => 'bar', 'bar' => 'foo: bar')),
// nested sequences and mappings
@ -554,7 +554,7 @@ class InlineTest extends TestCase
array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')),
array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3))), Yaml::PARSE_KEYS_AS_STRINGS),
array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3)))),
);
}
@ -739,11 +739,14 @@ class InlineTest extends TestCase
}
/**
* @group legacy
* @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.
* @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
* @dataProvider getNotPhpCompatibleMappingKeyData
*/
public function testExplicitStringCastingOfMappingKeys($yaml, $expected)
{
$this->assertSame($expected, Inline::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
$this->assertSame($expected, Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
}
public function getNotPhpCompatibleMappingKeyData()

View File

@ -71,6 +71,8 @@ class ParserTest extends TestCase
}
/**
* @group legacy
* @expectedDeprecationMessage Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable
* @dataProvider getNonStringMappingKeysData
*/
public function testNonStringMappingKeys($expected, $yaml, $comment)
@ -510,14 +512,10 @@ EOF;
/**
* @dataProvider getObjectForMapTests
*/
public function testObjectForMap($yaml, $expected, $explicitlyParseKeysAsStrings = false)
public function testObjectForMap($yaml, $expected)
{
$flags = Yaml::PARSE_OBJECT_FOR_MAP;
if ($explicitlyParseKeysAsStrings) {
$flags |= Yaml::PARSE_KEYS_AS_STRINGS;
}
$this->assertEquals($expected, $this->parser->parse($yaml, $flags));
}
@ -577,18 +575,18 @@ YAML;
$expected->map = new \stdClass();
$expected->map->{1} = 'one';
$expected->map->{2} = 'two';
$tests['numeric-keys'] = array($yaml, $expected, true);
$tests['numeric-keys'] = array($yaml, $expected);
$yaml = <<<'YAML'
map:
0: one
1: two
'0': one
'1': two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$expected->map->{0} = 'one';
$expected->map->{1} = 'two';
$tests['zero-indexed-numeric-keys'] = array($yaml, $expected, true);
$tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
return $tests;
}
@ -1120,37 +1118,29 @@ EOF;
$this->assertEquals($expected, $this->parser->parse($yaml));
}
public function testExplicitStringCastingOfFloatKeys()
public function testExplicitStringCasting()
{
$yaml = <<<'EOF'
foo:
1.2: "bar"
1.3: "baz"
EOF;
$expected = array(
'foo' => array(
'1.2' => 'bar',
'1.3' => 'baz',
),
);
$this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
}
public function testExplicitStringCastingOfBooleanKeys()
{
$yaml = <<<'EOF'
true: foo
false: bar
'1.2': "bar"
!!str 1.3: "baz"
'true': foo
!!str false: bar
!!str null: 'null'
'~': 'null'
EOF;
$expected = array(
'1.2' => 'bar',
'1.3' => 'baz',
'true' => 'foo',
'false' => 'bar',
'null' => 'null',
'~' => 'null',
);
$this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
$this->assertEquals($expected, $this->parser->parse($yaml));
}
/**
@ -1843,6 +1833,10 @@ YAML;
$this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
}
/**
* @group legacy
* @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.
*/
public function testPhpConstantTagMappingKeyWithKeysCastToStrings()
{
$yaml = <<<YAML

View File

@ -31,6 +31,10 @@ class Yaml
const PARSE_CONSTANT = 256;
const PARSE_CUSTOM_TAGS = 512;
const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
/**
* @deprecated since version 3.4, to be removed in 4.0. Quote your evaluable keys instead.
*/
const PARSE_KEYS_AS_STRINGS = 2048;
/**