Completed
Push — master ( 5e9205...742ab5 )
by Alex
01:40
created

Configuration::addErrorLoggingLevelNode()   B

Complexity

Conditions 2
Paths 1

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 15
cts 15
cp 1
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 16
nc 1
nop 0
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace AlexMasterov\PsyshBundle\DependencyInjection;
5
6
use Symfony\Component\Config\Definition\{
7
    Builder\ArrayNodeDefinition,
8
    Builder\TreeBuilder,
9
    ConfigurationInterface,
10
    Exception\InvalidConfigurationException
11
};
12
13
class Configuration implements ConfigurationInterface
14
{
15
    /**
16
     * @inheritDoc
17
     */
18 3
    public function getConfigTreeBuilder()
19
    {
20 3
        $treeBuilder = new TreeBuilder();
21 3
        $rootNode = $treeBuilder->root('psysh');
22
23
        $rootNode
24 3
            ->children()
25 3
                ->append($this->addVariablesNode())
26 3
                ->append($this->addArrayNode('commands'))
27 3
                ->append($this->addArrayNode('default_includes'))
28 3
                ->append($this->addErrorLoggingLevelNode())
29 3
                ->scalarNode('config_dir')->end()
30 3
                ->scalarNode('data_dir')->end()
31 3
                ->scalarNode('runtime_dir')
32 3
                    ->info('Set the shell\'s temporary directory location')
33 3
                ->end()
34 3
                ->integerNode('history_size')
35 3
                    ->info('If set to zero (0), the history size is unlimited')
36 3
                ->end()
37 3
                ->scalarNode('history_file')->end()
38 3
                ->scalarNode('manual_db_file')->end()
39 3
                ->booleanNode('tab_completion')->end()
40 3
                ->append($this->addArrayNode('tab_completion_matchers'))
41 3
                ->scalarNode('startup_message')->end()
42 3
                ->booleanNode('require_semicolons')->end()
43 3
                ->booleanNode('erase_duplicates')->end()
44 3
                ->booleanNode('pcntl')->end()
45 3
                ->booleanNode('readline')->end()
46 3
                ->booleanNode('unicode')->end()
47 3
                ->enumNode('color_mode')
48 3
                    ->values(['auto', 'forced', 'disabled'])
49 3
                ->end()
50 3
                ->scalarNode('pager')->treatNullLike('less')->end()
51 3
                ->enumNode('update_check')->defaultValue('never')
52 3
                    ->values(['never', 'always', 'daily', 'weekly', 'monthly'])
53 3
                ->end()
54 3
            ->end()
55 3
            ->validate()
56 3
                ->always()
57 3
                ->then($this->normalizer())
58 3
            ->end();
59
60 3
        return $treeBuilder;
61
    }
62
63 3
    private function normalizer(): callable
64
    {
65
        return static function (array $config): array {
66 2
            static $keys = [
67
                'pcntl'    => 'usePcntl',
68
                'readline' => 'useReadline',
69
                'unicode'  => 'useUnicode',
70
            ];
71
72
            // config_dir -> configDir
73
            $camelize = static function (string $value): string {
74 2
                return \str_replace('_', '', \lcfirst(\ucwords(\strtolower($value), '_')));
75 2
            };
76
77 2
            $normalized = [];
78 2
            foreach ($config as $key => $value) {
79 2
                if (empty($value)) {
80 1
                    continue;
81
                }
82 2
                $key = $keys[$key] ?? $camelize($key);
83 2
                $normalized[$key] = $value;
84
            }
85
86 2
            return $normalized;
87 3
        };
88
    }
89
90 3
    private function addVariablesNode(): ArrayNodeDefinition
91
    {
92 3
        $node = $this->addArrayNode('variables');
93
        $node
94 3
            ->validate()
95 3
                ->always()
96
                ->then(static function ($variables) {
97 2
                    return \array_filter($variables, 'is_string');
98 3
                })
99 3
            ->end()
100
        ;
101
102 3
        return $node;
103
    }
104
105 3
    private function addErrorLoggingLevelNode(): ArrayNodeDefinition
106
    {
107 3
        $node = $this->addArrayNode('error_logging_level');
108
        $node
109 3
            ->validate()
110 3
                ->always()
111
                ->then(static function ($methods) {
112
                    $invalidMethods = \array_filter($methods, static function ($method) {
113 2
                        return false === \defined("E_{$method}");
114 2
                    });
115
116 2
                    if (empty($invalidMethods)) {
117
                        return \array_reduce($methods, static function ($level, $method) {
118 1
                            return $level |= \constant("E_{$method}");
119 1
                        });
120
                    }
121
122 1
                    throw new InvalidConfigurationException(\sprintf(
123 1
                        'The errors are not supported: "%s".',
124 1
                        \implode('", "', $invalidMethods)
125
                    ));
126 3
                })
127 3
            ->end()
128
        ;
129
130 3
        return $node;
131
    }
132
133 3
    private function addArrayNode(string $name): ArrayNodeDefinition
134
    {
135 3
        $node = new ArrayNodeDefinition($name);
136
        $node
137 3
            ->normalizeKeys(false)
138 3
            ->useAttributeAsKey('name')
139 3
            ->beforeNormalization()
140 3
                ->ifString()
141 3
                ->then(static function ($v) {
142 2
                    return \preg_split('/\s*,\s*/', $v, -1, \PREG_SPLIT_NO_EMPTY);
143 3
                })
144 3
            ->end()
145 3
            ->prototype('scalar')->end()
146
        ;
147
148 3
        return $node;
149
    }
150
}
151