Completed
Push — master ( c1090d...38195c )
by Kévin
10s
created

Configuration::addExceptionToStatusSection()   C

Complexity

Conditions 7
Paths 1

Size

Total Lines 44
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 44
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 31
nc 1
nop 1
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 ApiPlatform\Core\Exception\InvalidArgumentException;
15
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
16
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
17
use Symfony\Component\Config\Definition\ConfigurationInterface;
18
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\Serializer\Exception\ExceptionInterface;
21
22
/**
23
 * The configuration of the bundle.
24
 *
25
 * @author Kévin Dunglas <[email protected]>
26
 * @author Baptiste Meyer <[email protected]>
27
 */
28
final class Configuration implements ConfigurationInterface
29
{
30
    /**
31
     * {@inheritdoc}
32
     */
33
    public function getConfigTreeBuilder()
34
    {
35
        $treeBuilder = new TreeBuilder();
36
        $rootNode = $treeBuilder->root('api_platform');
37
38
        $rootNode
39
            ->children()
40
                ->scalarNode('title')->defaultValue('')->info('The title of the API.')->end()
41
                ->scalarNode('description')->defaultValue('')->info('The description of the API.')->end()
42
                ->scalarNode('version')->defaultValue('0.0.0')->info('The version of the API.')->end()
43
                ->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()
44
                ->scalarNode('name_converter')->defaultNull()->info('Specify a name converter to use.')->end()
45
                ->booleanNode('enable_fos_user')->defaultValue(false)->info('Enable the FOSUserBundle integration.')->end()
46
                ->booleanNode('enable_nelmio_api_doc')->defaultValue(false)->info('Enable the Nelmio Api doc integration.')->end()
47
                ->booleanNode('enable_swagger')->defaultValue(true)->info('Enable the Swagger documentation and export.')->end()
48
49
                ->arrayNode('collection')
50
                    ->addDefaultsIfNotSet()
51
                    ->children()
52
                        ->scalarNode('order')->defaultNull()->info('The default order of results.')->end()
53
                        ->scalarNode('order_parameter_name')->defaultValue('order')->cannotBeEmpty()->info('The name of the query parameter to order results.')->end()
54
                        ->arrayNode('pagination')
55
                            ->canBeDisabled()
56
                            ->addDefaultsIfNotSet()
57
                            ->children()
58
                                ->booleanNode('enabled')->defaultTrue()->info('To enable or disable pagination for all resource collections by default.')->end()
59
                                ->booleanNode('client_enabled')->defaultFalse()->info('To allow the client to enable or disable the pagination.')->end()
60
                                ->booleanNode('client_items_per_page')->defaultFalse()->info('To allow the client to set the number of items per page.')->end()
61
                                ->integerNode('items_per_page')->defaultValue(30)->info('The default number of items per page.')->end()
62
                                ->integerNode('maximum_items_per_page')->defaultNull()->info('The maximum number of items per page.')->end()
63
                                ->scalarNode('page_parameter_name')->defaultValue('page')->cannotBeEmpty()->info('The default name of the parameter handling the page number.')->end()
64
                                ->scalarNode('enabled_parameter_name')->defaultValue('pagination')->cannotBeEmpty()->info('The name of the query parameter to enable or disable pagination.')->end()
65
                                ->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()
66
                            ->end()
67
                        ->end()
68
                    ->end()
69
                ->end()
70
            ->end();
71
72
        $this->addExceptionToStatusSection($rootNode);
73
74
        $this->addFormatSection($rootNode, 'formats', [
75
            'jsonld' => ['mime_types' => ['application/ld+json']],
76
            'json' => ['mime_types' => ['application/json']], // Swagger support
77
            'html' => ['mime_types' => ['text/html']], // Swagger UI support
78
        ]);
79
        $this->addFormatSection($rootNode, 'error_formats', [
80
            'jsonproblem' => ['mime_types' => ['application/problem+json']],
81
            'jsonld' => ['mime_types' => ['application/ld+json']],
82
        ]);
83
84
        return $treeBuilder;
85
    }
86
87
    /**
88
     * Adds an exception to status section.
89
     *
90
     * @param ArrayNodeDefinition $rootNode
91
     *
92
     * @throws InvalidConfigurationException
93
     */
94
    private function addExceptionToStatusSection(ArrayNodeDefinition $rootNode)
95
    {
96
        $rootNode
97
            ->children()
98
                ->arrayNode('exception_to_status')
99
                    ->defaultValue([
100
                        ExceptionInterface::class => Response::HTTP_BAD_REQUEST,
101
                        InvalidArgumentException::class => Response::HTTP_BAD_REQUEST,
102
                    ])
103
                    ->info('The list of exceptions mapped to their HTTP status code.')
104
                    ->normalizeKeys(false)
105
                    ->useAttributeAsKey('exception_class')
106
                    ->beforeNormalization()
107
                        ->ifArray()
108
                        ->then(function (array $exceptionToStatus) {
109
                            foreach ($exceptionToStatus as &$httpStatusCode) {
110
                                if (is_int($httpStatusCode)) {
111
                                    continue;
112
                                }
113
114
                                if (defined($httpStatusCodeConstant = sprintf('%s::%s', Response::class, $httpStatusCode))) {
115
                                    $httpStatusCode = constant($httpStatusCodeConstant);
116
                                }
117
                            }
118
119
                            return $exceptionToStatus;
120
                        })
121
                    ->end()
122
                    ->prototype('integer')->end()
123
                    ->validate()
124
                        ->ifArray()
125
                        ->then(function (array $exceptionToStatus) {
126
                            foreach ($exceptionToStatus as $httpStatusCode) {
127
                                if ($httpStatusCode < 100 || $httpStatusCode >= 600) {
128
                                    throw new InvalidConfigurationException(sprintf('The HTTP status code "%s" is not valid.', $httpStatusCode));
129
                                }
130
                            }
131
132
                            return $exceptionToStatus;
133
                        })
134
                    ->end()
135
                ->end()
136
            ->end();
137
    }
138
139
    /**
140
     * Adds a format section.
141
     *
142
     * @param ArrayNodeDefinition $rootNode
143
     * @param string              $key
144
     * @param array               $defaultValue
145
     */
146
    private function addFormatSection(ArrayNodeDefinition $rootNode, string $key, array $defaultValue)
147
    {
148
        $rootNode
149
            ->children()
150
                ->arrayNode($key)
151
                    ->defaultValue($defaultValue)
152
                    ->info('The list of enabled formats. The first one will be the default.')
153
                    ->normalizeKeys(false)
154
                    ->useAttributeAsKey('format')
155
                    ->beforeNormalization()
156
                        ->ifArray()
157
                        ->then(function ($v) {
158
                            foreach ($v as $format => $value) {
159
                                if (isset($value['mime_types'])) {
160
                                    continue;
161
                                }
162
163
                                $v[$format] = ['mime_types' => $value];
164
                            }
165
166
                            return $v;
167
                        })
168
                    ->end()
169
                    ->prototype('array')
170
                        ->children()
171
                            ->arrayNode('mime_types')->prototype('scalar')->end()->end()
172
                        ->end()
173
                    ->end()
174
                ->end()
175
            ->end();
176
    }
177
}
178