Completed
Push — 1.0 ( 67b058...8c2284 )
by Rob
01:51
created

FileSystemLoaderFactory   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 177
Duplicated Lines 3.95 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 9
dl 7
loc 177
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getName() 0 4 1
B addConfiguration() 0 44 1
B resolveDataRoots() 0 16 5
A getBundleResourcePaths() 0 12 2
A getBundlePathsUsingMetadata() 0 6 1
A getBundlePathsUsingNamedObj() 0 16 3
A create() 7 7 1
A setupLocator() 0 10 1
A getLocatorDefinition() 0 8 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * This file is part of the `liip/LiipImagineBundle` project.
5
 *
6
 * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Liip\ImagineBundle\DependencyInjection\Factory\Loader;
13
14
use Liip\ImagineBundle\Exception\InvalidArgumentException;
15
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
16
use Symfony\Component\DependencyInjection\ChildDefinition;
17
use Symfony\Component\DependencyInjection\ContainerBuilder;
18
use Symfony\Component\DependencyInjection\Definition;
19
use Symfony\Component\DependencyInjection\DefinitionDecorator;
20
use Symfony\Component\DependencyInjection\Reference;
21
22
class FileSystemLoaderFactory extends AbstractLoaderFactory
23
{
24
    /**
25
     * {@inheritdoc}
26
     */
27 View Code Duplication
    public function create(ContainerBuilder $container, $loaderName, array $config)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
28
    {
29
        $definition = $this->getChildLoaderDefinition();
30
        $definition->replaceArgument(2, new Reference($this->setupLocator($loaderName, $config, $container)));
31
32
        return $this->setTaggedLoaderDefinition($loaderName, $definition, $container);
33
    }
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public function getName()
39
    {
40
        return 'filesystem';
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function addConfiguration(ArrayNodeDefinition $builder)
47
    {
48
        $builder
49
            ->children()
50
                ->enumNode('locator')
51
                    ->values(array('filesystem', 'filesystem_insecure'))
52
                    ->info('Using the "filesystem_insecure" locator is not recommended due to a less secure resolver mechanism, but is provided for those using heavily symlinked projects.')
53
                    ->defaultValue('filesystem')
54
                ->end()
55
                ->arrayNode('data_root')
56
                    ->beforeNormalization()
57
                    ->ifString()
58
                        ->then(function ($value) {
59
                            return array($value);
60
                        })
61
                    ->end()
62
                    ->treatNullLike(array())
63
                    ->treatFalseLike(array())
64
                    ->defaultValue(array('%kernel.root_dir%/../web'))
65
                    ->prototype('scalar')
66
                        ->cannotBeEmpty()
67
                    ->end()
68
                ->end()
69
                ->arrayNode('bundle_resources')
70
                    ->addDefaultsIfNotSet()
71
                    ->children()
72
                        ->booleanNode('enabled')
73
                            ->defaultFalse()
74
                        ->end()
75
                        ->enumNode('access_control_type')
76
                            ->values(array('blacklist', 'whitelist'))
77
                            ->info('Sets the access control method applied to bundle names in "access_control_list" into a blacklist or whitelist.')
78
                            ->defaultValue('blacklist')
79
                        ->end()
80
                        ->arrayNode('access_control_list')
81
                            ->defaultValue(array())
82
                            ->prototype('scalar')
83
                                ->cannotBeEmpty()
84
                            ->end()
85
                        ->end()
86
                    ->end()
87
                ->end()
88
            ->end();
89
    }
90
91
    /*
92
     * @param string[]         $staticPaths
93
     * @param array            $config
94
     * @param ContainerBuilder $container
95
     *
96
     * @return string[]
97
     */
98
    private function resolveDataRoots(array $staticPaths, array $config, ContainerBuilder $container)
99
    {
100
        if (false === $config['enabled']) {
101
            return $staticPaths;
102
        }
103
104
        $resourcePaths = array();
105
106
        foreach ($this->getBundleResourcePaths($container) as $name => $path) {
107
            if (('whitelist' === $config['access_control_type']) === in_array($name, $config['access_control_list']) && is_dir($path)) {
108
                $resourcePaths[$name] = $path;
109
            }
110
        }
111
112
        return array_merge($staticPaths, $resourcePaths);
113
    }
114
115
    /**
116
     * @param ContainerBuilder $container
117
     *
118
     * @return string[]
119
     */
120
    private function getBundleResourcePaths(ContainerBuilder $container)
121
    {
122
        if ($container->hasParameter('kernel.bundles_metadata')) {
123
            $paths = $this->getBundlePathsUsingMetadata($container->getParameter('kernel.bundles_metadata'));
124
        } else {
125
            $paths = $this->getBundlePathsUsingNamedObj($container->getParameter('kernel.bundles'));
126
        }
127
128
        return array_map(function ($path) {
129
            return $path.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'public';
130
        }, $paths);
131
    }
132
133
    /**
134
     * @param array[] $metadata
135
     *
136
     * @return string[]
137
     */
138
    private function getBundlePathsUsingMetadata(array $metadata)
139
    {
140
        return array_combine(array_keys($metadata), array_map(function ($data) {
141
            return $data['path'];
142
        }, $metadata));
143
    }
144
145
    /**
146
     * @param string[] $classes
147
     *
148
     * @return string[]
149
     */
150
    private function getBundlePathsUsingNamedObj(array $classes)
151
    {
152
        $paths = array();
153
154
        foreach ($classes as $c) {
155
            try {
156
                $r = new \ReflectionClass($c);
157
            } catch (\ReflectionException $exception) {
158
                throw new InvalidArgumentException(sprintf('Unable to resolve bundle "%s" while auto-registering bundle resource paths.', $c), null, $exception);
159
            }
160
161
            $paths[$r->getShortName()] = dirname($r->getFileName());
162
        }
163
164
        return $paths;
165
    }
166
167
    /**
168
     * @param string           $loaderName
169
     * @param array            $config
170
     * @param ContainerBuilder $container
171
     *
172
     * @return string
173
     */
174
    private function setupLocator($loaderName, array $config, ContainerBuilder $container)
175
    {
176
        $locator = $this->getLocatorDefinition($config);
177
        $locator->replaceArgument(0, $this->resolveDataRoots($config['data_root'], $config['bundle_resources'], $container));
178
179
        $locatorId = sprintf('liip_imagine.binary.locator.%s.%s', $config['locator'], $loaderName);
180
        $container->setDefinition($locatorId, $locator);
181
182
        return $locatorId;
183
    }
184
185
    /**
186
     * @param array $config
187
     *
188
     * @return Definition
189
     */
190
    private function getLocatorDefinition(array $config)
191
    {
192
        $key = sprintf('liip_imagine.binary.locator.%s', $config['locator']);
193
        $def = class_exists('\Symfony\Component\DependencyInjection\ChildDefinition') ?
194
            new ChildDefinition($key) : new DefinitionDecorator($key);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
195
196
        return $def;
197
    }
198
}
199