Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#568)
by
unknown
21:30
created

OverblogGraphQLExtension   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 269
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 38
eloc 142
c 3
b 1
f 0
dl 0
loc 269
ccs 171
cts 171
cp 1
rs 9.36

19 Methods

Rating   Name   Duplication   Size   Complexity  
A loadConfigFiles() 0 11 1
A setCompilerCacheWarmer() 0 8 1
A registerValidatorFactory() 0 13 2
A setDefaultFieldResolver() 0 3 1
A setSecurity() 0 11 3
A setSchemaBuilderArguments() 0 4 1
A registerForAutoconfiguration() 0 8 1
A setErrorHandler() 0 26 4
A setBatchingMethod() 0 3 1
A setDefinitionParameters() 0 8 1
A setConfigBuilders() 0 7 4
A setDebugListener() 0 6 2
A buildExceptionMap() 0 15 3
A load() 0 23 1
A getAlias() 0 3 1
A setClassLoaderListener() 0 12 2
A setServicesAliases() 0 6 3
A setSchemaArguments() 0 35 4
A getConfiguration() 0 5 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\DependencyInjection;
6
7
use GraphQL\Error\UserError;
8
use GraphQL\Type\Definition\Type;
9
use GraphQL\Type\Schema;
10
use Overblog\GraphQLBundle\CacheWarmer\CompileCacheWarmer;
11
use Overblog\GraphQLBundle\Config\Processor\BuilderProcessor;
12
use Overblog\GraphQLBundle\Definition\Builder\SchemaBuilder;
13
use Overblog\GraphQLBundle\Definition\Resolver\MutationInterface;
14
use Overblog\GraphQLBundle\Definition\Resolver\ResolverInterface;
15
use Overblog\GraphQLBundle\Error\ErrorHandler;
16
use Overblog\GraphQLBundle\Error\UserWarning;
17
use Overblog\GraphQLBundle\Event\Events;
18
use Overblog\GraphQLBundle\EventListener\ClassLoaderListener;
19
use Overblog\GraphQLBundle\EventListener\DebugListener;
20
use Overblog\GraphQLBundle\EventListener\ErrorHandlerListener;
21
use Overblog\GraphQLBundle\EventListener\ErrorLoggerListener;
22
use Overblog\GraphQLBundle\EventListener\TypeDecoratorListener;
23
use Overblog\GraphQLBundle\Request\Executor;
24
use Overblog\GraphQLBundle\Validator\ValidatorFactory;
25
use Symfony\Component\Config\FileLocator;
26
use Symfony\Component\DependencyInjection\ContainerBuilder;
27
use Symfony\Component\DependencyInjection\ContainerInterface;
28
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
29
use Symfony\Component\DependencyInjection\Reference;
30
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
31
32
class OverblogGraphQLExtension extends Extension
33
{
34 41
    public function load(array $configs, ContainerBuilder $container): void
35
    {
36 41
        $this->loadConfigFiles($container);
37 41
        $configuration = $this->getConfiguration($configs, $container);
38 41
        $config = $this->processConfiguration($configuration, $configs);
39
40 41
        $this->setBatchingMethod($config, $container);
41 41
        $this->setServicesAliases($config, $container);
42 41
        $this->setSchemaBuilderArguments($config, $container);
43 41
        $this->setSchemaArguments($config, $container);
44 41
        $this->setErrorHandler($config, $container);
45 41
        $this->setSecurity($config, $container);
46 41
        $this->setConfigBuilders($config, $container);
47 41
        $this->setDebugListener($config, $container);
48 41
        $this->setDefinitionParameters($config, $container);
49 41
        $this->setClassLoaderListener($config, $container);
50 41
        $this->setCompilerCacheWarmer($config, $container);
51 41
        $this->registerForAutoconfiguration($container);
52 41
        $this->setDefaultFieldResolver($config, $container);
53 41
        $this->registerValidatorFactory($container);
54
55 41
        $container->setParameter($this->getAlias().'.config', $config);
56 41
        $container->setParameter($this->getAlias().'.resources_dir', \realpath(__DIR__.'/../Resources'));
57 41
    }
58
59 41
    public function getAlias()
60
    {
61 41
        return Configuration::NAME;
62
    }
63
64 41
    public function getConfiguration(array $config, ContainerBuilder $container)
65
    {
66 41
        return new Configuration(
67 41
            $container->getParameter('kernel.debug'),
68 41
            $container->hasParameter('kernel.cache_dir') ? $container->getParameter('kernel.cache_dir') : null
69
        );
70
    }
71
72 41
    private function loadConfigFiles(ContainerBuilder $container): void
73
    {
74 41
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
75 41
        $loader->load('services.yaml');
76 41
        $loader->load('commands.yaml');
77 41
        $loader->load('listeners.yaml');
78 41
        $loader->load('graphql_types.yaml');
79 41
        $loader->load('graphql_resolvers.yaml');
80 41
        $loader->load('expression_language_functions.yaml');
81 41
        $loader->load('definition_config_processors.yaml');
82 41
        $loader->load('aliases.yaml');
83 41
    }
84
85 41
    private function registerForAutoconfiguration(ContainerBuilder $container): void
86
    {
87 41
        $container->registerForAutoconfiguration(MutationInterface::class)
88 41
            ->addTag('overblog_graphql.mutation');
89 41
        $container->registerForAutoconfiguration(ResolverInterface::class)
90 41
            ->addTag('overblog_graphql.resolver');
91 41
        $container->registerForAutoconfiguration(Type::class)
92 41
            ->addTag('overblog_graphql.type');
93 41
    }
94
95 41
    private function registerValidatorFactory(ContainerBuilder $container): void
96
    {
97 41
        if (\class_exists('Symfony\\Component\\Validator\\Validation')) {
98 41
            $container->register(ValidatorFactory::class)
99 41
                ->setArguments([
100 41
                    new Reference('validator.validator_factory'),
101 41
                    new Reference('translator.default', $container::NULL_ON_INVALID_REFERENCE),
102
                ])
103 41
                ->addTag(
104 41
                    'overblog_graphql.global_variable',
105
                    [
106 41
                        'alias' => 'validatorFactory',
107
                        'public' => false,
108
                    ]
109
                );
110
        }
111 41
    }
112
113 41
    private function setDefaultFieldResolver(array $config, ContainerBuilder $container): void
114
    {
115 41
        $container->setAlias($this->getAlias().'.default_field_resolver', $config['definitions']['default_field_resolver']);
116 41
    }
117
118 41
    private function setCompilerCacheWarmer(array $config, ContainerBuilder $container): void
119
    {
120 41
        $container->register(CompileCacheWarmer::class)
121 41
            ->setArguments([
122 41
                new Reference($this->getAlias().'.cache_compiler'),
123 41
                $config['definitions']['auto_compile'],
124
            ])
125 41
            ->addTag('kernel.cache_warmer', ['priority' => 50])
126
        ;
127 41
    }
128
129 41
    private function setClassLoaderListener(array $config, ContainerBuilder $container): void
130
    {
131 41
        $container->setParameter($this->getAlias().'.use_classloader_listener', $config['definitions']['use_classloader_listener']);
132 41
        if ($config['definitions']['use_classloader_listener']) {
133 40
            $definition = $container->register(
134 40
                $this->getAlias().'.event_listener.classloader_listener',
135 40
                ClassLoaderListener::class
136
            );
137 40
            $definition->setPublic(true);
138 40
            $definition->setArguments([new Reference($this->getAlias().'.cache_compiler')]);
139 40
            $definition->addTag('kernel.event_listener', ['event' => 'kernel.request', 'method' => 'load', 'priority' => 255]);
140 40
            $definition->addTag('kernel.event_listener', ['event' => 'console.command', 'method' => 'load', 'priority' => 255]);
141
        }
142 41
    }
143
144 41
    private function setDefinitionParameters(array $config, ContainerBuilder $container): void
145
    {
146
        // generator and config
147 41
        $container->setParameter($this->getAlias().'.class_namespace', $config['definitions']['class_namespace']);
148 41
        $container->setParameter($this->getAlias().'.cache_dir', $config['definitions']['cache_dir']);
149 41
        $container->setParameter($this->getAlias().'.cache_dir_permissions', $config['definitions']['cache_dir_permissions']);
150 41
        $container->setParameter($this->getAlias().'.argument_class', $config['definitions']['argument_class']);
151 41
        $container->setParameter($this->getAlias().'.use_experimental_executor', $config['definitions']['use_experimental_executor']);
152 41
    }
153
154 41
    private function setBatchingMethod(array $config, ContainerBuilder $container): void
155
    {
156 41
        $container->setParameter($this->getAlias().'.batching_method', $config['batching_method']);
157 41
    }
158
159 41
    private function setDebugListener(array $config, ContainerBuilder $container): void
160
    {
161 41
        if ($config['definitions']['show_debug_info']) {
162 1
            $definition = $container->register(DebugListener::class);
163 1
            $definition->addTag('kernel.event_listener', ['event' => Events::PRE_EXECUTOR, 'method' => 'onPreExecutor']);
164 1
            $definition->addTag('kernel.event_listener', ['event' => Events::POST_EXECUTOR, 'method' => 'onPostExecutor']);
165
        }
166 41
    }
167
168 41
    private function setConfigBuilders(array $config, ContainerBuilder $container): void
169
    {
170 41
        foreach (BuilderProcessor::BUILDER_TYPES as $type) {
171 41
            if (!empty($config['definitions']['builders'][$type])) {
172 5
                foreach ($config['definitions']['builders'][$type] as $params) {
173 5
                    $container->addObjectResource($params['class']);
174 5
                    BuilderProcessor::addBuilderClass($params['alias'], $type, $params['class']);
175
                }
176
            }
177
        }
178 41
    }
179
180 41
    private function setSecurity(array $config, ContainerBuilder $container): void
181
    {
182 41
        $executorDefinition = $container->getDefinition(Executor::class);
183 41
        if ($config['security']['enable_introspection']) {
184 40
            $executorDefinition->addMethodCall('enableIntrospectionQuery');
185
        } else {
186 1
            $executorDefinition->addMethodCall('disableIntrospectionQuery');
187
        }
188
189 41
        foreach ($config['security'] as $key => $value) {
190 41
            $container->setParameter(\sprintf('%s.%s', $this->getAlias(), $key), $value);
191
        }
192 41
    }
193
194 41
    private function setErrorHandler(array $config, ContainerBuilder $container): void
195
    {
196 41
        if ($config['errors_handler']['enabled']) {
197 41
            $id = $this->getAlias().'.error_handler';
198 41
            $container->register($id, ErrorHandler::class)
199 41
                ->setArguments(
200
                    [
201 41
                        new Reference('event_dispatcher'),
202 41
                        $config['errors_handler']['internal_error_message'],
203 41
                        $this->buildExceptionMap($config['errors_handler']['exceptions']),
204 41
                        $config['errors_handler']['map_exceptions_to_parent'],
205
                    ]
206
                );
207
208 41
            $errorHandlerListenerDefinition = $container->register(ErrorHandlerListener::class);
209 41
            $errorHandlerListenerDefinition->setPublic(true)
210 41
                ->setArguments([new Reference($id), $config['errors_handler']['rethrow_internal_exceptions'], $config['errors_handler']['debug']])
211 41
                ->addTag('kernel.event_listener', ['event' => Events::POST_EXECUTOR, 'method' => 'onPostExecutor']);
212
213 41
            if ($config['errors_handler']['log']) {
214 41
                $loggerServiceId = $config['errors_handler']['logger_service'];
215 41
                $invalidBehavior = ErrorLoggerListener::DEFAULT_LOGGER_SERVICE === $loggerServiceId ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
216 41
                $container->register(ErrorLoggerListener::class)
217 41
                    ->setPublic(true)
218 41
                    ->setArguments([new Reference($loggerServiceId, $invalidBehavior)])
219 41
                    ->addTag('kernel.event_listener', ['event' => Events::ERROR_FORMATTING, 'method' => 'onErrorFormatting']);
220
            }
221
        }
222 41
    }
223
224 41
    private function setSchemaBuilderArguments(array $config, ContainerBuilder $container): void
225
    {
226 41
        $container->getDefinition(SchemaBuilder::class)
227 41
            ->replaceArgument(1, $config['definitions']['config_validation']);
228 41
    }
229
230 41
    private function setSchemaArguments(array $config, ContainerBuilder $container): void
231
    {
232 41
        if (isset($config['definitions']['schema'])) {
233 41
            $executorDefinition = $container->getDefinition(Executor::class);
234 41
            $typeDecoratorListenerDefinition = $container->getDefinition(TypeDecoratorListener::class);
235
236 41
            foreach ($config['definitions']['schema'] as $schemaName => $schemaConfig) {
237
                // builder
238 33
                $schemaBuilderID = \sprintf('%s.schema_builder_%s', $this->getAlias(), $schemaName);
239 33
                $definition = $container->register($schemaBuilderID, \Closure::class);
240 33
                $definition->setFactory([new Reference('overblog_graphql.schema_builder'), 'getBuilder']);
241 33
                $definition->setArguments([
242 33
                    $schemaName,
243 33
                    $schemaConfig['query'],
244 33
                    $schemaConfig['mutation'],
245 33
                    $schemaConfig['subscription'],
246 33
                    $schemaConfig['types'],
247
                ]);
248
                // schema
249 33
                $schemaID = \sprintf('%s.schema_%s', $this->getAlias(), $schemaName);
250 33
                $definition = $container->register($schemaID, Schema::class);
251 33
                $definition->setFactory([new Reference($schemaBuilderID), 'call']);
252
253 33
                if (!empty($schemaConfig['resolver_maps'])) {
254 1
                    $typeDecoratorListenerDefinition->addMethodCall(
255 1
                        'addSchemaResolverMaps',
256
                        [
257 1
                            $schemaName,
258
                            \array_map(function ($id) {
259 1
                                return new Reference($id);
260 1
                            }, $schemaConfig['resolver_maps']),
261
                        ]
262
                    );
263
                }
264 33
                $executorDefinition->addMethodCall('addSchemaBuilder', [$schemaName, new Reference($schemaBuilderID)]);
265
            }
266
        }
267 41
    }
268
269 41
    private function setServicesAliases(array $config, ContainerBuilder $container): void
270
    {
271 41
        if (isset($config['services'])) {
272 41
            foreach ($config['services'] as $name => $id) {
273 41
                $alias = \sprintf('%s.%s', $this->getAlias(), $name);
274 41
                $container->setAlias($alias, $id);
275
            }
276
        }
277 41
    }
278
279
    /**
280
     * Returns a list of custom exceptions mapped to error/warning classes.
281
     *
282
     * @param array $exceptionConfig
283
     *
284
     * @return array Custom exception map, [exception => UserError/UserWarning]
285
     */
286 41
    private function buildExceptionMap(array $exceptionConfig)
287
    {
288 41
        $exceptionMap = [];
289
        $errorsMapping = [
290 41
            'errors' => UserError::class,
291
            'warnings' => UserWarning::class,
292
        ];
293
294 41
        foreach ($exceptionConfig as $type => $exceptionList) {
295 41
            foreach ($exceptionList as $exception) {
296 2
                $exceptionMap[$exception] = $errorsMapping[$type];
297
            }
298
        }
299
300 41
        return $exceptionMap;
301
    }
302
}
303