Completed
Push — master ( c762b0...684d44 )
by John
02:56
created

YamlParser::fixHashMaps()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 12
nc 3
nop 1
1
<?php declare(strict_types = 1);
2
/*
3
 * This file is part of the KleijnWeb\ApiDescriptions package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace KleijnWeb\ApiDescriptions\Description\Document\Parser;
10
11
use Symfony\Component\Yaml\Parser as SymfonyYamlParser;
12
13
/**
14
 * @author John Kleijn <[email protected]>
15
 */
16
class YamlParser implements Parser
17
{
18
    /**
19
     * @var SymfonyYamlParser
20
     */
21
    private $parser;
22
23
    /**
24
     * Construct the wrapper
25
     */
26
    public function __construct()
27
    {
28
        $this->parser = new SymfonyYamlParser();
29
    }
30
31
    /**
32
     * @param string $string
33
     *
34
     * @return mixed
35
     * @throws ParseException
36
     */
37
    public function parse(string $string)
38
    {
39
        try {
40
            // Hashmap support is broken in a lot of versions, so disable it and attempt fix afterwards
41
            $data = $this->parser->parse($string, true, false, false);
42
        } catch (\Throwable $e) {
43
            throw new ParseException("Failed to parse as YAML", 0, $e);
44
        }
45
46
        return $this->fixHashMaps($data);
47
    }
48
49
    /**
50
     * @see https://github.com/symfony/symfony/pull/17711
51
     *
52
     * @param mixed $data
53
     *
54
     * @return mixed
55
     */
56
    private function fixHashMaps(&$data)
57
    {
58
        if (is_array($data)) {
59
            $shouldBeObject = false;
60
            $object         = (object)[];
61
            $index          = 0;
62
            foreach ($data as $key => &$value) {
63
                $object->$key = $this->fixHashMaps($value);
64
                if ($index++ !== $key) {
65
                    $shouldBeObject = true;
66
                }
67
            }
68
            if ($shouldBeObject) {
69
                $data = $object;
70
            }
71
        }
72
73
        return $data;
74
    }
75
76
    /**
77
     * @param string $contentType
78
     *
79
     * @return bool
80
     */
81
    public function canParse(string $contentType): bool
82
    {
83
        return strpos($contentType, 'yaml') == strlen($contentType) - 4
84
        || strpos($contentType, 'yml') == strlen($contentType) - 3;
85
    }
86
}
87