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