xref: /plugin/combo/vendor/symfony/yaml/Dumper.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeau/*
4*04fd306cSNickeau * This file is part of the Symfony package.
5*04fd306cSNickeau *
6*04fd306cSNickeau * (c) Fabien Potencier <fabien@symfony.com>
7*04fd306cSNickeau *
8*04fd306cSNickeau * For the full copyright and license information, please view the LICENSE
9*04fd306cSNickeau * file that was distributed with this source code.
10*04fd306cSNickeau */
11*04fd306cSNickeau
12*04fd306cSNickeaunamespace Symfony\Component\Yaml;
13*04fd306cSNickeau
14*04fd306cSNickeauuse Symfony\Component\Yaml\Tag\TaggedValue;
15*04fd306cSNickeau
16*04fd306cSNickeau/**
17*04fd306cSNickeau * Dumper dumps PHP variables to YAML strings.
18*04fd306cSNickeau *
19*04fd306cSNickeau * @author Fabien Potencier <fabien@symfony.com>
20*04fd306cSNickeau *
21*04fd306cSNickeau * @final
22*04fd306cSNickeau */
23*04fd306cSNickeauclass Dumper
24*04fd306cSNickeau{
25*04fd306cSNickeau    /**
26*04fd306cSNickeau     * The amount of spaces to use for indentation of nested nodes.
27*04fd306cSNickeau     *
28*04fd306cSNickeau     * @var int
29*04fd306cSNickeau     */
30*04fd306cSNickeau    protected $indentation;
31*04fd306cSNickeau
32*04fd306cSNickeau    public function __construct(int $indentation = 4)
33*04fd306cSNickeau    {
34*04fd306cSNickeau        if ($indentation < 1) {
35*04fd306cSNickeau            throw new \InvalidArgumentException('The indentation must be greater than zero.');
36*04fd306cSNickeau        }
37*04fd306cSNickeau
38*04fd306cSNickeau        $this->indentation = $indentation;
39*04fd306cSNickeau    }
40*04fd306cSNickeau
41*04fd306cSNickeau    /**
42*04fd306cSNickeau     * Dumps a PHP value to YAML.
43*04fd306cSNickeau     *
44*04fd306cSNickeau     * @param mixed $input  The PHP value
45*04fd306cSNickeau     * @param int   $inline The level where you switch to inline YAML
46*04fd306cSNickeau     * @param int   $indent The level of indentation (used internally)
47*04fd306cSNickeau     * @param int   $flags  A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
48*04fd306cSNickeau     */
49*04fd306cSNickeau    public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): string
50*04fd306cSNickeau    {
51*04fd306cSNickeau        $output = '';
52*04fd306cSNickeau        $prefix = $indent ? str_repeat(' ', $indent) : '';
53*04fd306cSNickeau        $dumpObjectAsInlineMap = true;
54*04fd306cSNickeau
55*04fd306cSNickeau        if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($input instanceof \ArrayObject || $input instanceof \stdClass)) {
56*04fd306cSNickeau            $dumpObjectAsInlineMap = empty((array) $input);
57*04fd306cSNickeau        }
58*04fd306cSNickeau
59*04fd306cSNickeau        if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || empty($input)) {
60*04fd306cSNickeau            $output .= $prefix.Inline::dump($input, $flags);
61*04fd306cSNickeau        } elseif ($input instanceof TaggedValue) {
62*04fd306cSNickeau            $output .= $this->dumpTaggedValue($input, $inline, $indent, $flags, $prefix);
63*04fd306cSNickeau        } else {
64*04fd306cSNickeau            $dumpAsMap = Inline::isHash($input);
65*04fd306cSNickeau
66*04fd306cSNickeau            foreach ($input as $key => $value) {
67*04fd306cSNickeau                if ('' !== $output && "\n" !== $output[-1]) {
68*04fd306cSNickeau                    $output .= "\n";
69*04fd306cSNickeau                }
70*04fd306cSNickeau
71*04fd306cSNickeau                if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) {
72*04fd306cSNickeau                    // If the first line starts with a space character, the spec requires a blockIndicationIndicator
73*04fd306cSNickeau                    // http://www.yaml.org/spec/1.2/spec.html#id2793979
74*04fd306cSNickeau                    $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : '';
75*04fd306cSNickeau
76*04fd306cSNickeau                    if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) {
77*04fd306cSNickeau                        $blockChompingIndicator = '+';
78*04fd306cSNickeau                    } elseif ("\n" === $value[-1]) {
79*04fd306cSNickeau                        $blockChompingIndicator = '';
80*04fd306cSNickeau                    } else {
81*04fd306cSNickeau                        $blockChompingIndicator = '-';
82*04fd306cSNickeau                    }
83*04fd306cSNickeau
84*04fd306cSNickeau                    $output .= sprintf('%s%s%s |%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator, $blockChompingIndicator);
85*04fd306cSNickeau
86*04fd306cSNickeau                    foreach (explode("\n", $value) as $row) {
87*04fd306cSNickeau                        if ('' === $row) {
88*04fd306cSNickeau                            $output .= "\n";
89*04fd306cSNickeau                        } else {
90*04fd306cSNickeau                            $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row);
91*04fd306cSNickeau                        }
92*04fd306cSNickeau                    }
93*04fd306cSNickeau
94*04fd306cSNickeau                    continue;
95*04fd306cSNickeau                }
96*04fd306cSNickeau
97*04fd306cSNickeau                if ($value instanceof TaggedValue) {
98*04fd306cSNickeau                    $output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag());
99*04fd306cSNickeau
100*04fd306cSNickeau                    if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) {
101*04fd306cSNickeau                        // If the first line starts with a space character, the spec requires a blockIndicationIndicator
102*04fd306cSNickeau                        // http://www.yaml.org/spec/1.2/spec.html#id2793979
103*04fd306cSNickeau                        $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : '';
104*04fd306cSNickeau                        $output .= sprintf(' |%s', $blockIndentationIndicator);
105*04fd306cSNickeau
106*04fd306cSNickeau                        foreach (explode("\n", $value->getValue()) as $row) {
107*04fd306cSNickeau                            $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row);
108*04fd306cSNickeau                        }
109*04fd306cSNickeau
110*04fd306cSNickeau                        continue;
111*04fd306cSNickeau                    }
112*04fd306cSNickeau
113*04fd306cSNickeau                    if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
114*04fd306cSNickeau                        $output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n";
115*04fd306cSNickeau                    } else {
116*04fd306cSNickeau                        $output .= "\n";
117*04fd306cSNickeau                        $output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags);
118*04fd306cSNickeau                    }
119*04fd306cSNickeau
120*04fd306cSNickeau                    continue;
121*04fd306cSNickeau                }
122*04fd306cSNickeau
123*04fd306cSNickeau                $dumpObjectAsInlineMap = true;
124*04fd306cSNickeau
125*04fd306cSNickeau                if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) {
126*04fd306cSNickeau                    $dumpObjectAsInlineMap = empty((array) $value);
127*04fd306cSNickeau                }
128*04fd306cSNickeau
129*04fd306cSNickeau                $willBeInlined = $inline - 1 <= 0 || !\is_array($value) && $dumpObjectAsInlineMap || empty($value);
130*04fd306cSNickeau
131*04fd306cSNickeau                $output .= sprintf('%s%s%s%s',
132*04fd306cSNickeau                    $prefix,
133*04fd306cSNickeau                    $dumpAsMap ? Inline::dump($key, $flags).':' : '-',
134*04fd306cSNickeau                    $willBeInlined ? ' ' : "\n",
135*04fd306cSNickeau                    $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags)
136*04fd306cSNickeau                ).($willBeInlined ? "\n" : '');
137*04fd306cSNickeau            }
138*04fd306cSNickeau        }
139*04fd306cSNickeau
140*04fd306cSNickeau        return $output;
141*04fd306cSNickeau    }
142*04fd306cSNickeau
143*04fd306cSNickeau    private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, int $flags, string $prefix): string
144*04fd306cSNickeau    {
145*04fd306cSNickeau        $output = sprintf('%s!%s', $prefix ? $prefix.' ' : '', $value->getTag());
146*04fd306cSNickeau
147*04fd306cSNickeau        if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) {
148*04fd306cSNickeau            // If the first line starts with a space character, the spec requires a blockIndicationIndicator
149*04fd306cSNickeau            // http://www.yaml.org/spec/1.2/spec.html#id2793979
150*04fd306cSNickeau            $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : '';
151*04fd306cSNickeau            $output .= sprintf(' |%s', $blockIndentationIndicator);
152*04fd306cSNickeau
153*04fd306cSNickeau            foreach (explode("\n", $value->getValue()) as $row) {
154*04fd306cSNickeau                $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row);
155*04fd306cSNickeau            }
156*04fd306cSNickeau
157*04fd306cSNickeau            return $output;
158*04fd306cSNickeau        }
159*04fd306cSNickeau
160*04fd306cSNickeau        if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
161*04fd306cSNickeau            return $output.' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n";
162*04fd306cSNickeau        }
163*04fd306cSNickeau
164*04fd306cSNickeau        return $output."\n".$this->dump($value->getValue(), $inline - 1, $indent, $flags);
165*04fd306cSNickeau    }
166*04fd306cSNickeau}
167