Completed
Pull Request — master (#223)
by Kevin
04:45
created

Configuration::getConfigTreeBuilder()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 66

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 49
CRAP Score 6.0002

Importance

Changes 0
Metric Value
dl 0
loc 66
ccs 49
cts 50
cp 0.98
rs 8.1195
c 0
b 0
f 0
cc 6
nc 2
nop 0
crap 6.0002

How to fix   Long Method   

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
namespace Liip\MonitorBundle\DependencyInjection;
4
5
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
6
use Symfony\Component\Config\Definition\ConfigurationInterface;
7
8
/**
9
 * This class contains the configuration information for the bundle.
10
 *
11
 * This information is solely responsible for how the different configuration
12
 * sections are normalized, and merged.
13
 *
14
 * @author Lukas Kahwe Smith <[email protected]>
15
 */
16
class Configuration implements ConfigurationInterface
17
{
18
    /**
19
     * Generates the configuration tree.
20
     *
21
     * @return TreeBuilder
22
     */
23 49
    public function getConfigTreeBuilder()
24
    {
25 49
        $treeBuilder = new TreeBuilder('liip_monitor');
26
27
        // Keep compatibility with symfony/config < 4.2
28 49
        if (\method_exists($treeBuilder, 'getRootNode')) {
29 49
            $rootNode = $treeBuilder->getRootNode();
30
        } else {
31
            $rootNode = $treeBuilder->root('liip_monitor');
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Config...der\TreeBuilder::root() has been deprecated with message: since Symfony 4.3, pass the root name to the constructor instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
32
        }
33
34
        $rootNode
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Config...\Builder\NodeDefinition as the method children() does only exist in the following sub-classes of Symfony\Component\Config...\Builder\NodeDefinition: Symfony\Component\Config...der\ArrayNodeDefinition. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
35 49
            ->beforeNormalization()
36
                ->always(function ($v) {
37 49
                    if (empty($v['default_group'])) {
38 49
                        $v['default_group'] = 'default';
39
                    }
40
41 49
                    if (isset($v['checks']) && is_array($v['checks']) && !isset($v['checks']['groups'])) {
42 40
                        $checks = $v['checks'];
43 40
                        unset($v['checks']);
44
45 40
                        $v['checks']['groups'][$v['default_group']] = $checks;
46
                    }
47
48 49
                    return $v;
49 49
                })
50 49
            ->end()
51 49
            ->children()
52 49
                ->booleanNode('enable_controller')->defaultFalse()->end()
53 49
                ->scalarNode('view_template')->defaultNull()->end()
54 49
                ->integerNode('failure_status_code')
55 49
                    ->min(100)->max(598)
56 49
                    ->defaultValue(502)
57 49
                ->end()
58 49
                ->booleanNode('is_lazy_run')
59 49
                    ->defaultValue(true)
60 49
                ->end()
61 49
                ->arrayNode('mailer')
62 49
                    ->canBeEnabled()
63 49
                    ->children()
64 49
                        ->arrayNode('recipient')
65 49
                            ->isRequired()->requiresAtLeastOneElement()
66 49
                            ->prototype('scalar')->end()
67 49
                            ->beforeNormalization()
68 49
                                ->ifString()
69
                                ->then(function ($v) { return [$v]; })
70 49
                            ->end()
71 49
                        ->end()
72 49
                        ->scalarNode('sender')->isRequired()->cannotBeEmpty()->end()
73 49
                        ->scalarNode('subject')->isRequired()->cannotBeEmpty()->end()
74 49
                        ->booleanNode('send_on_warning')->defaultTrue()->end()
75 49
                    ->end()
76 49
                ->end()
77 49
                ->scalarNode('default_group')->defaultValue('default')->end()
78 49
                ->arrayNode('checks')
79 49
                    ->canBeUnset()
80 49
                    ->children()
81 49
                        ->append($this->createGroupsNode())
82 49
                    ->end()
83 49
                ->end()
84 49
            ->end()
85 49
        ->end();
86
87 49
        return $treeBuilder;
88
    }
89
90 49
    private function createGroupsNode()
91
    {
92 49
        $builder = new TreeBuilder('groups');
93
94
        // Keep compatibility with symfony/config < 4.2
95 49
        if (\method_exists($builder, 'getRootNode')) {
96 49
            $node = $builder->getRootNode();
97
        } else {
98
            $node = $builder->root('groups');
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Config...der\TreeBuilder::root() has been deprecated with message: since Symfony 4.3, pass the root name to the constructor instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
99
        }
100
        $node
101 49
            ->requiresAtLeastOneElement()
102 49
            ->info('Grouping checks')
103 49
            ->useAttributeAsKey('name')
104 49
            ->prototype('array')
105 49
                ->children()
106 49
                    ->arrayNode('php_extensions')
107 49
                        ->info('Validate that a named extension or a collection of extensions is available')
108 49
                        ->example('session.use_only_cookies: false')
109 49
                        ->prototype('scalar')->end()
110 49
                    ->end()
111 49
                    ->arrayNode('php_flags')
112 49
                        ->info('Pairs of a PHP setting and an expected value')
113 49
                        ->example('session.use_only_cookies: false')
114 49
                        ->useAttributeAsKey('setting')
115 49
                        ->prototype('scalar')->defaultValue(true)->end()
116 49
                    ->end()
117 49
                    ->arrayNode('php_version')
118 49
                        ->info('Pairs of a version and a comparison operator')
119 49
                        ->example('5.4.15: >=')
120 49
                        ->useAttributeAsKey('version')
121 49
                        ->prototype('scalar')->end()
122 49
                    ->end()
123 49
                    ->variableNode('process_running')
124 49
                        ->info('Process name/pid or an array of process names/pids')
125 49
                        ->example('[apache, foo]')
126 49
                    ->end()
127 49
                    ->arrayNode('readable_directory')
128 49
                        ->info('Validate that a given path (or a collection of paths) is a dir and is readable')
129 49
                        ->example('["%kernel.cache_dir%"]')
130 49
                        ->prototype('scalar')->end()
131 49
                    ->end()
132 49
                    ->arrayNode('writable_directory')
133 49
                        ->info('Validate that a given path (or a collection of paths) is a dir and is writable')
134 49
                        ->example('["%kernel.cache_dir%"]')
135 49
                        ->prototype('scalar')->end()
136 49
                    ->end()
137 49
                    ->arrayNode('class_exists')
138 49
                        ->info('Validate that a class or a collection of classes is available')
139 49
                        ->example('["Lua", "My\Fancy\Class"]')
140 49
                        ->prototype('scalar')->end()
141 49
                    ->end()
142 49
                    ->scalarNode('cpu_performance')
143 49
                        ->info('Benchmark CPU performance and return failure if it is below the given ratio')
144 49
                        ->example('1.0 # This is the power of an EC2 micro instance')
145 49
                    ->end()
146 49
                    ->arrayNode('disk_usage')
147 49
                        ->info('Checks to see if the disk usage is below warning/critical percent thresholds')
148 49
                        ->children()
149 49
                            ->integerNode('warning')->defaultValue(70)->end()
150 49
                            ->integerNode('critical')->defaultValue(90)->end()
151 49
                            ->scalarNode('path')->defaultValue('%kernel.cache_dir%')->end()
152 49
                        ->end()
153 49
                    ->end()
154 49
                    ->arrayNode('symfony_requirements')
155 49
                        ->info('Checks Symfony2 requirements file')
156 49
                        ->children()
157 49
                            ->scalarNode('file')->defaultValue('%kernel.root_dir%/SymfonyRequirements.php')->end()
158 49
                        ->end()
159 49
                    ->end()
160 49
                    ->arrayNode('opcache_memory')
161 49
                        ->info('Checks to see if the OpCache memory usage is below warning/critical thresholds')
162 49
                        ->children()
163 49
                            ->integerNode('warning')->defaultValue(70)->end()
164 49
                            ->integerNode('critical')->defaultValue(90)->end()
165 49
                        ->end()
166 49
                    ->end()
167 49
                    ->arrayNode('apc_memory')
168 49
                        ->info('Checks to see if the APC memory usage is below warning/critical thresholds')
169 49
                        ->children()
170 49
                            ->integerNode('warning')->defaultValue(70)->end()
171 49
                            ->integerNode('critical')->defaultValue(90)->end()
172 49
                        ->end()
173 49
                    ->end()
174 49
                    ->arrayNode('apc_fragmentation')
175 49
                        ->info('Checks to see if the APC fragmentation is below warning/critical thresholds')
176 49
                        ->children()
177 49
                            ->integerNode('warning')->defaultValue(70)->end()
178 49
                            ->integerNode('critical')->defaultValue(90)->end()
179 49
                        ->end()
180 49
                    ->end()
181 49
                    ->variableNode('doctrine_dbal')
182 49
                        ->defaultNull()
183 49
                        ->info('Connection name or an array of connection names')
184 49
                        ->example('[default, crm]')
185 49
                    ->end()
186 49
                    ->variableNode('doctrine_mongodb')
187 49
                        ->defaultNull()
188 49
                        ->info('Connection name or an array of connection names')
189 49
                        ->example('[default, crm]')
190 49
                    ->end()
191 49
                    ->arrayNode('doctrine_migrations')
192 49
                        ->useAttributeAsKey('name')
193 49
                        ->info('Checks to see if migrations from specified configuration file are applied')
194 49
                        ->prototype('array')
195 49
                            ->children()
196 49
                                ->scalarNode('configuration_file')
197 49
                                    ->info('Absolute path to doctrine migrations configuration')
198 49
                                ->end()
199 49
                                ->scalarNode('connection')
200 49
                                    ->isRequired()
201 49
                                    ->cannotBeEmpty()
202 49
                                    ->info('Connection name from doctrine DBAL configuration')
203 49
                                ->end()
204 49
                            ->end()
205 49
                            ->beforeNormalization()
206 49
                                ->ifString()
207
                                ->then(function ($value) {
208
                                    if (is_string($value)) {
209
                                        $value = ['connection' => $value];
210
                                    }
211
212
                                    return $value;
213 49
                                })
214 49
                            ->end()
215 49
                            ->validate()
216
                                ->always(function ($value) {
217
                                    if (is_array($value) && !isset($value['configuration_file']) && !class_exists('Doctrine\\Bundle\\MigrationsBundle\\Command\\DoctrineCommand')) {
218
                                        throw new \InvalidArgumentException('You should explicitly define "configuration_file" parameter or install doctrine/doctrine-migrations-bundle to use empty parameter.');
219
                                    }
220
221
                                    return $value;
222 49
                                })
223 49
                            ->end()
224 49
                        ->end()
225 49
                        ->example(
226
                            [
227
                                'application_migrations' => [
228 49
                                    'configuration_file' => '%kernel.root_dir%/Resources/config/migrations.yml',
229
                                    'connection' => 'default',
230
                                ],
231
                                'migrations_with_doctrine_bundle' => [
232
                                    'connection' => 'default',
233
                                ],
234
                                'migrations_with_doctrine_bundle_v2' => 'default',
235
                            ]
236
                        )
237 49
                    ->end()
238 49
                    ->arrayNode('memcache')
239 49
                        ->info('Check if MemCache extension is loaded and given server is reachable')
240 49
                        ->useAttributeAsKey('name')
241 49
                        ->prototype('array')
242 49
                            ->children()
243 49
                                ->scalarNode('host')->defaultValue('localhost')->end()
244 49
                                ->integerNode('port')->defaultValue(11211)->end()
245 49
                            ->end()
246 49
                        ->end()
247 49
                    ->end()
248 49
                    ->arrayNode('memcached')
249 49
                        ->info('Check if MemCached extension is loaded and given server is reachable')
250 49
                        ->useAttributeAsKey('name')
251 49
                        ->prototype('array')
252 49
                            ->children()
253 49
                                ->scalarNode('host')->defaultValue('localhost')->end()
254 49
                                ->integerNode('port')->defaultValue(11211)->end()
255 49
                            ->end()
256 49
                        ->end()
257 49
                    ->end()
258 49
                    ->arrayNode('redis')
259 49
                        ->info('Validate that a Redis service is running')
260 49
                        ->useAttributeAsKey('name')
261 49
                        ->beforeNormalization()
262 49
                            ->ifString()
263
                            ->then(function ($v) { return ['dsn' => $v]; })
264 49
                        ->end()
265 49
                        ->prototype('array')
266 49
                            ->children()
267 49
                                ->scalarNode('host')->defaultValue('localhost')->end()
268 49
                                ->integerNode('port')->defaultValue(6379)->end()
269 49
                                ->scalarNode('password')->defaultNull()->end()
270 49
                                ->scalarNode('dsn')->defaultNull()->end()
271 49
                            ->end()
272 49
                        ->end()
273 49
                    ->end()
274 49
                    ->arrayNode('http_service')
275 49
                        ->info('Attempt connection to given HTTP host and (optionally) check status code and page content')
276 49
                        ->useAttributeAsKey('name')
277 49
                        ->prototype('array')
278 49
                            ->children()
279 49
                                ->scalarNode('host')->defaultValue('localhost')->end()
280 49
                                ->integerNode('port')->defaultValue(80)->end()
281 49
                                ->scalarNode('path')->defaultValue('/')->end()
282 49
                                ->integerNode('status_code')->defaultValue(200)->end()
283 49
                                ->scalarNode('content')->defaultNull()->end()
284 49
                            ->end()
285 49
                        ->end()
286 49
                    ->end()
287 49
                    ->arrayNode('guzzle_http_service')
288 49
                        ->info('Attempt connection using Guzzle to given HTTP host and (optionally) check status code and page content')
289 49
                        ->useAttributeAsKey('name')
290 49
                        ->prototype('array')
291 49
                            ->children()
292 49
                                ->scalarNode('url')->defaultValue('localhost')->end()
293 49
                                ->variableNode('headers')->defaultValue([])->end()
294 49
                                ->variableNode('options')->defaultValue([])->end()
295 49
                                ->integerNode('status_code')->defaultValue(200)->end()
296 49
                                ->scalarNode('content')->defaultNull()->end()
297 49
                                ->scalarNode('method')->defaultValue('GET')->end()
298 49
                                ->scalarNode('body')->defaultNull()->end()
299 49
                            ->end()
300 49
                        ->end()
301 49
                    ->end()
302 49
                    ->arrayNode('rabbit_mq')
303 49
                        ->info('Validate that a RabbitMQ service is running')
304 49
                        ->useAttributeAsKey('name')
305 49
                        ->beforeNormalization()
306 49
                            ->ifString()
307
                            ->then(function ($v) { return ['dsn' => $v]; })
308 49
                        ->end()
309 49
                        ->prototype('array')
310 49
                            ->children()
311 49
                                ->scalarNode('host')->defaultValue('localhost')->end()
312 49
                                ->integerNode('port')->defaultValue(5672)->end()
313 49
                                ->scalarNode('user')->defaultValue('guest')->end()
314 49
                                ->scalarNode('password')->defaultValue('guest')->end()
315 49
                                ->scalarNode('vhost')->defaultValue('/')->end()
316 49
                                ->scalarNode('dsn')->defaultNull()->end()
317 49
                            ->end()
318 49
                        ->end()
319 49
                    ->end()
320 49
                    ->booleanNode('symfony_version')
321 49
                        ->info('Checks the version of this app against the latest stable release')
322 49
                    ->end()
323 49
                    ->arrayNode('custom_error_pages')
324 49
                        ->info('Checks if error pages have been customized for given error codes')
325 49
                        ->children()
326 49
                            ->arrayNode('error_codes')
327 49
                                ->isRequired()
328 49
                                ->requiresAtLeastOneElement()
329 49
                                ->prototype('scalar')->end()
330 49
                            ->end()
331 49
                            ->scalarNode('path')->defaultValue('%kernel.root_dir%')->end()
332 49
                            ->scalarNode('controller')->defaultValue('%twig.exception_listener.controller%')->end()
333 49
                        ->end()
334 49
                    ->end()
335 49
                    ->arrayNode('security_advisory')
336 49
                        ->info('Checks installed composer dependencies against the SensioLabs Security Advisory database')
337 49
                        ->children()
338 49
                            ->scalarNode('lock_file')->defaultValue('%kernel.root_dir%'.'/../composer.lock')->end()
339 49
                        ->end()
340 49
                    ->end()
341 49
                    ->arrayNode('stream_wrapper_exists')
342 49
                        ->info('Validate that a stream wrapper or collection of stream wrappers exists')
343 49
                        ->example('[\'zlib\', \'bzip2\', \'zip\']')
344 49
                        ->prototype('scalar')->end()
345 49
                    ->end()
346 49
                    ->arrayNode('file_ini')
347 49
                        ->info('Find and validate INI files')
348 49
                        ->example('[\'path/to/my.ini\']')
349 49
                        ->prototype('scalar')->end()
350 49
                    ->end()
351 49
                    ->arrayNode('file_json')
352 49
                        ->info('Find and validate JSON files')
353 49
                        ->example('[\'path/to/my.json\']')
354 49
                        ->prototype('scalar')->end()
355 49
                    ->end()
356 49
                    ->arrayNode('file_xml')
357 49
                        ->info('Find and validate XML files')
358 49
                        ->example('[\'path/to/my.xml\']')
359 49
                        ->prototype('scalar')->end()
360 49
                    ->end()
361 49
                    ->arrayNode('file_yaml')
362 49
                        ->info('Find and validate YAML files')
363 49
                        ->example('[\'path/to/my.yml\']')
364 49
                        ->prototype('scalar')->end()
365 49
                    ->end()
366 49
                    ->arrayNode('pdo_connections')
367 49
                        ->info('PDO connections to check for connection')
368 49
                        ->useAttributeAsKey('name')
369 49
                        ->prototype('array')
370 49
                            ->children()
371 49
                                ->scalarNode('dsn')->defaultNull()->end()
372 49
                                ->scalarNode('username')->defaultNull()->end()
373 49
                                ->scalarNode('password')->defaultNull()->end()
374 49
                                ->integerNode('timeout')->defaultValue(1)->end()
375 49
                            ->end()
376 49
                        ->end()
377 49
                    ->end()
378 49
                    ->arrayNode('expressions')
379 49
                        ->useAttributeAsKey('alias')
380 49
                        ->info('Checks that fail/warn when given expression is false (expressions are evaluated with symfony/expression-language)')
381 49
                        ->example([
382
                            'opcache' => [
383 49
                                'label' => 'OPcache',
384
                                'warning_expression' => "ini('opcache.revalidate_freq') > 0",
385
                                'critical_expression' => "ini('opcache.enable')",
386
                                'warning_message' => 'OPcache not optimized for production',
387
                                'critical_message' => 'OPcache not enabled',
388
                            ],
389
                        ])
390 49
                        ->prototype('array')
391 49
                            ->addDefaultsIfNotSet()
392 49
                            ->validate()
393
                                ->ifTrue(function ($value) {
394 2
                                    return !$value['warning_expression'] && !$value['critical_expression'];
395 49
                                })
396 49
                                ->thenInvalid('A warning_expression or a critical_expression must be set.')
397 49
                            ->end()
398 49
                            ->children()
399 49
                                ->scalarNode('label')->isRequired()->end()
400 49
                                ->scalarNode('warning_expression')
401 49
                                ->defaultNull()
402 49
                                ->example('ini(\'apc.stat\') == 0')
403 49
                            ->end()
404 49
                            ->scalarNode('critical_expression')
405 49
                            ->defaultNull()
406 49
                            ->example('ini(\'short_open_tag\') == 1')
407 49
                        ->end()
408 49
                        ->scalarNode('warning_message')->defaultNull()->end()
409 49
                        ->scalarNode('critical_message')->defaultNull()->end()
410 49
                    ->end()
411 49
                ->end()
412 49
            ->end()
413
        ;
414
415 49
        return $node;
416
    }
417
}
418