fc5d20a2e70408d1423bd439b4adfcddf9f8f610
[yaffs-website] / vendor / symfony / config / Definition / Dumper / YamlReferenceDumper.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
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 Symfony\Component\Config\Definition\Dumper;
13
14 use Symfony\Component\Config\Definition\ArrayNode;
15 use Symfony\Component\Config\Definition\ConfigurationInterface;
16 use Symfony\Component\Config\Definition\EnumNode;
17 use Symfony\Component\Config\Definition\NodeInterface;
18 use Symfony\Component\Config\Definition\PrototypedArrayNode;
19 use Symfony\Component\Config\Definition\ScalarNode;
20 use Symfony\Component\Yaml\Inline;
21
22 /**
23  * Dumps a Yaml reference configuration for the given configuration/node instance.
24  *
25  * @author Kevin Bond <kevinbond@gmail.com>
26  */
27 class YamlReferenceDumper
28 {
29     private $reference;
30
31     public function dump(ConfigurationInterface $configuration)
32     {
33         return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree());
34     }
35
36     public function dumpAtPath(ConfigurationInterface $configuration, $path)
37     {
38         $rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree();
39
40         foreach (explode('.', $path) as $step) {
41             if (!$node instanceof ArrayNode) {
42                 throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path));
43             }
44
45             /** @var NodeInterface[] $children */
46             $children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren();
47
48             foreach ($children as $child) {
49                 if ($child->getName() === $step) {
50                     $node = $child;
51
52                     continue 2;
53                 }
54             }
55
56             throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path));
57         }
58
59         return $this->dumpNode($node);
60     }
61
62     public function dumpNode(NodeInterface $node)
63     {
64         $this->reference = '';
65         $this->writeNode($node);
66         $ref = $this->reference;
67         $this->reference = null;
68
69         return $ref;
70     }
71
72     /**
73      * @param NodeInterface      $node
74      * @param NodeInterface|null $parentNode
75      * @param int                $depth
76      * @param bool               $prototypedArray
77      */
78     private function writeNode(NodeInterface $node, NodeInterface $parentNode = null, $depth = 0, $prototypedArray = false)
79     {
80         $comments = array();
81         $default = '';
82         $defaultArray = null;
83         $children = null;
84         $example = $node->getExample();
85
86         // defaults
87         if ($node instanceof ArrayNode) {
88             $children = $node->getChildren();
89
90             if ($node instanceof PrototypedArrayNode) {
91                 $children = $this->getPrototypeChildren($node);
92             }
93
94             if (!$children) {
95                 if ($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue())) {
96                     $default = '';
97                 } elseif (!\is_array($example)) {
98                     $default = '[]';
99                 }
100             }
101         } elseif ($node instanceof EnumNode) {
102             $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues()));
103             $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~';
104         } else {
105             $default = '~';
106
107             if ($node->hasDefaultValue()) {
108                 $default = $node->getDefaultValue();
109
110                 if (\is_array($default)) {
111                     if (\count($defaultArray = $node->getDefaultValue())) {
112                         $default = '';
113                     } elseif (!\is_array($example)) {
114                         $default = '[]';
115                     }
116                 } else {
117                     $default = Inline::dump($default);
118                 }
119             }
120         }
121
122         // required?
123         if ($node->isRequired()) {
124             $comments[] = 'Required';
125         }
126
127         // deprecated?
128         if ($node->isDeprecated()) {
129             $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath()));
130         }
131
132         // example
133         if ($example && !\is_array($example)) {
134             $comments[] = 'Example: '.$example;
135         }
136
137         $default = '' != (string) $default ? ' '.$default : '';
138         $comments = \count($comments) ? '# '.implode(', ', $comments) : '';
139
140         $key = $prototypedArray ? '-' : $node->getName().':';
141         $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' ');
142
143         if ($info = $node->getInfo()) {
144             $this->writeLine('');
145             // indenting multi-line info
146             $info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info);
147             $this->writeLine('# '.$info, $depth * 4);
148         }
149
150         $this->writeLine($text, $depth * 4);
151
152         // output defaults
153         if ($defaultArray) {
154             $this->writeLine('');
155
156             $message = \count($defaultArray) > 1 ? 'Defaults' : 'Default';
157
158             $this->writeLine('# '.$message.':', $depth * 4 + 4);
159
160             $this->writeArray($defaultArray, $depth + 1);
161         }
162
163         if (\is_array($example)) {
164             $this->writeLine('');
165
166             $message = \count($example) > 1 ? 'Examples' : 'Example';
167
168             $this->writeLine('# '.$message.':', $depth * 4 + 4);
169
170             $this->writeArray($example, $depth + 1);
171         }
172
173         if ($children) {
174             foreach ($children as $childNode) {
175                 $this->writeNode($childNode, $node, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute());
176             }
177         }
178     }
179
180     /**
181      * Outputs a single config reference line.
182      *
183      * @param string $text
184      * @param int    $indent
185      */
186     private function writeLine($text, $indent = 0)
187     {
188         $indent = \strlen($text) + $indent;
189         $format = '%'.$indent.'s';
190
191         $this->reference .= sprintf($format, $text)."\n";
192     }
193
194     private function writeArray(array $array, $depth)
195     {
196         $isIndexed = array_values($array) === $array;
197
198         foreach ($array as $key => $value) {
199             if (\is_array($value)) {
200                 $val = '';
201             } else {
202                 $val = $value;
203             }
204
205             if ($isIndexed) {
206                 $this->writeLine('- '.$val, $depth * 4);
207             } else {
208                 $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4);
209             }
210
211             if (\is_array($value)) {
212                 $this->writeArray($value, $depth + 1);
213             }
214         }
215     }
216
217     /**
218      * @param PrototypedArrayNode $node
219      *
220      * @return array
221      */
222     private function getPrototypeChildren(PrototypedArrayNode $node)
223     {
224         $prototype = $node->getPrototype();
225         $key = $node->getKeyAttribute();
226
227         // Do not expand prototype if it isn't an array node nor uses attribute as key
228         if (!$key && !$prototype instanceof ArrayNode) {
229             return $node->getChildren();
230         }
231
232         if ($prototype instanceof ArrayNode) {
233             $keyNode = new ArrayNode($key, $node);
234             $children = $prototype->getChildren();
235
236             if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) {
237                 $children = $this->getPrototypeChildren($prototype);
238             }
239
240             // add children
241             foreach ($children as $childNode) {
242                 $keyNode->addChild($childNode);
243             }
244         } else {
245             $keyNode = new ScalarNode($key, $node);
246         }
247
248         $info = 'Prototype';
249         if (null !== $prototype->getInfo()) {
250             $info .= ': '.$prototype->getInfo();
251         }
252         $keyNode->setInfo($info);
253
254         return array($key => $keyNode);
255     }
256 }