Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: symfony/yaml
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.4.29
Choose a base ref
...
head repository: symfony/yaml
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.4.34
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 13, 2021

  1. Copy the full SHA
    878d63b View commit details

Commits on Nov 18, 2021

  1. Copy the full SHA
    2c309e2 View commit details
Showing with 48 additions and 10 deletions.
  1. +20 −10 Inline.php
  2. +28 −0 Tests/InlineTest.php
30 changes: 20 additions & 10 deletions Inline.php
Original file line number Diff line number Diff line change
@@ -269,10 +269,11 @@ private static function dumpNull(int $flags): string
*
* @throws ParseException When malformed inline YAML string is parsed
*/
public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [])
public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [], bool &$isQuoted = null)
{
if (\in_array($scalar[$i], ['"', "'"])) {
// quoted scalar
$isQuoted = true;
$output = self::parseQuotedScalar($scalar, $i);

if (null !== $delimiters) {
@@ -286,6 +287,8 @@ public static function parseScalar(string $scalar, int $flags = 0, array $delimi
}
} else {
// "normal" string
$isQuoted = false;

if (!$delimiters) {
$output = substr($scalar, $i);
$i += \strlen($output);
@@ -308,7 +311,7 @@ public static function parseScalar(string $scalar, int $flags = 0, array $delimi
}

if ($evaluate) {
$output = self::evaluateScalar($output, $flags, $references);
$output = self::evaluateScalar($output, $flags, $references, $isQuoted);
}
}

@@ -320,7 +323,7 @@ public static function parseScalar(string $scalar, int $flags = 0, array $delimi
*
* @throws ParseException When malformed inline YAML string is parsed
*/
private static function parseQuotedScalar(string $scalar, int &$i): string
private static function parseQuotedScalar(string $scalar, int &$i = 0): string
{
if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
throw new ParseException(sprintf('Malformed inline YAML string: "%s".', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
@@ -373,8 +376,7 @@ private static function parseSequence(string $sequence, int $flags, int &$i = 0,
$value = self::parseMapping($sequence, $flags, $i, $references);
break;
default:
$isQuoted = \in_array($sequence[$i], ['"', "'"]);
$value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references);
$value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references, $isQuoted);

// the value can be an array if a reference has been resolved to an array var
if (\is_string($value) && !$isQuoted && false !== strpos($value, ': ')) {
@@ -387,7 +389,7 @@ private static function parseSequence(string $sequence, int $flags, int &$i = 0,
}
}

if (\is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
if (!$isQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
$references[$matches['ref']] = $matches['value'];
$value = $matches['value'];
}
@@ -521,15 +523,15 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a
}
break;
default:
$value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references);
$value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references, $isValueQuoted);
// Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines
// are processed sequentially.
// But overwriting is allowed when a merge node is used in current block.
if ('<<' === $key) {
$output += $value;
} elseif ($allowOverwrite || !isset($output[$key])) {
if (\is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
if (!$isValueQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
$references[$matches['ref']] = $matches['value'];
$value = $matches['value'];
}
@@ -560,8 +562,9 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a
*
* @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved
*/
private static function evaluateScalar(string $scalar, int $flags, array &$references = [])
private static function evaluateScalar(string $scalar, int $flags, array &$references = [], bool &$isQuotedString = null)
{
$isQuotedString = false;
$scalar = trim($scalar);
$scalarLower = strtolower($scalar);

@@ -596,7 +599,14 @@ private static function evaluateScalar(string $scalar, int $flags, array &$refer
case '!' === $scalar[0]:
switch (true) {
case 0 === strpos($scalar, '!!str '):
return (string) substr($scalar, 6);
$s = (string) substr($scalar, 6);

if (\in_array($s[0] ?? '', ['"', "'"], true)) {
$isQuotedString = true;
$s = self::parseQuotedScalar($s);
}

return $s;
case 0 === strpos($scalar, '! '):
return substr($scalar, 2);
case 0 === strpos($scalar, '!php/object'):
28 changes: 28 additions & 0 deletions Tests/InlineTest.php
Original file line number Diff line number Diff line change
@@ -905,4 +905,32 @@ public function ideographicSpaceProvider(): array
["'a b'", 'a b'],
];
}

public function testParseSingleQuotedTaggedString()
{
$this->assertSame('foo', Inline::parse("!!str 'foo'"));
}

public function testParseDoubleQuotedTaggedString()
{
$this->assertSame('foo', Inline::parse('!!str "foo"'));
}

public function testParseQuotedReferenceLikeStringsInMapping()
{
$yaml = <<<YAML
{foo: '&foo', bar: "&bar", baz: !!str '&baz'}
YAML;

$this->assertSame(['foo' => '&foo', 'bar' => '&bar', 'baz' => '&baz'], Inline::parse($yaml));
}

public function testParseQuotedReferenceLikeStringsInSequence()
{
$yaml = <<<YAML
['&foo', "&bar", !!str '&baz']
YAML;

$this->assertSame(['&foo', '&bar', '&baz'], Inline::parse($yaml));
}
}