Completed
Pull Request — 2.0 (#1192)
by
unknown
03:00
created

Configuration   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 5

Importance

Changes 0
Metric Value
wmc 11
lcom 0
cbo 5
dl 0
loc 221
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B getConfigTreeBuilder() 0 124 1
C addExceptionToStatusSection() 0 44 7
B addFormatSection() 0 31 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
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection;
15
16
use ApiPlatform\Core\Exception\InvalidArgumentException;
17
use Symfony\Bundle\TwigBundle\TwigBundle;
18
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
19
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
20
use Symfony\Component\Config\Definition\ConfigurationInterface;
21
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
22
use Symfony\Component\HttpFoundation\Response;
23
use Symfony\Component\Serializer\Exception\ExceptionInterface;
24
25
/**
26
 * The configuration of the bundle.
27
 *
28
 * @author Kévin Dunglas <[email protected]>
29
 * @author Baptiste Meyer <[email protected]>
30
 */
31
final class Configuration implements ConfigurationInterface
32
{
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function getConfigTreeBuilder()
37
    {
38
        $treeBuilder = new TreeBuilder();
39
        $rootNode = $treeBuilder->root('api_platform');
40
41
        $rootNode
42
            ->children()
43
                ->scalarNode('title')->defaultValue('')->info('The title of the API.')->end()
44
                ->scalarNode('description')->defaultValue('')->info('The description of the API.')->end()
45
                ->scalarNode('version')->defaultValue('0.0.0')->info('The version of the API.')->end()
46
                ->scalarNode('default_operation_path_resolver')->defaultValue('api_platform.operation_path_resolver.underscore')->info('Specify the default operation path resolver to use for generating resources operations path.')->end()
47
                ->scalarNode('name_converter')->defaultNull()->info('Specify a name converter to use.')->end()
48
                ->scalarNode('api_resources_directory')->defaultValue('Entity')->info('The name of the directory within the bundles that contains the api resources.')->end()
49
                ->arrayNode('eager_loading')
50
                    ->canBeDisabled()
51
                    ->addDefaultsIfNotSet()
52
                    ->children()
53
                        ->booleanNode('enabled')->defaultTrue()->info('To enable or disable eager loading')->end()
54
                        ->booleanNode('fetch_partial')->defaultFalse()->info('Fetch only partial data according to serialization groups. If enabled, Doctrine ORM entities will not work as expected if any of the other fields are used.')->end()
55
                        ->integerNode('max_joins')->defaultValue(30)->info('Max number of joined relations before EagerLoading throws a RuntimeException')->end()
56
                        ->booleanNode('force_eager')->defaultTrue()->info('Force join on every relation. If disabled, it will only join relations having the EAGER fetch mode.')->end()
57
                    ->end()
58
                ->end()
59
                ->booleanNode('enable_fos_user')->defaultValue(false)->info('Enable the FOSUserBundle integration.')->end()
60
                ->booleanNode('enable_nelmio_api_doc')->defaultValue(false)->info('Enable the Nelmio Api doc integration.')->end()
61
                ->booleanNode('enable_swagger')->defaultValue(true)->info('Enable the Swagger documentation and export.')->end()
62
                ->booleanNode('enable_swagger_ui')->defaultValue(class_exists(TwigBundle::class))->info('Enable Swagger ui.')->end()
63
64
                ->arrayNode('oauth')
65
                    ->canBeEnabled()
66
                    ->addDefaultsIfNotSet()
67
                    ->children()
68
                        ->booleanNode('enabled')->defaultFalse()->info('To enable or disable oauth')->end()
69
                        ->scalarNode('clientId')->defaultValue('')->info('The oauth client id.')->end()
70
                        ->scalarNode('clientSecret')->defaultValue('')->info('The oauth client secret.')->end()
71
                        ->scalarNode('type')->defaultValue('oauth2')->info('The oauth client secret.')->end()
72
                        ->scalarNode('flow')->defaultValue('application')->info('The oauth flow grant type.')->end()
73
                        ->scalarNode('tokenUrl')->defaultValue('/oauth/v2/token')->info('The oauth token url.')->end()
74
                        ->scalarNode('authorizationUrl')->defaultValue('/oauth/v2/auth')->info('The oauth authentication url.')->end()
75
                        ->arrayNode('scopes')
76
                            ->prototype('scalar')->end()
77
                        ->end()
78
                    ->end()
79
                ->end()
80
81
                ->arrayNode('collection')
82
                    ->addDefaultsIfNotSet()
83
                    ->children()
84
                        ->scalarNode('order')->defaultValue('ASC')->info('The default order of results.')->end() // Default ORDER is required for postgresql and mysql >= 5.7 when using LIMIT/OFFSET request
85
                        ->scalarNode('order_parameter_name')->defaultValue('order')->cannotBeEmpty()->info('The name of the query parameter to order results.')->end()
86
                        ->arrayNode('pagination')
87
                            ->canBeDisabled()
88
                            ->addDefaultsIfNotSet()
89
                            ->children()
90
                                ->booleanNode('enabled')->defaultTrue()->info('To enable or disable pagination for all resource collections by default.')->end()
91
                                ->booleanNode('client_enabled')->defaultFalse()->info('To allow the client to enable or disable the pagination.')->end()
92
                                ->booleanNode('client_items_per_page')->defaultFalse()->info('To allow the client to set the number of items per page.')->end()
93
                                ->integerNode('items_per_page')->defaultValue(30)->info('The default number of items per page.')->end()
94
                                ->integerNode('maximum_items_per_page')->defaultNull()->info('The maximum number of items per page.')->end()
95
                                ->scalarNode('page_parameter_name')->defaultValue('page')->cannotBeEmpty()->info('The default name of the parameter handling the page number.')->end()
96
                                ->scalarNode('enabled_parameter_name')->defaultValue('pagination')->cannotBeEmpty()->info('The name of the query parameter to enable or disable pagination.')->end()
97
                                ->scalarNode('items_per_page_parameter_name')->defaultValue('itemsPerPage')->cannotBeEmpty()->info('The name of the query parameter to set the number of items per page.')->end()
98
                            ->end()
99
                        ->end()
100
                    ->end()
101
                ->end()
102
103
                ->arrayNode('loader_paths')
104
                    ->addDefaultsIfNotSet()
105
                    ->children()
106
                        ->arrayNode('annotation')
107
                            ->prototype('scalar')->end()
108
                        ->end()
109
                        ->arrayNode('yaml')
110
                            ->prototype('scalar')->end()
111
                        ->end()
112
                        ->arrayNode('xml')
113
                            ->prototype('scalar')->end()
114
                        ->end()
115
                    ->end()
116
                ->end()
117
118
                ->arrayNode('http_cache')
119
                    ->addDefaultsIfNotSet()
120
                    ->children()
121
                        ->booleanNode('etag')->defaultTrue()->info('Automatically generate etags for API responses.')->end()
122
                        ->integerNode('max_age')->defaultNull()->info('Default value for the response max age.')->end()
123
                        ->integerNode('shared_max_age')->defaultNull()->info('Default value for the response shared (proxy) max age.')->end()
124
                        ->arrayNode('vary')
125
                            ->defaultValue(['Content-Type'])
126
                            ->prototype('scalar')->end()
127
                            ->info('Default values of the "Vary" HTTP header.')
128
                        ->end()
129
                        ->booleanNode('public')->defaultNull()->info('To make all responses public by default.')->end()
130
                        ->arrayNode('invalidation')
131
                            ->info('Enable the tags-based cache invalidation system.')
132
                            ->canBeEnabled()
133
                            ->children()
134
                                ->arrayNode('varnish_urls')
135
                                    ->defaultValue([])
136
                                    ->prototype('scalar')->end()
137
                                    ->info('URLs of the Varnish servers to purge using cache tags when a resource is updated.')
138
                                ->end()
139
                            ->end()
140
                        ->end()
141
                    ->end()
142
                ->end()
143
144
            ->end();
145
146
        $this->addExceptionToStatusSection($rootNode);
147
148
        $this->addFormatSection($rootNode, 'formats', [
149
            'jsonld' => ['mime_types' => ['application/ld+json']],
150
            'json' => ['mime_types' => ['application/json']], // Swagger support
151
            'html' => ['mime_types' => ['text/html']], // Swagger UI support
152
        ]);
153
        $this->addFormatSection($rootNode, 'error_formats', [
154
            'jsonproblem' => ['mime_types' => ['application/problem+json']],
155
            'jsonld' => ['mime_types' => ['application/ld+json']],
156
        ]);
157
158
        return $treeBuilder;
159
    }
160
161
    /**
162
     * Adds an exception to status section.
163
     *
164
     * @param ArrayNodeDefinition $rootNode
165
     *
166
     * @throws InvalidConfigurationException
167
     */
168
    private function addExceptionToStatusSection(ArrayNodeDefinition $rootNode)
169
    {
170
        $rootNode
171
            ->children()
172
                ->arrayNode('exception_to_status')
173
                    ->defaultValue([
174
                        ExceptionInterface::class => Response::HTTP_BAD_REQUEST,
175
                        InvalidArgumentException::class => Response::HTTP_BAD_REQUEST,
176
                    ])
177
                    ->info('The list of exceptions mapped to their HTTP status code.')
178
                    ->normalizeKeys(false)
179
                    ->useAttributeAsKey('exception_class')
180
                    ->beforeNormalization()
181
                        ->ifArray()
182
                        ->then(function (array $exceptionToStatus) {
183
                            foreach ($exceptionToStatus as &$httpStatusCode) {
184
                                if (is_int($httpStatusCode)) {
185
                                    continue;
186
                                }
187
188
                                if (defined($httpStatusCodeConstant = sprintf('%s::%s', Response::class, $httpStatusCode))) {
189
                                    $httpStatusCode = constant($httpStatusCodeConstant);
190
                                }
191
                            }
192
193
                            return $exceptionToStatus;
194
                        })
195
                    ->end()
196
                    ->prototype('integer')->end()
197
                    ->validate()
198
                        ->ifArray()
199
                        ->then(function (array $exceptionToStatus) {
200
                            foreach ($exceptionToStatus as $httpStatusCode) {
201
                                if ($httpStatusCode < 100 || $httpStatusCode >= 600) {
202
                                    throw new InvalidConfigurationException(sprintf('The HTTP status code "%s" is not valid.', $httpStatusCode));
203
                                }
204
                            }
205
206
                            return $exceptionToStatus;
207
                        })
208
                    ->end()
209
                ->end()
210
            ->end();
211
    }
212
213
    /**
214
     * Adds a format section.
215
     *
216
     * @param ArrayNodeDefinition $rootNode
217
     * @param string              $key
218
     * @param array               $defaultValue
219
     */
220
    private function addFormatSection(ArrayNodeDefinition $rootNode, string $key, array $defaultValue)
221
    {
222
        $rootNode
223
            ->children()
224
                ->arrayNode($key)
225
                    ->defaultValue($defaultValue)
226
                    ->info('The list of enabled formats. The first one will be the default.')
227
                    ->normalizeKeys(false)
228
                    ->useAttributeAsKey('format')
229
                    ->beforeNormalization()
230
                        ->ifArray()
231
                        ->then(function ($v) {
232
                            foreach ($v as $format => $value) {
233
                                if (isset($value['mime_types'])) {
234
                                    continue;
235
                                }
236
237
                                $v[$format] = ['mime_types' => $value];
238
                            }
239
240
                            return $v;
241
                        })
242
                    ->end()
243
                    ->prototype('array')
244
                        ->children()
245
                            ->arrayNode('mime_types')->prototype('scalar')->end()->end()
246
                        ->end()
247
                    ->end()
248
                ->end()
249
            ->end();
250
    }
251
}
252