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
Push — master ( e143f5...f9ed24 )
by Jérémiah
11:37 queued 07:50
created

OverblogGraphQLExtension::setServicesAliases()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

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