Completed
Push — master ( 01e071...007090 )
by Ehsan
01:46 queued 13s
created

YamlReferenceDumper::writeNode()   F

Complexity

Conditions 27
Paths > 20000

Size

Total Lines 96
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 27
eloc 55
nc 25920
nop 3
dl 0
loc 96
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 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 <[email protected]>
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 int           $depth
75
     * @param bool          $prototypedArray
76
     */
77
    private function writeNode(NodeInterface $node, $depth = 0, $prototypedArray = false)
78
    {
79
        $comments = array();
80
        $default = '';
81
        $defaultArray = null;
82
        $children = null;
83
        $example = $node->getExample();
84
85
        // defaults
86
        if ($node instanceof ArrayNode) {
87
            $children = $node->getChildren();
88
89
            if ($node instanceof PrototypedArrayNode) {
90
                $children = $this->getPrototypeChildren($node);
91
            }
92
93
            if (!$children) {
94
                if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) {
95
                    $default = '';
96
                } elseif (!is_array($example)) {
97
                    $default = '[]';
98
                }
99
            }
100
        } elseif ($node instanceof EnumNode) {
101
            $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues()));
102
            $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~';
103
        } else {
104
            $default = '~';
105
106
            if ($node->hasDefaultValue()) {
107
                $default = $node->getDefaultValue();
108
109
                if (is_array($default)) {
110
                    if (count($defaultArray = $node->getDefaultValue())) {
111
                        $default = '';
112
                    } elseif (!is_array($example)) {
113
                        $default = '[]';
114
                    }
115
                } else {
116
                    $default = Inline::dump($default);
117
                }
118
            }
119
        }
120
121
        // required?
122
        if ($node->isRequired()) {
123
            $comments[] = 'Required';
124
        }
125
126
        // example
127
        if ($example && !is_array($example)) {
128
            $comments[] = 'Example: '.$example;
129
        }
130
131
        $default = (string) $default != '' ? ' '.$default : '';
132
        $comments = count($comments) ? '# '.implode(', ', $comments) : '';
133
134
        $key = $prototypedArray ? '-' : $node->getName().':';
135
        $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' ');
136
137
        if ($info = $node->getInfo()) {
138
            $this->writeLine('');
139
            // indenting multi-line info
140
            $info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info);
141
            $this->writeLine('# '.$info, $depth * 4);
142
        }
143
144
        $this->writeLine($text, $depth * 4);
145
146
        // output defaults
147
        if ($defaultArray) {
148
            $this->writeLine('');
149
150
            $message = count($defaultArray) > 1 ? 'Defaults' : 'Default';
151
152
            $this->writeLine('# '.$message.':', $depth * 4 + 4);
153
154
            $this->writeArray($defaultArray, $depth + 1);
155
        }
156
157
        if (is_array($example)) {
158
            $this->writeLine('');
159
160
            $message = count($example) > 1 ? 'Examples' : 'Example';
161
162
            $this->writeLine('# '.$message.':', $depth * 4 + 4);
163
164
            $this->writeArray($example, $depth + 1);
165
        }
166
167
        if ($children) {
168
            foreach ($children as $childNode) {
169
                $this->writeNode($childNode, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute());
170
            }
171
        }
172
    }
173
174
    /**
175
     * Outputs a single config reference line.
176
     *
177
     * @param string $text
178
     * @param int    $indent
179
     */
180
    private function writeLine($text, $indent = 0)
181
    {
182
        $indent = strlen($text) + $indent;
183
        $format = '%'.$indent.'s';
184
185
        $this->reference .= sprintf($format, $text)."\n";
186
    }
187
188
    private function writeArray(array $array, $depth)
189
    {
190
        $isIndexed = array_values($array) === $array;
191
192
        foreach ($array as $key => $value) {
193
            if (is_array($value)) {
194
                $val = '';
195
            } else {
196
                $val = $value;
197
            }
198
199
            if ($isIndexed) {
200
                $this->writeLine('- '.$val, $depth * 4);
201
            } else {
202
                $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4);
203
            }
204
205
            if (is_array($value)) {
206
                $this->writeArray($value, $depth + 1);
207
            }
208
        }
209
    }
210
211
    /**
212
     * @param PrototypedArrayNode $node
213
     *
214
     * @return array
215
     */
216
    private function getPrototypeChildren(PrototypedArrayNode $node)
217
    {
218
        $prototype = $node->getPrototype();
219
        $key = $node->getKeyAttribute();
220
221
        // Do not expand prototype if it isn't an array node nor uses attribute as key
222
        if (!$key && !$prototype instanceof ArrayNode) {
223
            return $node->getChildren();
224
        }
225
226
        if ($prototype instanceof ArrayNode) {
227
            $keyNode = new ArrayNode($key, $node);
228
            $children = $prototype->getChildren();
229
230
            if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) {
231
                $children = $this->getPrototypeChildren($prototype);
232
            }
233
234
            // add children
235
            foreach ($children as $childNode) {
236
                $keyNode->addChild($childNode);
237
            }
238
        } else {
239
            $keyNode = new ScalarNode($key, $node);
240
        }
241
242
        $info = 'Prototype';
243
        if (null !== $prototype->getInfo()) {
244
            $info .= ': '.$prototype->getInfo();
245
        }
246
        $keyNode->setInfo($info);
247
248
        return array($key => $keyNode);
249
    }
250
}
251