Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cd37427

Browse filesBrowse files
committed
feature #17730 [Yaml] introduce flags to customize the parser behavior (xabbuh)
This PR was merged into the 3.1-dev branch. Discussion ---------- [Yaml] introduce flags to customize the parser behavior | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | TODO Since #17578 it is possible to customise dumped YAML strings with an optional bit field. This pull request does the same for the parser part of the Yaml component. Commits ------- 9cb8552 introduce flags to customize the parser behavior
2 parents 33168b0 + 9cb8552 commit cd37427
Copy full SHA for cd37427

File tree

8 files changed

+309
-38
lines changed
Filter options

8 files changed

+309
-38
lines changed

‎UPGRADE-3.1.md

Copy file name to clipboardExpand all lines: UPGRADE-3.1.md
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,51 @@ Serializer
3333
Yaml
3434
----
3535

36+
* Deprecated support for passing `true`/`false` as the second argument to the
37+
`parse()` method to trigger exceptions when an invalid type was passed.
38+
39+
Before:
40+
41+
```php
42+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', true);
43+
```
44+
45+
After:
46+
47+
```php
48+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', YAML::PARSE_EXCEPTION_ON_INVALID_TYPE);
49+
```
50+
51+
* Deprecated support for passing `true`/`false` as the third argument to the
52+
`parse()` method to toggle object support.
53+
54+
Before:
55+
56+
```php
57+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', false, true);
58+
```
59+
60+
After:
61+
62+
```php
63+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::PARSE_OBJECT);
64+
```
65+
66+
* Deprecated support for passing `true`/`false` as the fourth argument to the
67+
`parse()` method to parse objects as maps.
68+
69+
Before:
70+
71+
```php
72+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', false, false, true);
73+
```
74+
75+
After:
76+
77+
```php
78+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::PARSE_OBJECT_FOR_MAP);
79+
```
80+
3681
* Deprecated support for passing `true`/`false` as the third argument to the `dump()` methods to toggle object support.
3782

3883
Before:

‎UPGRADE-4.0.md

Copy file name to clipboardExpand all lines: UPGRADE-4.0.md
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,51 @@ Serializer
2424
Yaml
2525
----
2626

27+
* Removed support for passing `true`/`false` as the second argument to the
28+
`parse()` method to trigger exceptions when an invalid type was passed.
29+
30+
Before:
31+
32+
```php
33+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', true);
34+
```
35+
36+
After:
37+
38+
```php
39+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', YAML::PARSE_EXCEPTION_ON_INVALID_TYPE);
40+
```
41+
42+
* Removed support for passing `true`/`false` as the third argument to the
43+
`parse()` method to toggle object support.
44+
45+
Before:
46+
47+
```php
48+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', false, true);
49+
```
50+
51+
After:
52+
53+
```php
54+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::PARSE_OBJECT);
55+
```
56+
57+
* Removed support for passing `true`/`false` as the fourth argument to the
58+
`parse()` method to parse objects as maps.
59+
60+
Before:
61+
62+
```php
63+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', false, false, true);
64+
```
65+
66+
After:
67+
68+
```php
69+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::PARSE_OBJECT_FOR_MAP);
70+
```
71+
2772
* Removed support for passing `true`/`false` as the third argument to the `dump()` methods to toggle object support.
2873

2974
Before:

‎src/Symfony/Component/Yaml/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ CHANGELOG
44
3.1.0
55
-----
66

7+
* Added support for customizing the YAML parser behavior through an optional bit field:
8+
9+
```php
10+
Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::EXCEPTION_ON_INVALID_TYPE | Yaml::PARSE_OBJECT | Yaml::PARSE_OBJECT_FOR_MAP);
11+
```
12+
713
* Added support for customizing the dumped YAML string through an optional bit field:
814

915
```php

‎src/Symfony/Component/Yaml/Inline.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Inline.php
+39-9Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,51 @@ class Inline
3030
/**
3131
* Converts a YAML string to a PHP array.
3232
*
33-
* @param string $value A YAML string
34-
* @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
35-
* @param bool $objectSupport true if object support is enabled, false otherwise
36-
* @param bool $objectForMap true if maps should return a stdClass instead of array()
37-
* @param array $references Mapping of variable names to values
33+
* @param string $value A YAML string
34+
* @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior
35+
* @param array $references Mapping of variable names to values
3836
*
3937
* @return array A PHP array representing the YAML string
4038
*
4139
* @throws ParseException
4240
*/
43-
public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false, $references = array())
41+
public static function parse($value, $flags = 0, $references = array())
4442
{
45-
self::$exceptionOnInvalidType = $exceptionOnInvalidType;
46-
self::$objectSupport = $objectSupport;
47-
self::$objectForMap = $objectForMap;
43+
if (is_bool($flags)) {
44+
@trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
45+
46+
if ($flags) {
47+
$flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE;
48+
} else {
49+
$flags = 0;
50+
}
51+
}
52+
53+
if (func_num_args() >= 3 && !is_array($references)) {
54+
@trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
55+
56+
if ($references) {
57+
$flags |= Yaml::PARSE_OBJECT;
58+
}
59+
60+
if (func_num_args() >= 4) {
61+
@trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
62+
63+
if (func_get_arg(3)) {
64+
$flags |= Yaml::PARSE_OBJECT_FOR_MAP;
65+
}
66+
}
67+
68+
if (func_num_args() >= 5) {
69+
$references = func_get_arg(4);
70+
} else {
71+
$references = array();
72+
}
73+
}
74+
75+
self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags);
76+
self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
77+
self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
4878

4979
$value = trim($value);
5080

‎src/Symfony/Component/Yaml/Parser.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Parser.php
+43-21Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,41 @@ public function __construct($offset = 0)
4141
/**
4242
* Parses a YAML string to a PHP value.
4343
*
44-
* @param string $value A YAML string
45-
* @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
46-
* @param bool $objectSupport true if object support is enabled, false otherwise
47-
* @param bool $objectForMap true if maps should return a stdClass instead of array()
44+
* @param string $value A YAML string
45+
* @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior
4846
*
4947
* @return mixed A PHP value
5048
*
5149
* @throws ParseException If the YAML is not valid
5250
*/
53-
public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false)
51+
public function parse($value, $flags = 0)
5452
{
53+
if (is_bool($flags)) {
54+
@trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
55+
56+
if ($flags) {
57+
$flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE;
58+
} else {
59+
$flags = 0;
60+
}
61+
}
62+
63+
if (func_num_args() >= 3) {
64+
@trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
65+
66+
if (func_get_arg(2)) {
67+
$flags |= Yaml::PARSE_OBJECT;
68+
}
69+
}
70+
71+
if (func_num_args() >= 4) {
72+
@trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
73+
74+
if (func_get_arg(3)) {
75+
$flags |= Yaml::PARSE_OBJECT_FOR_MAP;
76+
}
77+
}
78+
5579
if (!preg_match('//u', $value)) {
5680
throw new ParseException('The YAML value does not appear to be valid UTF-8.');
5781
}
@@ -95,7 +119,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
95119
$c = $this->getRealCurrentLineNb() + 1;
96120
$parser = new self($c);
97121
$parser->refs = &$this->refs;
98-
$data[] = $parser->parse($this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport, $objectForMap);
122+
$data[] = $parser->parse($this->getNextEmbedBlock(null, true), $flags);
99123
} else {
100124
if (isset($values['leadspaces'])
101125
&& preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches)
@@ -110,9 +134,9 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
110134
$block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + strlen($values['leadspaces']) + 1);
111135
}
112136

113-
$data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport, $objectForMap);
137+
$data[] = $parser->parse($block, $flags);
114138
} else {
115-
$data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap, $context);
139+
$data[] = $this->parseValue($values['value'], $flags, $context);
116140
}
117141
}
118142
if ($isRef) {
@@ -125,7 +149,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
125149
$context = 'mapping';
126150

127151
// force correct settings
128-
Inline::parse(null, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
152+
Inline::parse(null, $flags, $this->refs);
129153
try {
130154
$key = Inline::parseScalar($values['key']);
131155
} catch (ParseException $e) {
@@ -169,7 +193,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
169193
$c = $this->getRealCurrentLineNb() + 1;
170194
$parser = new self($c);
171195
$parser->refs = &$this->refs;
172-
$parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap);
196+
$parsed = $parser->parse($value, $flags);
173197

174198
if (!is_array($parsed)) {
175199
throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
@@ -220,15 +244,15 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
220244
$c = $this->getRealCurrentLineNb() + 1;
221245
$parser = new self($c);
222246
$parser->refs = &$this->refs;
223-
$value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap);
247+
$value = $parser->parse($this->getNextEmbedBlock(), $flags);
224248
// Spec: Keys MUST be unique; first one wins.
225249
// But overwriting is allowed when a merge node is used in current block.
226250
if ($allowOverwrite || !isset($data[$key])) {
227251
$data[$key] = $value;
228252
}
229253
}
230254
} else {
231-
$value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap, $context);
255+
$value = $this->parseValue($values['value'], $flags, $context);
232256
// Spec: Keys MUST be unique; first one wins.
233257
// But overwriting is allowed when a merge node is used in current block.
234258
if ($allowOverwrite || !isset($data[$key])) {
@@ -247,7 +271,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
247271
// 1-liner optionally followed by newline(s)
248272
if (is_string($value) && $this->lines[0] === trim($value)) {
249273
try {
250-
$value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
274+
$value = Inline::parse($this->lines[0], $flags, $this->refs);
251275
} catch (ParseException $e) {
252276
$e->setParsedLine($this->getRealCurrentLineNb() + 1);
253277
$e->setSnippet($this->currentLine);
@@ -301,7 +325,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
301325
mb_internal_encoding($mbEncoding);
302326
}
303327

304-
if ($objectForMap && !is_object($data)) {
328+
if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && !is_object($data)) {
305329
$data = (object) $data;
306330
}
307331

@@ -462,17 +486,15 @@ private function moveToPreviousLine()
462486
/**
463487
* Parses a YAML value.
464488
*
465-
* @param string $value A YAML value
466-
* @param bool $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise
467-
* @param bool $objectSupport True if object support is enabled, false otherwise
468-
* @param bool $objectForMap true if maps should return a stdClass instead of array()
469-
* @param string $context The parser context (either sequence or mapping)
489+
* @param string $value A YAML value
490+
* @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior
491+
* @param string $context The parser context (either sequence or mapping)
470492
*
471493
* @return mixed A PHP value
472494
*
473495
* @throws ParseException When reference does not exist
474496
*/
475-
private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $context)
497+
private function parseValue($value, $flags, $context)
476498
{
477499
if (0 === strpos($value, '*')) {
478500
if (false !== $pos = strpos($value, '#')) {
@@ -495,7 +517,7 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob
495517
}
496518

497519
try {
498-
$parsedValue = Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
520+
$parsedValue = Inline::parse($value, $flags, $this->refs);
499521

500522
if ('mapping' === $context && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) {
501523
throw new ParseException('A colon cannot be used in an unquoted mapping value.');

‎src/Symfony/Component/Yaml/Tests/InlineTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Yaml/Tests/InlineTest.php
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Yaml\Tests;
1313

1414
use Symfony\Component\Yaml\Inline;
15+
use Symfony\Component\Yaml\Yaml;
1516

1617
class InlineTest extends \PHPUnit_Framework_TestCase
1718
{
@@ -27,6 +28,17 @@ public function testParse($yaml, $value)
2728
* @dataProvider getTestsForParseWithMapObjects
2829
*/
2930
public function testParseWithMapObjects($yaml, $value)
31+
{
32+
$actual = Inline::parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP);
33+
34+
$this->assertSame(serialize($value), serialize($actual));
35+
}
36+
37+
/**
38+
* @group legacy
39+
* @dataProvider getTestsForParseWithMapObjects
40+
*/
41+
public function testParseWithMapObjectsPassingTrue($yaml, $value)
3042
{
3143
$actual = Inline::parse($yaml, false, false, true);
3244

@@ -142,6 +154,15 @@ public function testParseScalarWithCorrectlyQuotedStringShouldReturnString()
142154
* @dataProvider getDataForParseReferences
143155
*/
144156
public function testParseReferences($yaml, $expected)
157+
{
158+
$this->assertSame($expected, Inline::parse($yaml, 0, array('var' => 'var-value')));
159+
}
160+
161+
/**
162+
* @group legacy
163+
* @dataProvider getDataForParseReferences
164+
*/
165+
public function testParseReferencesAsFifthArgument($yaml, $expected)
145166
{
146167
$this->assertSame($expected, Inline::parse($yaml, false, false, false, array('var' => 'var-value')));
147168
}
@@ -161,6 +182,19 @@ public function getDataForParseReferences()
161182
}
162183

163184
public function testParseMapReferenceInSequence()
185+
{
186+
$foo = array(
187+
'a' => 'Steve',
188+
'b' => 'Clark',
189+
'c' => 'Brian',
190+
);
191+
$this->assertSame(array($foo), Inline::parse('[*foo]', 0, array('foo' => $foo)));
192+
}
193+
194+
/**
195+
* @group legacy
196+
*/
197+
public function testParseMapReferenceInSequenceAsFifthArgument()
164198
{
165199
$foo = array(
166200
'a' => 'Steve',

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.