Completed
Push — master ( 55b776...163790 )
by Eric
08:26
created

createClassMetadataLoaderDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Ivory Serializer bundle package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\SerializerBundle\DependencyInjection;
13
14
use Ivory\Serializer\Mapping\Loader\AnnotationClassMetadataLoader;
15
use Ivory\Serializer\Mapping\Loader\DirectoryClassMetadataLoader;
16
use Ivory\Serializer\Mapping\Loader\FileClassMetadataLoader;
17
use Ivory\Serializer\Mapping\Loader\ReflectionClassMetadataLoader;
18
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
19
use Symfony\Component\Config\FileLocator;
20
use Symfony\Component\Config\Resource\DirectoryResource;
21
use Symfony\Component\Config\Resource\FileResource;
22
use Symfony\Component\DependencyInjection\ContainerBuilder;
23
use Symfony\Component\DependencyInjection\Definition;
24
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
25
use Symfony\Component\DependencyInjection\Reference;
26
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;
27
28
/**
29
 * @author GeLo <[email protected]>
30
 */
31
class IvorySerializerExtension extends ConfigurableExtension
32
{
33
    /**
34
     * {@inheritdoc}
35
     */
36 243
    protected function loadInternal(array $config, ContainerBuilder $container)
37
    {
38 243
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
39
40
        $resources = [
41 243
            'cache',
42 189
            'common',
43 189
            'event',
44 189
            'fos',
45 189
            'mapping',
46 189
            'navigator',
47 189
            'registry',
48 189
            'serializer',
49 189
            'type',
50 189
            'visitor',
51 189
        ];
52
53 243
        foreach ($resources as $resource) {
54 243
            $loader->load($resource.'.xml');
55 189
        }
56
57 243
        $this->loadEvent($config['event'], $container);
58 243
        $this->loadMapping($config['mapping'], $container);
59 234
        $this->loadTypes($config['types'], $container);
60 234
        $this->loadVisitors($config['visitors'], $container);
61 234
    }
62
63
    /**
64
     * @param mixed[]          $config
65
     * @param ContainerBuilder $container
66
     */
67 243
    private function loadEvent(array $config, ContainerBuilder $container)
68
    {
69 243
        if ($config['enabled']) {
70
            $container
71 234
                ->getDefinition('ivory.serializer.mapping.factory')
72 234
                ->replaceArgument(0, new Reference('ivory.serializer.mapping.factory.event'));
73
74 234
            $container->setAlias('ivory.serializer.navigator', 'ivory.serializer.navigator.event');
75
76 234
            return;
77
        }
78
79 9
        $container->removeDefinition('ivory.serializer.event.dispatcher');
80 9
        $container->removeDefinition('ivory.serializer.mapping.factory.event');
81 9
        $container->removeDefinition('ivory.serializer.navigator.event');
82
83 9
        $container->setAlias('ivory.serializer.navigator', 'ivory.serializer.navigator.default');
84 9
    }
85
86
    /**
87
     * @param mixed[]          $config
88
     * @param ContainerBuilder $container
89
     */
90 243
    private function loadMapping(array $config, ContainerBuilder $container)
91
    {
92 243
        $directories = $files = [];
93
94 243
        foreach ($this->resolveMappingPaths($config, $container) as $path) {
95 36
            if (is_dir($path)) {
96 27
                $directories[] = $path;
97 27
                $container->addResource(new DirectoryResource($path));
98 36
            } elseif (is_file($path)) {
99 27
                $files[] = $path;
100 27
                $container->addResource(new FileResource($path));
101 21
            } else {
102 15
                throw new InvalidConfigurationException(sprintf('The path "%s" does not exist.', $path));
103
            }
104 182
        }
105
106 234
        $loaders = [];
107 234
        $typeParser = new Reference('ivory.serializer.type.parser');
108
109 234
        if ($config['reflection']) {
110 225
            $loaders['reflection'] = $this->createClassMetadataLoaderDefinition(ReflectionClassMetadataLoader::class, [
111 225
                new Reference('property_info', ContainerBuilder::NULL_ON_INVALID_REFERENCE),
112 225
                $typeParser,
113 175
            ]);
114 175
        }
115
116 234
        if ($config['annotation']) {
117 216
            $loaders['annotation'] = $this->createClassMetadataLoaderDefinition(AnnotationClassMetadataLoader::class, [
118 216
                new Reference('annotation_reader'),
119 216
                $typeParser,
120 168
            ]);
121 168
        }
122
123 234
        if (!empty($directories)) {
124 27
            $loaders['directory'] = $this->createClassMetadataLoaderDefinition(DirectoryClassMetadataLoader::class, [
125 27
                $directories,
126 27
                $typeParser,
127 21
            ]);
128 21
        }
129
130 234
        foreach ($files as $file) {
131 27
            $loaders['file_'.sha1($file)] = $this->createClassMetadataLoaderDefinition(FileClassMetadataLoader::class, [
132 27
                $file,
133 27
                $typeParser,
134 21
            ]);
135 182
        }
136
137 234
        foreach ($loaders as $key => $loader) {
138 225
            $container->setDefinition(
139 225
                'ivory.serializer.mapping.loader.'.$key,
140 225
                $loader->addTag('ivory.serializer.loader')
141 175
            );
142 182
        }
143
144 234
        $this->loadMappingCache($config['cache'], $container);
145 234
    }
146
147
    /**
148
     * @param mixed[]          $config
149
     * @param ContainerBuilder $container
150
     */
151 234
    private function loadMappingCache(array $config, ContainerBuilder $container)
152
    {
153 234
        $cacheWarmerService = 'ivory.serializer.cache_warmer';
154 234
        $classMetadataFactoryService = 'ivory.serializer.mapping.factory';
155
156 234
        if ($config['debug']) {
157 198
            $container->removeDefinition($cacheWarmerService);
158 198
            $container->removeDefinition($classMetadataFactoryService);
159
160 198
            $container->setAlias($classMetadataFactoryService, $classMetadataFactoryService.'.default');
161 154
        } else {
162
            $container
163 36
                ->getDefinition($cacheWarmerService)
164 36
                ->addArgument($cachePool = new Reference($config['pool']));
165
166
            $container
167 36
                ->getDefinition($classMetadataFactoryService)
168 36
                ->addArgument($cachePool)
169 36
                ->addArgument($config['prefix']);
170
        }
171 234
    }
172
173
    /**
174
     * @param mixed[]          $config
175
     * @param ContainerBuilder $container
176
     */
177 234
    private function loadTypes(array $config, ContainerBuilder $container)
178
    {
179
        $container
180 234
            ->getDefinition('ivory.serializer.type.date_time')
181 234
            ->addArgument($config['date_time']['format'])
182 234
            ->addArgument($config['date_time']['timezone']);
183
184
        $container
185 234
            ->getDefinition('ivory.serializer.type.exception')
186 234
            ->addArgument($config['exception']['debug']);
187 234
    }
188
189
    /**
190
     * @param mixed[]          $config
191
     * @param ContainerBuilder $container
192
     */
193 234
    private function loadVisitors(array $config, ContainerBuilder $container)
194
    {
195
        $container
196 234
            ->getDefinition('ivory.serializer.visitor.csv.serialization')
197 234
            ->addArgument($config['csv']['delimiter'])
198 234
            ->addArgument($config['csv']['enclosure'])
199 234
            ->addArgument($config['csv']['escape_char'])
200 234
            ->addArgument($config['csv']['key_separator']);
201
202
        $container
203 234
            ->getDefinition('ivory.serializer.visitor.csv.deserialization')
204 234
            ->addArgument($config['csv']['delimiter'])
205 234
            ->addArgument($config['csv']['enclosure'])
206 234
            ->addArgument($config['csv']['escape_char'])
207 234
            ->addArgument($config['csv']['key_separator']);
208
209
        $container
210 234
            ->getDefinition('ivory.serializer.visitor.json.serialization')
211 234
            ->addArgument($config['json']['options']);
212
213
        $container
214 234
            ->getDefinition('ivory.serializer.visitor.json.deserialization')
215 234
            ->addArgument($config['json']['max_depth'])
216 234
            ->addArgument($config['json']['options']);
217
218
        $container
219 234
            ->getDefinition('ivory.serializer.visitor.xml.serialization')
220 234
            ->addArgument($config['xml']['version'])
221 234
            ->addArgument($config['xml']['encoding'])
222 234
            ->addArgument($config['xml']['format_output'])
223 234
            ->addArgument($config['xml']['root'])
224 234
            ->addArgument($config['xml']['entry'])
225 234
            ->addArgument($config['xml']['entry_attribute']);
226
227
        $container
228 234
            ->getDefinition('ivory.serializer.visitor.xml.deserialization')
229 234
            ->addArgument($config['xml']['entry'])
230 234
            ->addArgument($config['xml']['entry_attribute']);
231
232
        $container
233 234
            ->getDefinition('ivory.serializer.visitor.yaml.serialization')
234 234
            ->addArgument($config['yaml']['inline'])
235 234
            ->addArgument($config['yaml']['indent'])
236 234
            ->addArgument($config['yaml']['options']);
237
238
        $container
239 234
            ->getDefinition('ivory.serializer.visitor.yaml.deserialization')
240 234
            ->addArgument($config['yaml']['options']);
241 234
    }
242
243
    /**
244
     * @param mixed[]          $config
245
     * @param ContainerBuilder $container
246
     *
247
     * @return string[]
248
     */
249 243
    private function resolveMappingPaths(array $config, ContainerBuilder $container)
250
    {
251 243
        $paths = [];
252
253 243
        if ($config['auto']['enabled']) {
254 225
            $bundles = $container->getParameter('kernel.bundles');
255
256 225
            foreach ($bundles as $bundle) {
257 18
                $bundlePath = dirname((new \ReflectionClass($bundle))->getFileName());
258
259 18
                foreach ($config['auto']['paths'] as $relativePath) {
260 18
                    $path = $bundlePath.'/'.$relativePath;
261
262 18
                    if (file_exists($path)) {
263 18
                        $paths[] = $path;
264 14
                    }
265 14
                }
266 175
            }
267 175
        }
268
269 243
        return array_merge($paths, $config['paths']);
270
    }
271
272
    /**
273
     * @param string  $class
274
     * @param mixed[] $arguments
275
     *
276
     * @return Definition
277
     */
278 225
    private function createClassMetadataLoaderDefinition($class, array $arguments = [])
279
    {
280 225
        $definition = new Definition($class, $arguments);
281 225
        $definition->addTag('ivory.serializer.loader', ['priority' => -1000]);
282
283 225
        return $definition;
284
    }
285
}
286