diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index be65b535cdd6e..11d46f470d024 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -23,6 +23,12 @@ CHANGELOG the parser and dumper is no longer supported, pass bitmask flags instead * the constructor arguments of the `Parser` class have been removed * the `Inline` class is internal and no longer part of the BC promise + * added support for tagged scalars. + + ```yml + Yaml::parse('!foo bar', Yaml::PARSE_CUSTOM_TAGS); + // returns TaggedValue('foo', 'bar'); + ``` 3.4.0 ----- diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 45e173dd7211d..73389d7a076cd 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -77,7 +77,7 @@ public static function parse($value, $flags = 0, $references = array()) $result = self::parseScalar($value, $flags, null, $i, null === $tag, $references); } - if (null !== $tag) { + if (null !== $tag && '' !== $tag) { return new TaggedValue($tag, $result); } @@ -379,7 +379,7 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = --$i; } - if (null !== $tag) { + if (null !== $tag && '' !== $tag) { $value = new TaggedValue($tag, $value); } @@ -489,7 +489,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar --$i; } - if (null !== $tag) { + if (null !== $tag && '' !== $tag) { $output[$key] = new TaggedValue($tag, $value); } else { $output[$key] = $value; @@ -582,7 +582,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 0 === strpos($scalar, '!!binary '): return self::evaluateBinaryScalar(substr($scalar, 9)); default: - @trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar), E_USER_DEPRECATED); + throw new ParseException(sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar)); } // Optimize for returning strings. @@ -650,20 +650,20 @@ private static function parseTag($value, &$i, $flags) $nextOffset = $i + $tagLength + 1; $nextOffset += strspn($value, ' ', $nextOffset); - // Is followed by a scalar - if (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) { - // Manage scalars in {@link self::evaluateScalar()} + // Is followed by a scalar and is a built-in tag + if ($tag && (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && ('!' === $tag[0] || 'str' === $tag || 0 === strpos($tag, 'php/const:') || 0 === strpos($tag, 'php/object:'))) { + // Manage in {@link self::evaluateScalar()} return; } + $i = $nextOffset; + // Built-in tags if ($tag && '!' === $tag[0]) { throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag)); } - if (Yaml::PARSE_CUSTOM_TAGS & $flags) { - $i = $nextOffset; - + if ('' === $tag || Yaml::PARSE_CUSTOM_TAGS & $flags) { return $tag; } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index d24179d134a0c..fbd5678454e90 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -609,12 +609,12 @@ private function parseValue($value, $flags, $context) $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); - if ('' !== $matches['tag']) { + if ('' !== $matches['tag'] && '!' !== $matches['tag']) { if ('!!binary' === $matches['tag']) { return Inline::evaluateBinaryScalar($data); - } elseif ('!' !== $matches['tag']) { - @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED); } + + return new TaggedValue(substr($matches['tag'], 1), $data); } return $data; diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 761a145a1089d..570daf6a2a3cd 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1542,6 +1542,18 @@ public function testCustomTagSupport($expected, $yaml) public function taggedValuesProvider() { return array( + 'scalars' => array( + array( + 'foo' => new TaggedValue('inline', 'bar'), + 'quz' => new TaggedValue('long', 'this is a long text'), + ), + << + this is a long + text +YAML + ), 'sequences' => array( array(new TaggedValue('foo', array('yaml')), new TaggedValue('quz', array('bar'))), <<assertSame('12', $this->parser->parse('! 12')); + } + /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]"). @@ -1579,12 +1596,21 @@ public function testCustomTagsDisabled() } /** - * @group legacy - * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator foo"). */ public function testUnsupportedTagWithScalar() { - $this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo')); + $this->parser->parse('!iterator foo'); + } + + /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage The string "!!iterator foo" could not be parsed as it uses an unsupported built-in tag at line 1 (near "!!iterator foo"). + */ + public function testUnsupportedBuiltInTagWithScalar() + { + $this->parser->parse('!!iterator foo'); } /**