Completed
Pull Request — 1.0 (#937)
by
unknown
02:35
created

FileSystemLoaderFactory::createLocatorReference()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
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 Liip\ImagineBundle\Utility\Framework\SymfonyFramework;
16
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
17
use Symfony\Component\DependencyInjection\ChildDefinition;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\ContainerInterface;
20
use Symfony\Component\DependencyInjection\DefinitionDecorator;
21
use Symfony\Component\DependencyInjection\Reference;
22
23
class FileSystemLoaderFactory extends AbstractLoaderFactory
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function create(ContainerBuilder $container, $loaderName, array $config)
29
    {
30
        $parentLocatorServiceId = sprintf('liip_imagine.binary.locator.%s', $config['locator']);
31
32
        $locatorDefinition = class_exists('\Symfony\Component\DependencyInjection\ChildDefinition') ?
33
            new ChildDefinition($parentLocatorServiceId) : new DefinitionDecorator($parentLocatorServiceId);
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...
34
35
        $locatorServiceId = sprintf('liip_imagine.binary.locator.%s.%s', $config['locator'], $loaderName);
36
        $container->setDefinition($locatorServiceId, $locatorDefinition);
37
38
        $locatorDefinition->replaceArgument(0, $this->resolveDataRoots($config['data_root'], $config['bundle_resources'], $container));
39
40
        $definition = $this->getChildLoaderDefinition();
41
        $definition->replaceArgument(2, new Reference($locatorServiceId));
42
43
        return $this->setTaggedLoaderDefinition($loaderName, $definition, $container);
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    public function getName()
50
    {
51
        return 'filesystem';
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function addConfiguration(ArrayNodeDefinition $builder)
58
    {
59
        $builder
60
            ->children()
61
                ->enumNode('locator')
62
                    ->values(array('filesystem', 'filesystem_insecure'))
63
                    ->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.')
64
                    ->defaultValue('filesystem')
65
                ->end()
66
                ->arrayNode('data_root')
67
                    ->beforeNormalization()
68
                    ->ifString()
69
                        ->then(function ($value) {
70
                            return array($value);
71
                        })
72
                    ->end()
73
                    ->treatNullLike(array())
74
                    ->treatFalseLike(array())
75
                    ->defaultValue(array('%kernel.root_dir%/../web'))
76
                    ->prototype('scalar')
77
                        ->cannotBeEmpty()
78
                    ->end()
79
                ->end()
80
                ->arrayNode('bundle_resources')
81
                    ->addDefaultsIfNotSet()
82
                    ->children()
83
                        ->booleanNode('enabled')
84
                            ->defaultFalse()
85
                        ->end()
86
                        ->enumNode('access_control_type')
87
                            ->values(array('blacklist', 'whitelist'))
88
                            ->info('Sets the access control method applied to bundle names in "access_control_list" into a blacklist or whitelist.')
89
                            ->defaultValue('blacklist')
90
                        ->end()
91
                        ->arrayNode('access_control_list')
92
                            ->defaultValue(array())
93
                            ->prototype('scalar')
94
                                ->cannotBeEmpty()
95
                            ->end()
96
                        ->end()
97
                    ->end()
98
                ->end()
99
            ->end();
100
    }
101
102
    /*
103
     * @param string[]         $staticPaths
104
     * @param array            $config
105
     * @param ContainerBuilder $container
106
     *
107
     * @return string[]
108
     */
109
    private function resolveDataRoots(array $staticPaths, array $config, ContainerBuilder $container)
110
    {
111
        if (false === $config['enabled']) {
112
            return $staticPaths;
113
        }
114
115
        $resourcePaths = array();
116
117
        foreach ($this->getBundleResourcePaths($container) as $name => $path) {
118
            if (('whitelist' === $config['access_control_type']) === in_array($name, $config['access_control_list']) && is_dir($path)) {
119
                $resourcePaths[$name] = $path;
120
            }
121
        }
122
123
        return array_merge($staticPaths, $resourcePaths);
124
    }
125
126
    /**
127
     * @param ContainerBuilder $container
128
     *
129
     * @return string[]
130
     */
131
    private function getBundleResourcePaths(ContainerBuilder $container)
132
    {
133
        if ($container->hasParameter('kernel.bundles_metadata')) {
134
            $paths = $this->getBundlePathsUsingMetadata($container->getParameter('kernel.bundles_metadata'));
135
        } else {
136
            $paths = $this->getBundlePathsUsingNamedObj($container->getParameter('kernel.bundles'));
137
        }
138
139
        return array_map(function ($path) {
140
            return $path.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'public';
141
        }, $paths);
142
    }
143
144
    /**
145
     * @param array[] $metadata
146
     *
147
     * @return string[]
148
     */
149
    private function getBundlePathsUsingMetadata(array $metadata)
150
    {
151
        return array_combine(array_keys($metadata), array_map(function ($data) {
152
            return $data['path'];
153
        }, $metadata));
154
    }
155
156
    /**
157
     * @param string[] $classes
158
     *
159
     * @return string[]
160
     */
161
    private function getBundlePathsUsingNamedObj(array $classes)
162
    {
163
        $paths = array();
164
165
        foreach ($classes as $c) {
166
            try {
167
                $r = new \ReflectionClass($c);
168
            } catch (\ReflectionException $exception) {
169
                throw new InvalidArgumentException(sprintf('Unable to resolve bundle "%s" while auto-registering bundle resource paths.', $c), null, $exception);
170
            }
171
172
            $paths[$r->getShortName()] = dirname($r->getFileName());
173
        }
174
175
        return $paths;
176
    }
177
}
178