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

Passed
Pull Request — 0.12 (#505)
by Jérémiah
20:07
created

OverblogGraphQLExtension::setSchemaArguments()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 32
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 4

Importance

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