diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 074306969a..fe80c0bd98 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -159,7 +159,7 @@ class Parser // hash } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { // if next line is less indented or equal, then it means that the current value is null - if ($this->isNextLineIndented()) { + if ($this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { $data[$key] = null; } else { $c = $this->getRealCurrentLineNb() + 1; @@ -275,7 +275,9 @@ class Parser if (null === $indentation) { $newIndent = $this->getCurrentLineIndentation(); - if (!$this->isCurrentLineEmpty() && 0 == $newIndent) { + $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine); + + if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { @@ -284,7 +286,15 @@ class Parser $data = array(substr($this->currentLine, $newIndent)); + $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine); + while ($this->moveToNextLine()) { + + if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine)) { + $this->moveToPreviousLine(); + break; + } + if ($this->isCurrentLineEmpty()) { if ($this->isCurrentLineBlank()) { $data[] = substr($this->currentLine, $newIndent); @@ -553,4 +563,47 @@ class Parser return $value; } + + /** + * Returns true if the next line starts unindented collection + * + * @return Boolean Returns true if the next line starts unindented collection, false otherwise + */ + private function isNextLineUnIndentedCollection() + { + $currentIndentation = $this->getCurrentLineIndentation(); + $notEOF = $this->moveToNextLine(); + + while ($notEOF && $this->isCurrentLineEmpty()) { + $notEOF = $this->moveToNextLine(); + } + + if (false === $notEOF) { + return false; + } + + $ret = false; + if ( + $this->getCurrentLineIndentation() == $currentIndentation + && + $this->isStringUnIndentedCollectionItem($this->currentLine) + ) { + $ret = true; + } + + $this->moveToPreviousLine(); + + return $ret; + } + + /** + * Returns true if the string is unindented collection item + * + * @return Boolean Returns true if the string is unindented collection item, false otherwise + */ + private function isStringUnIndentedCollectionItem($string) + { + return (0 === strpos($this->currentLine, '- ')); + } + } diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/index.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/index.yml index a1d7f39e0b..a471c5271e 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/index.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/index.yml @@ -15,3 +15,4 @@ - YtsNullsAndEmpties - YtsSpecificationExamples - YtsTypeTransfers +- unindentedCollections \ No newline at end of file diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml new file mode 100644 index 0000000000..fd8ad7ed44 --- /dev/null +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml @@ -0,0 +1,62 @@ +--- %YAML:1.0 +test: Unindented collection +brief: > + Unindented collection +yaml: | + collection: + - item1 + - item2 + - item3 +php: | + array('collection' => array('item1', 'item2', 'item3')) +--- +test: Nested unindented collection (two levels) +brief: > + Nested unindented collection +yaml: | + collection: + key: + - a + - b + - c +php: | + array('collection' => array('key' => array('a', 'b', 'c'))) +--- +test: Nested unindented collection (three levels) +brief: > + Nested unindented collection +yaml: | + collection: + key: + subkey: + - one + - two + - three +php: | + array('collection' => array('key' => array('subkey' => array('one', 'two', 'three')))) +--- +test: Key/value after unindented collection (1) +brief: > + Key/value after unindented collection (1) +yaml: | + collection: + key: + - a + - b + - c + foo: bar +php: | + array('collection' => array('key' => array('a', 'b', 'c')), 'foo' => 'bar') +--- +test: Key/value after unindented collection (at the same level) +brief: > + Key/value after unindented collection +yaml: | + collection: + key: + - a + - b + - c + foo: bar +php: | + array('collection' => array('key' => array('a', 'b', 'c'), 'foo' => 'bar')) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 98689ae6bd..6b4e2d482b 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -140,6 +140,26 @@ EOF } } } + + /** + * + * @expectedException Symfony\Component\Yaml\Exception\ParseException + * + */ + public function testUnindentedCollectionException() + { + $yaml = <<parser->parse($yaml); + } + } class B