Dumper::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace TheAentMachine\Yaml;
13
14
use Safe\Exceptions\PcreException;
15
use Safe\Exceptions\StringsException;
16
use Symfony\Component\Yaml\Inline;
17
use Symfony\Component\Yaml\Yaml;
18
use function Safe\substr;
19
use function Safe\sprintf;
20
use function Safe\preg_split;
21
22
/**
23
 * Dumper dumps PHP variables to YAML strings.
24
 *
25
 * Shamelessly stolen and customized from symfony/yaml in order to add support for comments.
26
 * The code still uses the Yaml\Inline class which is marked as internal. In order to avoid any issue,
27
 * the symfony/yaml version is therefore hard-coded in composer.json.
28
 *
29
 * You can use a CommentedItem instance instead of any value in the Yaml input and a comment will be displayed
30
 * on top of the value.
31
 *
32
 * @author Fabien Potencier <[email protected]>
33
 *
34
 * @final
35
 */
36
class Dumper
37
{
38
    /**
39
     * The amount of spaces to use for indentation of nested nodes.
40
     *
41
     * @var int
42
     */
43
    protected $indentation;
44
45
    public function __construct(int $indentation = 4)
46
    {
47
        if ($indentation < 1) {
48
            throw new \InvalidArgumentException('The indentation must be greater than zero.');
49
        }
50
51
        $this->indentation = $indentation;
52
    }
53
54
    /**
55
     * Dumps a PHP value to YAML.
56
     *
57
     * @param mixed $input  The PHP value
58
     * @param int   $inline The level where you switch to inline YAML
59
     * @param int   $indent The level of indentation (used internally)
60
     * @param int   $flags  A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
61
     *
62
     * @return string The YAML representation of the PHP value
63
     * @throws StringsException
64
     * @throws PcreException
65
     */
66
    public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): string
67
    {
68
        if ($input instanceof CommentedItem) {
69
            //$comment = $input->getComment();
70
            $output = '# '.$input->getComment()."\n";
71
            $input = $input->getItem();
72
        } else {
73
            //$comment = null;
74
            $output = '';
75
        }
76
77
//        $output = '';
78
        $prefix = $indent ? str_repeat(' ', $indent) : '';
79
        $dumpObjectAsInlineMap = true;
80
81
        if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($input instanceof \ArrayObject || $input instanceof \stdClass)) {
82
            $dumpObjectAsInlineMap = empty((array) $input);
83
        }
84
85
        if ($inline <= 0 || (!\is_array($input) && $dumpObjectAsInlineMap) || empty($input)) {
86
            $output .= $prefix.Inline::dump($input, $flags);
87
        } else {
88
            $dumpAsMap = Inline::isHash($input);
89
90
            foreach ($input as $key => $value) {
91
                if ($value instanceof CommentedItem) {
92
                    $comment = $value->getComment();
93
                    $value = $value->getItem();
94
                } else {
95
                    $comment = null;
96
                }
97
98
                if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r\n")) {
99
                    // If the first line starts with a space character, the spec requires a blockIndicationIndicator
100
                    // http://www.yaml.org/spec/1.2/spec.html#id2793979
101
                    $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : '';
102
                    $output .= sprintf("%s%s%s |%s\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator);
103
104
                    $pregSplit = preg_split('/\n|\r\n/', $value);
105
                    foreach ($pregSplit as $row) {
106
                        $output .= sprintf("%s%s%s\n", $prefix, str_repeat(' ', $this->indentation), $row);
107
                    }
108
109
                    continue;
110
                }
111
112
                $dumpObjectAsInlineMap = true;
113
114
                if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) {
115
                    $dumpObjectAsInlineMap = empty((array) $value);
116
                }
117
118
                $willBeInlined = $inline - 1 <= 0 || !\is_array($value) && $dumpObjectAsInlineMap || empty($value);
119
120
                if ($comment) {
121
                    $output .= sprintf("%s# %s\n", $prefix, $comment);
122
                }
123
                $output .= sprintf(
124
                    '%s%s%s%s',
125
                    $prefix,
126
                    $dumpAsMap ? Inline::dump($key, $flags).':' : '-',
127
                    $willBeInlined ? ' ' : "\n",
128
                    $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags)
129
                ).($willBeInlined ? "\n" : '');
130
            }
131
        }
132
133
        return $output;
134
    }
135
}
136