Completed
Push — master ( 979520...aaae07 )
by Kévin
02:52
created

ApiPlatformExtension::registerOAuthConfiguration()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 11
nc 2
nop 3
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
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 ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection;
13
14
use Doctrine\ORM\Version;
15
use phpDocumentor\Reflection\DocBlockFactoryInterface;
16
use Symfony\Component\Cache\Adapter\ArrayAdapter;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\Config\Resource\DirectoryResource;
19
use Symfony\Component\DependencyInjection\ContainerBuilder;
20
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
21
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
22
use Symfony\Component\Finder\Finder;
23
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
24
25
/**
26
 * The extension of this bundle.
27
 *
28
 * @author Kévin Dunglas <[email protected]>
29
 */
30
final class ApiPlatformExtension extends Extension implements PrependExtensionInterface
31
{
32
    /**
33
     * {@inheritdoc}
34
     */
35
    public function prepend(ContainerBuilder $container)
36
    {
37
        if (empty($frameworkConfiguration = $container->getExtensionConfig('framework'))) {
38
            return;
39
        }
40
41
        foreach ($frameworkConfiguration as $frameworkParameters) {
42
            if (isset($frameworkParameters['serializer'])) {
43
                $serializerConfig = $serializerConfig ?? $frameworkParameters['serializer'];
44
            }
45
46
            if (isset($frameworkParameters['property_info'])) {
47
                $propertyInfoConfig = $propertyInfoConfig ?? $frameworkParameters['property_info'];
48
            }
49
        }
50
51 View Code Duplication
        if (!isset($serializerConfig['enabled'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
52
            $container->prependExtensionConfig('framework', ['serializer' => ['enabled' => true]]);
53
        }
54
55 View Code Duplication
        if (!isset($propertyInfoConfig['enabled'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
56
            $container->prependExtensionConfig('framework', ['property_info' => ['enabled' => true]]);
57
        }
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function load(array $configs, ContainerBuilder $container)
64
    {
65
        $configuration = new Configuration();
66
        $config = $this->processConfiguration($configuration, $configs);
67
        $formats = $this->getFormats($config['formats']);
68
        $errorFormats = $this->getFormats($config['error_formats']);
69
        $this->handleConfig($container, $config, $formats, $errorFormats);
70
71
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
72
        $loader->load('api.xml');
73
        $loader->load('data_provider.xml');
74
75
        $bundles = $container->getParameter('kernel.bundles');
76
77
        $this->registerMetadataConfiguration($container, $loader);
78
        $this->registerOAuthConfiguration($container, $config, $loader);
79
        $this->registerSwaggerConfiguration($container, $config, $loader);
80
        $this->registerJsonLdConfiguration($formats, $loader);
81
        $this->registerJsonHalConfiguration($formats, $loader);
82
        $this->registerJsonProblemConfiguration($errorFormats, $loader);
83
        $this->registerLoaders($container, $bundles, $config['loader_paths']);
84
        $this->registerBundlesConfiguration($bundles, $config, $loader);
85
        $this->registerCacheConfiguration($container);
86
        $this->registerDoctrineExtensionConfiguration($container, $config);
87
    }
88
89
    /**
90
     * Handles configuration.
91
     *
92
     * @param ContainerBuilder $container
93
     * @param array            $config
94
     * @param array            $formats
95
     * @param array            $errorFormats
96
     */
97
    private function handleConfig(ContainerBuilder $container, array $config, array $formats, array $errorFormats)
98
    {
99
        $container->setParameter('api_platform.title', $config['title']);
100
        $container->setParameter('api_platform.description', $config['description']);
101
        $container->setParameter('api_platform.version', $config['version']);
102
        $container->setParameter('api_platform.exception_to_status', $config['exception_to_status']);
103
        $container->setParameter('api_platform.formats', $formats);
104
        $container->setParameter('api_platform.error_formats', $errorFormats);
105
        $container->setParameter('api_platform.eager_loading.enabled', $config['eager_loading']['enabled']);
106
        $container->setParameter('api_platform.eager_loading.max_joins', $config['eager_loading']['max_joins']);
107
        $container->setParameter('api_platform.eager_loading.force_eager', $config['eager_loading']['force_eager']);
108
        $container->setParameter('api_platform.collection.order', $config['collection']['order']);
109
        $container->setParameter('api_platform.collection.order_parameter_name', $config['collection']['order_parameter_name']);
110
        $container->setParameter('api_platform.collection.pagination.enabled', $config['collection']['pagination']['enabled']);
111
        $container->setParameter('api_platform.collection.pagination.client_enabled', $config['collection']['pagination']['client_enabled']);
112
        $container->setParameter('api_platform.collection.pagination.client_items_per_page', $config['collection']['pagination']['client_items_per_page']);
113
        $container->setParameter('api_platform.collection.pagination.items_per_page', $config['collection']['pagination']['items_per_page']);
114
        $container->setParameter('api_platform.collection.pagination.maximum_items_per_page', $config['collection']['pagination']['maximum_items_per_page']);
115
        $container->setParameter('api_platform.collection.pagination.page_parameter_name', $config['collection']['pagination']['page_parameter_name']);
116
        $container->setParameter('api_platform.collection.pagination.enabled_parameter_name', $config['collection']['pagination']['enabled_parameter_name']);
117
        $container->setParameter('api_platform.collection.pagination.items_per_page_parameter_name', $config['collection']['pagination']['items_per_page_parameter_name']);
118
119
        $container->setAlias('api_platform.operation_path_resolver.default', $config['default_operation_path_resolver']);
120
121
        if ($config['name_converter']) {
122
            $container->setAlias('api_platform.name_converter', $config['name_converter']);
123
        }
124
    }
125
126
    /**
127
     * Registers metadata configuration.
128
     *
129
     * @param ContainerBuilder $container
130
     * @param XmlFileLoader    $loader
131
     */
132
    private function registerMetadataConfiguration(ContainerBuilder $container, XmlFileLoader $loader)
133
    {
134
        $loader->load('metadata.xml');
135
136
        if (!interface_exists(DocBlockFactoryInterface::class)) {
137
            $container->removeDefinition('api_platform.metadata.resource.metadata_factory.php_doc');
138
        }
139
    }
140
141
    /**
142
     * Registers the OAuth configuration.
143
     *
144
     * @param ContainerBuilder $container
145
     * @param array            $config
146
     * @param XmlFileLoader    $loader
147
     */
148
    private function registerOAuthConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader)
0 ignored issues
show
Unused Code introduced by
The parameter $loader is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
149
    {
150
        if (!$config['oauth']) {
151
            return;
152
        }
153
154
        $container->setParameter('api_platform.oauth.enabled', $config['oauth']['enabled']);
155
        $container->setParameter('api_platform.oauth.clientId', $config['oauth']['clientId']);
156
        $container->setParameter('api_platform.oauth.clientSecret', $config['oauth']['clientSecret']);
157
        $container->setParameter('api_platform.oauth.type', $config['oauth']['type']);
158
        $container->setParameter('api_platform.oauth.flow', $config['oauth']['flow']);
159
        $container->setParameter('api_platform.oauth.tokenUrl', $config['oauth']['tokenUrl']);
160
        $container->setParameter('api_platform.oauth.authorizationUrl', $config['oauth']['authorizationUrl']);
161
        $container->setParameter('api_platform.oauth.scopes', $config['oauth']['scopes']);
162
    }
163
164
    /**
165
     * Registers the Swagger and Swagger UI configuration.
166
     *
167
     * @param ContainerBuilder $container
168
     * @param array            $config
169
     * @param XmlFileLoader    $loader
170
     */
171
    private function registerSwaggerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader)
172
    {
173
        if (!$config['enable_swagger']) {
174
            return;
175
        }
176
177
        $loader->load('swagger.xml');
178
179
        if ($config['enable_swagger_ui']) {
180
            $loader->load('swagger-ui.xml');
181
            $container->setParameter('api_platform.enable_swagger_ui', $config['enable_swagger_ui']);
182
        }
183
184
        $container->setParameter('api_platform.enable_swagger', $config['enable_swagger']);
185
    }
186
187
    /**
188
     * Registers the JSON-LD and Hydra configuration.
189
     *
190
     * @param array         $formats
191
     * @param XmlFileLoader $loader
192
     */
193
    private function registerJsonLdConfiguration(array $formats, XmlFileLoader $loader)
194
    {
195
        if (!isset($formats['jsonld'])) {
196
            return;
197
        }
198
199
        $loader->load('jsonld.xml');
200
        $loader->load('hydra.xml');
201
    }
202
203
    /**
204
     * Registers the HAL configuration.
205
     *
206
     * @param array         $formats
207
     * @param XmlFileLoader $loader
208
     */
209
    private function registerJsonHalConfiguration(array $formats, XmlFileLoader $loader)
210
    {
211
        if (!isset($formats['jsonhal'])) {
212
            return;
213
        }
214
215
        $loader->load('hal.xml');
216
    }
217
218
    /**
219
     * Registers the JSON Problem configuration.
220
     *
221
     * @param array         $errorFormats
222
     * @param XmlFileLoader $loader
223
     */
224
    private function registerJsonProblemConfiguration(array $errorFormats, XmlFileLoader $loader)
225
    {
226
        if (!isset($errorFormats['jsonproblem'])) {
227
            return;
228
        }
229
230
        $loader->load('problem.xml');
231
    }
232
233
    /**
234
     * Registers configuration for integration with third-party bundles.
235
     *
236
     * @param string[]      $bundles
237
     * @param array         $config
238
     * @param XmlFileLoader $loader
239
     */
240
    private function registerBundlesConfiguration(array $bundles, array $config, XmlFileLoader $loader)
241
    {
242
        // Doctrine ORM support
243
        if (isset($bundles['DoctrineBundle']) && class_exists(Version::class)) {
244
            $loader->load('doctrine_orm.xml');
245
        }
246
247
        // FOSUser support
248
        if (isset($bundles['FOSUserBundle']) && $config['enable_fos_user']) {
249
            $loader->load('fos_user.xml');
250
        }
251
252
        // NelmioApiDoc support
253
        if (isset($bundles['NelmioApiDocBundle']) && $config['enable_nelmio_api_doc']) {
254
            $loader->load('nelmio_api_doc.xml');
255
        }
256
    }
257
258
    /**
259
     * Registers the cache configuration.
260
     *
261
     * @param ContainerBuilder $container
262
     */
263
    private function registerCacheConfiguration(ContainerBuilder $container)
264
    {
265
        // Don't use system cache pool in dev
266
        if (!$container->getParameter('kernel.debug')) {
267
            return;
268
        }
269
270
        $container->register('api_platform.cache.metadata.property', ArrayAdapter::class);
271
        $container->register('api_platform.cache.metadata.resource', ArrayAdapter::class);
272
        $container->register('api_platform.cache.route_name_resolver', ArrayAdapter::class);
273
    }
274
275
    /**
276
     * Registers configuration file loaders.
277
     *
278
     * @param ContainerBuilder $container
279
     * @param string[]         $bundles
280
     */
281
    private function registerLoaders(ContainerBuilder $container, array $bundles, array $loaderPaths)
282
    {
283
        $annotationPaths = $loaderPaths['annotation'];
284
        $yamlResources = $loaderPaths['yaml'];
285
        $xmlResources = $loaderPaths['xml'];
286
287
        foreach ($bundles as $bundle) {
288
            $bundleDirectory = dirname((new \ReflectionClass($bundle))->getFileName());
289
            $this->addFileResources($bundleDirectory, $xmlResources, $yamlResources);
290
291
            if (file_exists($entityDirectory = $bundleDirectory.'/Entity')) {
292
                $annotationPaths[] = $entityDirectory;
293
                $container->addResource(new DirectoryResource($entityDirectory, '/\.php$/'));
294
            }
295
        }
296
297
        $container->getDefinition('api_platform.metadata.resource.name_collection_factory.annotation')->addArgument($annotationPaths);
298
        $container->getDefinition('api_platform.metadata.extractor.yaml')->addArgument($yamlResources);
299
        $container->getDefinition('api_platform.metadata.extractor.xml')->addArgument($xmlResources);
300
    }
301
302
    /**
303
     * Manipulate doctrine extension services according to the configuration.
304
     *
305
     * @param ContainerBuilder $container
306
     * @param array            $config
307
     */
308
    private function registerDoctrineExtensionConfiguration(ContainerBuilder $container, array $config)
309
    {
310
        if (false === $config['eager_loading']['enabled']) {
311
            $container->removeDefinition('api_platform.doctrine.orm.query_extension.eager_loading');
312
        }
313
    }
314
315
    /**
316
     * Populates file resources lists.
317
     *
318
     * @param string   $bundleDirectory
319
     * @param string[] $xmlResources
320
     * @param string[] $yamlResources
321
     */
322
    private function addFileResources(string $bundleDirectory, array &$xmlResources, array &$yamlResources)
323
    {
324
        try {
325
            foreach (Finder::create()->files()->in($bundleDirectory.'/Resources/config/')->path('api_resources')->name('*.{yml,yaml,xml}') as $file) {
326
                if ('xml' === $file->getExtension()) {
327
                    $xmlResources[] = $file->getRealPath();
328
                } else {
329
                    $yamlResources[] = $file->getRealPath();
330
                }
331
            }
332
        } catch (\InvalidArgumentException $e) {
333
            // Ignore invalid paths
334
        }
335
    }
336
337
    /**
338
     * Normalizes the format from config to the one accepted by Symfony HttpFoundation.
339
     *
340
     * @param array $configFormats
341
     *
342
     * @return array
343
     */
344
    private function getFormats(array $configFormats): array
345
    {
346
        $formats = [];
347
        foreach ($configFormats as $format => $value) {
348
            foreach ($value['mime_types'] as $mimeType) {
349
                $formats[$format][] = $mimeType;
350
            }
351
        }
352
353
        return $formats;
354
    }
355
}
356