a474249380914bf3c013bf57ac9ea739877d37f6
[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\ConfigurationInterface;
15 use Symfony\Component\Config\Definition\NodeInterface;
16 use Symfony\Component\Config\Definition\ArrayNode;
17 use Symfony\Component\Config\Definition\EnumNode;
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 dumpNode(NodeInterface $node)
37     {
38         $this->reference = '';
39         $this->writeNode($node);
40         $ref = $this->reference;
41         $this->reference = null;
42
43         return $ref;
44     }
45
46     /**
47      * @param NodeInterface $node
48      * @param int           $depth
49      * @param bool          $prototypedArray
50      */
51     private function writeNode(NodeInterface $node, $depth = 0, $prototypedArray = false)
52     {
53         $comments = array();
54         $default = '';
55         $defaultArray = null;
56         $children = null;
57         $example = $node->getExample();
58
59         // defaults
60         if ($node instanceof ArrayNode) {
61             $children = $node->getChildren();
62
63             if ($node instanceof PrototypedArrayNode) {
64                 $children = $this->getPrototypeChildren($node);
65             }
66
67             if (!$children) {
68                 if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) {
69                     $default = '';
70                 } elseif (!is_array($example)) {
71                     $default = '[]';
72                 }
73             }
74         } elseif ($node instanceof EnumNode) {
75             $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues()));
76             $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~';
77         } else {
78             $default = '~';
79
80             if ($node->hasDefaultValue()) {
81                 $default = $node->getDefaultValue();
82
83                 if (is_array($default)) {
84                     if (count($defaultArray = $node->getDefaultValue())) {
85                         $default = '';
86                     } elseif (!is_array($example)) {
87                         $default = '[]';
88                     }
89                 } else {
90                     $default = Inline::dump($default);
91                 }
92             }
93         }
94
95         // required?
96         if ($node->isRequired()) {
97             $comments[] = 'Required';
98         }
99
100         // example
101         if ($example && !is_array($example)) {
102             $comments[] = 'Example: '.$example;
103         }
104
105         $default = (string) $default != '' ? ' '.$default : '';
106         $comments = count($comments) ? '# '.implode(', ', $comments) : '';
107
108         $key = $prototypedArray ? '-' : $node->getName().':';
109         $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' ');
110
111         if ($info = $node->getInfo()) {
112             $this->writeLine('');
113             // indenting multi-line info
114             $info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info);
115             $this->writeLine('# '.$info, $depth * 4);
116         }
117
118         $this->writeLine($text, $depth * 4);
119
120         // output defaults
121         if ($defaultArray) {
122             $this->writeLine('');
123
124             $message = count($defaultArray) > 1 ? 'Defaults' : 'Default';
125
126             $this->writeLine('# '.$message.':', $depth * 4 + 4);
127
128             $this->writeArray($defaultArray, $depth + 1);
129         }
130
131         if (is_array($example)) {
132             $this->writeLine('');
133
134             $message = count($example) > 1 ? 'Examples' : 'Example';
135
136             $this->writeLine('# '.$message.':', $depth * 4 + 4);
137
138             $this->writeArray($example, $depth + 1);
139         }
140
141         if ($children) {
142             foreach ($children as $childNode) {
143                 $this->writeNode($childNode, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute());
144             }
145         }
146     }
147
148     /**
149      * Outputs a single config reference line.
150      *
151      * @param string $text
152      * @param int    $indent
153      */
154     private function writeLine($text, $indent = 0)
155     {
156         $indent = strlen($text) + $indent;
157         $format = '%'.$indent.'s';
158
159         $this->reference .= sprintf($format, $text)."\n";
160     }
161
162     private function writeArray(array $array, $depth)
163     {
164         $isIndexed = array_values($array) === $array;
165
166         foreach ($array as $key => $value) {
167             if (is_array($value)) {
168                 $val = '';
169             } else {
170                 $val = $value;
171             }
172
173             if ($isIndexed) {
174                 $this->writeLine('- '.$val, $depth * 4);
175             } else {
176                 $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4);
177             }
178
179             if (is_array($value)) {
180                 $this->writeArray($value, $depth + 1);
181             }
182         }
183     }
184
185     /**
186      * @param PrototypedArrayNode $node
187      *
188      * @return array
189      */
190     private function getPrototypeChildren(PrototypedArrayNode $node)
191     {
192         $prototype = $node->getPrototype();
193         $key = $node->getKeyAttribute();
194
195         // Do not expand prototype if it isn't an array node nor uses attribute as key
196         if (!$key && !$prototype instanceof ArrayNode) {
197             return $node->getChildren();
198         }
199
200         if ($prototype instanceof ArrayNode) {
201             $keyNode = new ArrayNode($key, $node);
202             $children = $prototype->getChildren();
203
204             if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) {
205                 $children = $this->getPrototypeChildren($prototype);
206             }
207
208             // add children
209             foreach ($children as $childNode) {
210                 $keyNode->addChild($childNode);
211             }
212         } else {
213             $keyNode = new ScalarNode($key, $node);
214         }
215
216         $info = 'Prototype';
217         if (null !== $prototype->getInfo()) {
218             $info .= ': '.$prototype->getInfo();
219         }
220         $keyNode->setInfo($info);
221
222         return array($key => $keyNode);
223     }
224 }