Completed
Pull Request — master (#5)
by Yonel Ceruto
10:19 queued 23s
created

Configuration   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 7
dl 0
loc 208
ccs 0
cts 140
cp 0
rs 10
c 2
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A configureExtensionPagination() 0 5 1
A configureDefinition() 0 7 1
A configureExtensionNamespace() 0 65 1
B configureSecurity() 0 24 1
A configureCORS() 0 8 1
A configureGraphiQL() 0 71 1
A getConfigTreeBuilder() 0 11 1
1
<?php
2
3
/*******************************************************************************
4
 *  This file is part of the GraphQL Bundle package.
5
 *
6
 *  (c) YnloUltratech <[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 Ynlo\GraphQLBundle\DependencyInjection;
13
14
use GraphQL\Validator\Rules\QueryComplexity;
15
use GraphQL\Validator\Rules\QueryDepth;
16
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
17
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
18
use Symfony\Component\Config\Definition\ConfigurationInterface;
19
20
/**
21
 * Class Configuration
22
 */
23
class Configuration implements ConfigurationInterface
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function getConfigTreeBuilder()
29
    {
30
        $treeBuilder = new TreeBuilder();
31
        /** @var NodeBuilder $rootNode */
32
        $rootNode = $treeBuilder->root('graphql')->addDefaultsIfNotSet()->children();
0 ignored issues
show
Bug introduced by
The method addDefaultsIfNotSet() does not exist on Symfony\Component\Config...\Builder\NodeDefinition. It seems like you code against a sub-type of Symfony\Component\Config...\Builder\NodeDefinition such as Symfony\Component\Config...der\ArrayNodeDefinition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

32
        $rootNode = $treeBuilder->root('graphql')->/** @scrutinizer ignore-call */ addDefaultsIfNotSet()->children();
Loading history...
33
        $this->configureCORS($rootNode);
34
        $this->configureGraphiQL($rootNode);
35
        $this->configureDefinition($rootNode);
36
        $this->configureSecurity($rootNode);
37
38
        return $treeBuilder;
39
    }
40
41
    protected function configureGraphiQL(NodeBuilder $root)
42
    {
43
        $graphiql = $root->arrayNode('graphiql')->addDefaultsIfNotSet()->children();
44
45
        $graphiql->scalarNode('title')
46
                 ->defaultValue('GraphQL API Explorer');
47
48
        $graphiql
49
            ->scalarNode('data_warning_message')
50
            ->defaultValue('Heads up! GraphQL Explorer makes use of your <strong>real</strong>, <strong>live</strong>, <strong>production</strong> data.');
51
        $graphiql->booleanNode('data_warning_dismissible')->defaultTrue();
52
        $graphiql->enumNode('data_warning_style')->values(['info', 'warning', 'danger'])->defaultValue('danger');
53
54
        $graphiql->scalarNode('template')
55
                 ->defaultValue('@YnloGraphQL/explorer.twig');
56
57
        $authentication = $graphiql->arrayNode('authentication')->addDefaultsIfNotSet()->children();
58
        $authentication
59
            ->booleanNode('required')
60
            ->info(
61
                'The API require credentials to make any requests, 
62
if this value is FALSE and a provider is specified the authentication is optional.'
63
            )
64
            ->defaultFalse();
65
66
        $authentication->scalarNode('login_message')
67
                       ->defaultValue('Start exploring GraphQL API queries using your account’s data now.');
68
69
        $authenticationProvider = $authentication->arrayNode('provider')->children();
70
71
        $jwt = $authenticationProvider->arrayNode('jwt')->canBeEnabled()->children();
72
73
        $jwtLogin = $jwt->arrayNode('login')->children();
74
75
        $jwtLogin->scalarNode('url')
76
                 ->info('Route name or URI to make the login process to retrieve the token.')
77
                 ->isRequired();
78
79
        $jwtLogin->scalarNode('username_parameter')
80
                 ->defaultValue('username');
81
82
        $jwtLogin->scalarNode('password_parameter')
83
                 ->defaultValue('password');
84
85
        $jwtLogin->enumNode('parameters_in')
86
                 ->values(['form', 'query', 'header'])
87
                 ->info('How pass parameters to request the token')
88
                 ->defaultValue('form');
89
90
        $jwtLogin->scalarNode('response_token_path')
91
                 ->defaultValue('token')
92
                 ->info('Where the token should be located in the response in case of JSON, set null if the response is the token.');
93
94
        $jwtRequests = $jwt->arrayNode('requests')->addDefaultsIfNotSet()->children();
95
96
        $jwtRequests->enumNode('token_in')
97
                    ->values(['query', 'header'])
98
                    ->info('Where should be located the token on every request')
99
                    ->defaultValue('header');
100
101
        $jwtRequests->scalarNode('token_name')
102
                    ->defaultValue('Authorization')
103
                    ->info('Name of the token in query or header name');
104
105
        $jwtRequests->scalarNode('token_template')
106
                    ->defaultValue('Bearer {token}')
107
                    ->info('Customize how the token should be send,  use the place holder {token} to replace for current token');
108
109
        $authenticationProvider->scalarNode('custom')
110
                               ->defaultNull()
111
                               ->info('Configure custom service to use as authentication provider');
112
    }
113
114
    protected function configureCORS(NodeBuilder $root)
115
    {
116
        $cors = $root->arrayNode('cors')->canBeEnabled()->children();
117
        $cors->booleanNode('allow_credentials')->defaultTrue();
118
        $cors->variableNode('allow_headers')->defaultValue(['Origin', 'Content-Type', 'Accept', 'Authorization']);
119
        $cors->integerNode('max_age')->defaultValue(3600);
120
        $cors->variableNode('allow_methods')->defaultValue(['POST', 'GET', 'OPTIONS']);
121
        $cors->variableNode('allow_origins')->defaultValue(['*']);
122
    }
123
124
    protected function configureDefinition(NodeBuilder $root)
125
    {
126
        $definitions = $root->arrayNode('definitions')->addDefaultsIfNotSet()->children();
127
128
        $extensions = $definitions->arrayNode('extensions')->addDefaultsIfNotSet();
129
        $this->configureExtensionPagination($extensions->children());
130
        $this->configureExtensionNamespace($extensions->children());
131
    }
132
133
    protected function configureExtensionPagination(NodeBuilder $root)
134
    {
135
        $pagination = $root->arrayNode('pagination')->addDefaultsIfNotSet()->children();
136
        $pagination->integerNode('limit')
137
                   ->defaultValue(100)->info('Maximum limit allowed for all paginations');
138
    }
139
140
    protected function configureExtensionNamespace(NodeBuilder $root)
141
    {
142
        $namespaces = $root->arrayNode('namespaces')
143
                           ->info(
144
                               'Group GraphQL schema using namespaced schemas. 
145
On large schemas is  helpful to keep schemas grouped by bundle and node'
146
                           )
147
                           ->canBeEnabled()
148
                           ->addDefaultsIfNotSet()
149
                           ->children();
150
151
        $bundles = $namespaces->arrayNode('bundles')
152
                              ->info('Group each bundle into a separate schema definition')
153
                              ->canBeDisabled()
154
                              ->addDefaultsIfNotSet()
155
                              ->children();
156
157
        $bundles->scalarNode('query_suffix')
158
                ->info('The following suffix will be used for bundle query groups')
159
                ->defaultValue('BundleQuery');
160
161
        $bundles->scalarNode('mutation_suffix')
162
                ->info('The following suffix will be used for bundle mutation groups')
163
                ->defaultValue('BundleMutation');
164
165
        $bundles->variableNode('ignore')
166
                ->info('The following bundles will be ignore for grouping, all definitions will be placed in the root query or mutation')
167
                ->defaultValue(['AppBundle']);
168
169
        $bundles->arrayNode('aliases')
170
                ->info(
171
                    'Define aliases for bundles to set definitions inside other desired bundle name. 
172
Can be used to group multiple bundles or publish a bundle with a different name'
173
                )
174
                ->example('SecurityBundle: AppBundle')
175
                ->useAttributeAsKey('name')
176
                ->prototype('scalar');
177
178
179
        $nodes = $namespaces->arrayNode('nodes')
180
                            ->info('Group queries and mutations of the same node into a node specific schema definition.')
181
                            ->addDefaultsIfNotSet()
182
                            ->canBeDisabled()
183
                            ->children();
184
185
        $nodes->scalarNode('query_suffix')
186
              ->info('The following suffix will be used to create the name for queries to the same node')
187
              ->defaultValue('Query');
188
189
        $nodes->scalarNode('mutation_suffix')
190
              ->info('The following suffix will be used to create the name for mutations to the same node')
191
              ->defaultValue('Mutation');
192
193
        $nodes->variableNode('ignore')
194
              ->info('The following nodes will be ignore for grouping, all definitions will be placed in the root query or mutation')
195
              ->defaultValue(['Node']);
196
197
        $nodes->arrayNode('aliases')
198
              ->info(
199
                  'Define aliases for nodes to set definitions inside other desired node name. 
200
Can be used to group multiple nodes or publish a node with a different group name'
201
              )
202
              ->example('InvoiceItem: Invoice')
203
              ->useAttributeAsKey('name')
204
              ->prototype('scalar');
205
    }
206
207
    private function configureSecurity(NodeBuilder $rootNode)
208
    {
209
        $securityNode = $rootNode
210
            ->arrayNode('security')
211
            ->canBeEnabled()
212
            ->children();
213
214
        $validationRulesNode = $securityNode
215
            ->arrayNode('validation_rules')
216
            ->addDefaultsIfNotSet()
217
            ->children();
218
        $validationRulesNode
219
            ->integerNode('query_complexity')
220
            ->info('Query complexity score before execution.')
221
            ->min(0)
222
            ->defaultValue(QueryComplexity::DISABLED);
223
        $validationRulesNode
224
            ->integerNode('query_depth')
225
            ->info('Max depth of the query.')
226
            ->min(0)
227
            ->defaultValue(QueryDepth::DISABLED);
228
        $validationRulesNode
229
            ->booleanNode('disable_introspection')
230
            ->defaultFalse();
231
    }
232
}
233