Configuration::addSvgSection()   C
last analyzed

Complexity

Conditions 13
Paths 10

Size

Total Lines 217
Code Lines 156

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 173
CRAP Score 13.0002

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 156
c 1
b 0
f 0
nc 10
nop 1
dl 0
loc 217
ccs 173
cts 175
cp 0.9886
crap 13.0002
rs 5.2933

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 ocubom/twig-extra-bundle
5
 *
6
 * © Oscar Cubo Medina <https://ocubom.github.io>
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 Ocubom\TwigExtraBundle\DependencyInjection;
13
14
use Iconify\IconsJSON\Finder as IconifyFinder;
15
use Ocubom\TwigExtraBundle\Extensions;
16
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
17
use Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition;
18
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
19
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
20
use Symfony\Component\Config\Definition\ConfigurationInterface;
21
22
class Configuration implements ConfigurationInterface
23
{
24 14
    public function getConfigTreeBuilder(): TreeBuilder
25
    {
26 14
        $builder = new TreeBuilder('ocubom_twig_extra');
27 14
        $root = $builder->getRootNode();
28
29
        // Register available extensions
30 14
        foreach (Extensions::getClasses() as $name => $class) {
31 14
            $call = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $name)));
32 14
            $this->{'add'.$call.'Section'}(
33 14
                $this->createSectionNode($root, $name, class_exists($class))
34 14
            );
35
        }
36
37
        // Headers listener included on this bundle
38 14
        $this->addHttpHeaderSection($root);
39
40 14
        return $builder;
41
    }
42
43 14
    private function createSectionNode(
44
        ArrayNodeDefinition $root,
45
        string $name,
46
        bool $canBeDisabled = true
47
    ): ArrayNodeDefinition {
48 14
        $node = $root->children()->arrayNode($name);
49
        assert($node instanceof ArrayNodeDefinition);
50
51 14
        $node->info(sprintf('Twig %s Extension', ucfirst($name)));
52 14
        $node->{$canBeDisabled ? 'canBeDisabled' : 'canBeEnabled'}();
53
54 14
        $enabled = $node->find('enabled');
55
        assert($enabled instanceof BooleanNodeDefinition);
56 14
        $enabled->info('Enable or disable this extension');
57
58 14
        return $node;
59
    }
60
61 14
    private function addHttpHeaderSection(ArrayNodeDefinition $root): void
62
    {
63 14
        $root
64 14
            ->fixXmlConfig('http_header')
65 14
            ->children()
66 14
                ->arrayNode('http_headers')
67 14
                    ->info(implode("\n", [
68 14
                        'HTTP headers that must be set.',
69 14
                        'The listener will only be registered if at least one rule is enabled.',
70 14
                    ]))
71 14
                    ->prototype('array')
72 14
                        ->treatFalseLike(['enabled' => false])
73 14
                        ->treatTrueLike(['enabled' => true])
74 14
                        ->treatNullLike(['enabled' => true])
75 14
                        ->children()
76 14
                            ->booleanNode('enabled')
77 14
                                ->info('Enable or disable this rule')
78 14
                                ->defaultTrue()
79 14
                            ->end()
80 14
                            ->scalarNode('name')
81 14
                                ->info('The header name to be added.')
82 14
                                ->example('X-UA-Compatible')
83 14
                                ->isRequired()
84 14
                                ->cannotBeEmpty()
85 14
                            ->end()
86 14
                            ->scalarNode('pattern')
87 14
                                ->info('A regular expression to extract the header value.')
88 14
                                ->example('@@[\p{Zs}]*<meta\s+(?:http-equiv="X-UA-Compatible"\s+content="([^"]+)"|content="([^"]+)"\s+http-equiv="X-UA-Compatible")\s*>\p{Zs}*\n?@i')
89 14
                                ->isRequired()
90 14
                                ->cannotBeEmpty()
91 14
                            ->end()
92 14
                            ->scalarNode('value')
93 14
                                ->info('The format of the value (printf processed using the matched value).')
94 14
                                ->example('%2$s')
95 14
                                ->isRequired()
96 14
                                ->cannotBeEmpty()
97 14
                            ->end()
98 14
                            ->scalarNode('replace')
99 14
                                ->info('The text that replaces the match in the original (printf processed using the matched value).')
100 14
                                ->defaultValue('%s')
101 14
                            ->end()
102 14
                            ->arrayNode('formats')
103 14
                                ->info('The response formats when this replacement must be done.')
104 14
                                ->example('["text/html"]')
105 14
                                ->prototype('scalar')->end()
106 14
                            ->end()
107 14
                        ->end()
108 14
                    ->end()
109 14
                ->end()
110 14
            ->end();
111
    }
112
113 14
    private function addHtmlSection(ArrayNodeDefinition $root): void
114
    {
115 14
        $children = $root
116 14
            ->children()
117 14
                ->arrayNode('compression')
118 14
                    ->info('Compress HTML output')
119 14
                    ->addDefaultsIfNotSet()
120 14
                    ->children();
121
122 14
        $children
123 14
            ->booleanNode('force')
124 14
                ->info('Force compression')
125 14
                ->defaultFalse()
126 14
            ->end();
127
128 14
        $children
129 14
            ->enumNode('level')
130 14
                ->info('The level of compression to use')
131 14
                ->defaultValue('smallest')
132 14
                ->values([
133 14
                    'none',
134 14
                    'fastest',
135 14
                    'normal',
136 14
                    'smallest',
137 14
                ])
138 14
            ->end();
139
    }
140
141 14
    private function addSvgSection(ArrayNodeDefinition $root): void
142
    {
143 14
        $providers = [
144 14
            'file_system' => [
145 14
                'name' => 'Local File System',
146 14
                'paths' => [
147 14
                    '%kernel.project_dir%/assets',
148 14
                    '%kernel.project_dir%/node_modules',
149 14
                ],
150 14
            ],
151 14
            'font_awesome' => [
152 14
                'name' => 'FontAwesome',
153 14
                'paths' => [
154 14
                    '%kernel.project_dir%/node_modules/@fortawesome/fontawesome-pro/svgs',
155 14
                    '%kernel.project_dir%/node_modules/@fortawesome/fontawesome-free/svgs',
156 14
                    '%kernel.project_dir%/vendor/fortawesome/font-awesome/svgs/',
157 14
                ],
158 14
            ],
159 14
            'iconify' => [
160 14
                'name' => 'Iconify',
161 14
                'paths' => [
162 14
                    '%kernel.project_dir%/node_modules/@iconify-json/',
163 14
                    '%kernel.project_dir%/node_modules/@iconify/json/',
164 14
                    '%kernel.project_dir%/vendor/iconify/json/',
165 14
                    class_exists(IconifyFinder::class) ? IconifyFinder::rootDir() : '',
166 14
                ],
167 14
                'runtime' => function (NodeBuilder $parent): void {
168 14
                    $parent
169 14
                        ->arrayNode('svg_framework')
170 14
                            ->info('Enable SVG Framework Server Side Rendering on classes (empty to disable).')
171 14
                            ->defaultValue(['iconify', 'iconify-inline'])
172 14
                            ->prototype('scalar')->end()
173 14
                        ->end();
174
175 14
                    $parent
176 14
                        ->arrayNode('web_component')
177 14
                            ->info('Enable Web Component Server Side Rendering on tags (empty to disable).')
178 14
                            ->defaultValue(['icon', 'iconify-icon'])
179 14
                            ->prototype('scalar')->end()
180 14
                        ->end();
181 14
                },
182 14
                'loader' => function (NodeBuilder $parent): void {
183 14
                    $parent
184 14
                        ->scalarNode('cache_dir')
185 14
                            ->info('Enable cache on this path (empty to disable).')
186 14
                            ->defaultValue('%kernel.cache_dir%/iconify')
187 14
                        ->end();
188 14
                },
189 14
            ],
190 14
        ];
191
192 14
        $root
193 14
            ->beforeNormalization()
194 14
                ->always(static function ($v) {
195
                    // Convert to finders (1.x) configuration
196 12
                    $v['finders'] = $v['finders'] ?? [];
197
                    // Default finder
198 12
                    $v['finders']['default'] = $v['finders']['default'] ?? $v['search_path'] ?? [];
199 12
                    unset($v['search_path']);
200
                    // FontAwesome
201 12
                    $v['finders']['fontawesome'] = $v['finders']['fontawesome'] ?? $v['fontawesome']['search_path'] ?? [];
202 12
                    unset($v['fontawesome']);
203
204
                    // Convert to providers (2.x) configuration
205 12
                    foreach ($v['finders'] as $key => $val) {
206 12
                        if (empty($val)) {
207 10
                            continue;
208
                        }
209
210
                        switch ($key) {
211 2
                            case 'default':
212 2
                                $v['providers']['file_system']['paths'] = $v['providers']['file_system']['paths'] ?? $val;
213 2
                                break;
214
215 2
                            case 'fontawesome':
216 2
                                $v['providers']['font_awesome']['paths'] = $v['providers']['font_awesome']['paths'] ?? $val;
217 2
                                break;
218
219
                            default:
220
                                $v['providers'][$key]['paths'] = $v['providers'][$key]['paths'] ?? $val;
221
                                break;
222
                        }
223
                    }
224 12
                    unset($v['finders']);
225
226 12
                    return $v;
227 14
                })
228 14
            ->end()
229 14
            ->validate()
230 14
                ->always(function ($v) {
231
                    // Clean deprecated configuration
232 12
                    unset($v['search_path']);
233 12
                    unset($v['fontawesome']);
234 12
                    unset($v['finders']);
235
236
                    // Enable/Disable providers
237 12
                    $enabled = 0;
238 12
                    foreach (array_keys($v['providers'] ?? []) as $key) {
239 12
                        $v['providers'][$key]['paths'] = array_filter($v['providers'][$key]['paths'] ?? []);
240 12
                        $v['providers'][$key]['enabled'] = $v['providers'][$key]['enabled'] && count($v['providers'][$key]['paths']) > 0;
241
242 12
                        if ($v['providers'][$key]['enabled']) {
243 12
                            ++$enabled;
244
                        }
245
                    }
246
247
                    // Disable if no provider are enabled
248 12
                    $v['enabled'] = $v['enabled'] && $enabled > 0;
249
250 12
                    return $v;
251 14
                })
252 14
            ->end();
253
254
        // Add providers (2.x) configuration
255 14
        $parent = $root
256 14
            ->fixXmlConfig('provider')
257 14
            ->children()
258 14
                ->arrayNode('providers')
259 14
                    ->info('SVG providers.')
260 14
                    ->addDefaultsIfNotSet();
261
262 14
        foreach ($providers as $key => $val) {
263 14
            $provider = $parent
264 14
                ->children()
265 14
                    ->arrayNode($key);
266
267 14
            $children = $provider
268 14
                    ->info(sprintf('%s provider.', $val['name']))
269 14
                    ->canBeDisabled()
270 14
                    ->children();
271
272 14
            $enabled = $provider->find('enabled');
273
            assert($enabled instanceof BooleanNodeDefinition);
274 14
            $enabled->info('Enable or disable this provider.');
275
276
            // Provider paths
277 14
            $provider->fixXmlConfig('path');
278 14
            $children
279 14
                ->arrayNode('paths')
280 14
                    ->info(sprintf('The paths where the %s files will be searched for.', $val['name']))
281 14
                    // ->example(sprintf('["%s"]', implode('", "', $val['paths'])))
282 14
                    ->defaultValue($val['paths'])
283 14
                    ->prototype('scalar')->end()
284 14
                ->end();
285
286
            // Extra configuration
287 14
            if (is_callable($val['loader'] ?? null)) {
288 14
                $val['loader']($children->arrayNode('loader')
289 14
                    ->info(sprintf('Loader configuration options for %s', $val['name']))
290 14
                    ->addDefaultsIfNotSet()
291 14
                    ->children()
292 14
                );
293
            }
294
295 14
            if (is_callable($val['runtime'] ?? null)) {
296 14
                $val['runtime']($children->arrayNode('runtime')
297 14
                    ->info(sprintf('Runtime configuration options for %s', $val['name']))
298 14
                    ->addDefaultsIfNotSet()
299 14
                    ->children()
300 14
                );
301
            }
302
        }
303
304
        // Add finders (1.x) configuration
305 14
        $root
306 14
            ->fixXmlConfig('finder')
307 14
            ->children()
308 14
                ->arrayNode('finders')
309 14
                    ->setDeprecated(
310 14
                        'ocubom/twig-extra-bundle',
311 14
                        '1.3',
312 14
                        'The "%node%" option is deprecated. Use "providers" instead.'
313 14
                    )
314 14
                    ->info('The paths where SVG files will be searched for.')
315 14
                    ->children()
316 14
                        ->arrayNode('default')
317 14
                            ->info('The default paths where the SVG files will be searched for.')
318 14
                            ->example(sprintf('["%s"]', implode('", "', $providers['file_system']['paths'])))
319 14
                            // ->defaultValue($providers['file_system']['paths'])
320 14
                            ->prototype('scalar')->end()
321 14
                        ->end()
322 14
                        ->arrayNode('fontawesome')
323 14
                            ->info('The paths where the FontAwesome files will be searched for.')
324 14
                            ->example(sprintf('["%s"]', implode('", "', $providers['font_awesome']['paths'])))
325 14
                            // ->defaultValue($providers['font_awesome']['paths'])
326 14
                            ->prototype('scalar')->end()
327 14
                        ->end()
328 14
                    ->end()
329 14
                ->end()
330 14
                ->arrayNode('search_path')
331 14
                    ->setDeprecated(
332 14
                        'ocubom/twig-extra-bundle',
333 14
                        '1.2',
334 14
                        'The "%node%" option is deprecated. Use "providers.filesystem" instead.'
335 14
                    )
336 14
                    ->info('The paths where the SVG files will be searched for.')
337 14
                    ->example(sprintf('["%s"]', implode('", "', $providers['file_system']['paths'])))
338 14
                    // ->defaultValue($providers['file_system']['paths'])
339 14
                    ->prototype('scalar')->end()
340 14
                ->end()
341 14
                ->arrayNode('fontawesome')
342 14
                    ->setDeprecated(
343 14
                        'ocubom/twig-extra-bundle',
344 14
                        '1.2',
345 14
                        'The "%node%" option is deprecated. Use "providers.fontawesome" instead.'
346 14
                    )
347 14
                    ->info('Configuration for FontAwesome.')
348 14
                    ->children()
349 14
                        ->arrayNode('search_path')
350 14
                            ->info('The paths where the FontAwesome files will be searched for.')
351 14
                            ->example(sprintf('["%s"]', implode('", "', $providers['font_awesome']['paths'])))
352 14
                            // ->defaultValue($providers['font_awesome']['paths'])
353 14
                            ->prototype('scalar')->end()
354 14
                        ->end()
355 14
                    ->end()
356 14
                ->end()
357 14
            ->end();
358
    }
359
360 14
    private function addWebpackEncoreSection(ArrayNodeDefinition $root): void
361
    {
362 14
        $defaultPaths = [
363 14
            '%kernel.project_dir%/public/build',
364 14
        ];
365
366 14
        $root
367 14
            ->children()
368 14
                ->arrayNode('output_paths')
369 14
                    ->info('Paths where Symfony Encore will generate its output.')
370 14
                    // ->example(sprintf('["%s"]', implode('", "', $defaultPaths)))
371 14
                    ->defaultValue($defaultPaths)
372 14
                    ->prototype('scalar')->end()
373 14
            ->end();
374
    }
375
}
376