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 — master (#325)
by Jérémiah
13:59
created

OverblogGraphQLExtension::setSchemaArguments()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 3.0013

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 18
cts 19
cp 0.9474
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 18
nc 3
nop 2
crap 3.0013
1
<?php
2
3
namespace Overblog\GraphQLBundle\DependencyInjection;
4
5
use GraphQL\Error\UserError;
6
use GraphQL\Type\Schema;
7
use Overblog\GraphQLBundle\CacheWarmer\CompileCacheWarmer;
8
use Overblog\GraphQLBundle\Config\Processor\BuilderProcessor;
9
use Overblog\GraphQLBundle\Error\ErrorHandler;
10
use Overblog\GraphQLBundle\Error\UserWarning;
11
use Overblog\GraphQLBundle\Event\Events;
12
use Overblog\GraphQLBundle\EventListener\ClassLoaderListener;
13
use Overblog\GraphQLBundle\EventListener\DebugListener;
14
use Overblog\GraphQLBundle\EventListener\ErrorHandlerListener;
15
use Overblog\GraphQLBundle\EventListener\ErrorLoggerListener;
16
use Symfony\Component\Cache\Adapter\ArrayAdapter;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\ContainerInterface;
20
use Symfony\Component\DependencyInjection\Definition;
21
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
22
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
23
use Symfony\Component\DependencyInjection\Reference;
24
use Symfony\Component\ExpressionLanguage\ParserCache\ArrayParserCache;
25
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
26
use Symfony\Component\HttpKernel\Kernel;
27
28
class OverblogGraphQLExtension extends Extension implements PrependExtensionInterface
29
{
30 19
    public function load(array $configs, ContainerBuilder $container)
31
    {
32 19
        $this->loadConfigFiles($container);
33 19
        $config = $this->treatConfigs($configs, $container);
34
35 19
        $this->setBatchingMethod($config, $container);
36 19
        $this->setExpressionLanguageDefaultParser($container);
37 19
        $this->setServicesAliases($config, $container);
38 19
        $this->setSchemaBuilderArguments($config, $container);
39 19
        $this->setSchemaArguments($config, $container);
40 19
        $this->setErrorHandler($config, $container);
41 19
        $this->setSecurity($config, $container);
42 19
        $this->setConfigBuilders($config, $container);
43 19
        $this->setDebugListener($config, $container);
44 19
        $this->setDefinitionParameters($config, $container);
45 19
        $this->setClassLoaderListener($config, $container);
46 19
        $this->setCompilerCacheWarmer($config, $container);
47
48 19
        $container->setParameter($this->getAlias().'.resources_dir', realpath(__DIR__.'/../Resources'));
49 19
    }
50
51 17
    public function prepend(ContainerBuilder $container)
52
    {
53 17
        $configs = $container->getExtensionConfig($this->getAlias());
54 17
        $configs = $container->getParameterBag()->resolveValue($configs);
55 17
        $config = $this->treatConfigs($configs, $container, true);
56
57
        /** @var OverblogGraphQLTypesExtension $typesExtension */
58 17
        $typesExtension = $container->getExtension($this->getAlias().'_types');
59 17
        $typesExtension->containerPrependExtensionConfig($config, $container);
60 17
    }
61
62 19
    public function getAlias()
63
    {
64 19
        return Configuration::NAME;
65
    }
66
67 19
    public function getConfiguration(array $config, ContainerBuilder $container)
68
    {
69 19
        return new Configuration(
70 19
            $container->getParameter('kernel.debug'),
71 19
            $container->hasParameter('kernel.cache_dir') ? $container->getParameter('kernel.cache_dir') : null
72
        );
73
    }
74
75 19
    private function loadConfigFiles(ContainerBuilder $container)
76
    {
77 19
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
78 19
        $loader->load('services.yml');
79 19
        $loader->load('graphql_types.yml');
80 19
        $loader->load('expression_language_functions.yml');
81 19
        $loader->load('definition_config_processors.yml');
82 19
    }
83
84 19
    private function setCompilerCacheWarmer(array $config, ContainerBuilder $container)
85
    {
86 19
        if ($config['definitions']['auto_compile']) {
87 18
            $definition = $container->setDefinition(
88 18
                CompileCacheWarmer::class,
89 18
                new Definition(CompileCacheWarmer::class)
90
            );
91 18
            $definition->setArguments([new Reference($this->getAlias().'.cache_compiler')]);
92 18
            $definition->addTag('kernel.cache_warmer', ['priority' => 50]);
93
        }
94 19
    }
95
96 19
    private function setClassLoaderListener(array $config, ContainerBuilder $container)
97
    {
98 19
        $container->setParameter($this->getAlias().'.use_classloader_listener', $config['definitions']['use_classloader_listener']);
99 19
        if ($config['definitions']['use_classloader_listener']) {
100 18
            $definition = $container->setDefinition(
101 18
                $this->getAlias().'.event_listener.classloader_listener',
102 18
                new Definition(ClassLoaderListener::class)
103
            );
104 18
            $definition->setPublic(true);
105 18
            $definition->setArguments([new Reference($this->getAlias().'.cache_compiler')]);
106 18
            $definition->addTag('kernel.event_listener', ['event' => 'kernel.request', 'method' => 'load', 'priority' => 255]);
107 18
            $definition->addTag('kernel.event_listener', ['event' => 'console.command', 'method' => 'load', 'priority' => 255]);
108
        }
109 19
    }
110
111 19
    private function setDefinitionParameters(array $config, ContainerBuilder $container)
112
    {
113
        // auto mapping
114 19
        $container->setParameter($this->getAlias().'.auto_mapping.enabled', $config['definitions']['auto_mapping']['enabled']);
115 19
        $container->setParameter($this->getAlias().'.auto_mapping.directories', $config['definitions']['auto_mapping']['directories']);
116
        // generator and config
117 19
        $container->setParameter($this->getAlias().'.default_resolver', $config['definitions']['default_resolver']);
118 19
        $container->setParameter($this->getAlias().'.class_namespace', $config['definitions']['class_namespace']);
119 19
        $container->setParameter($this->getAlias().'.cache_dir', $config['definitions']['cache_dir']);
120 19
    }
121
122 19
    private function setBatchingMethod(array $config, ContainerBuilder $container)
123
    {
124 19
        $container->setParameter($this->getAlias().'.batching_method', $config['batching_method']);
125 19
    }
126
127 19
    private function setExpressionLanguageDefaultParser(ContainerBuilder $container)
128
    {
129 19
        $class = version_compare(Kernel::VERSION, '3.2.0', '>=') ? ArrayAdapter::class : ArrayParserCache::class;
130 19
        $definition = new Definition($class);
131 19
        $definition->setPublic(false);
132 19
        $container->setDefinition($this->getAlias().'.cache_expression_language_parser.default', $definition);
133 19
    }
134
135 19
    private function setDebugListener(array $config, ContainerBuilder $container)
136
    {
137 19
        if ($config['definitions']['show_debug_info']) {
138
            $definition = $container->setDefinition(
139
                DebugListener::class,
140
                new Definition(DebugListener::class)
141
            );
142
            $definition->addTag('kernel.event_listener', ['event' => Events::PRE_EXECUTOR, 'method' => 'onPreExecutor']);
143
            $definition->addTag('kernel.event_listener', ['event' => Events::POST_EXECUTOR, 'method' => 'onPostExecutor']);
144
        }
145 19
    }
146
147 19
    private function setConfigBuilders(array $config, ContainerBuilder $container)
148
    {
149 19
        $useObjectToAddResource = method_exists($container, 'addObjectResource');
150 19
        $objectToAddResourceMethod = $useObjectToAddResource ? 'addObjectResource' : 'addClassResource';
151
152 19
        foreach (BuilderProcessor::BUILDER_TYPES as $type) {
153 19
            if (!empty($config['definitions']['builders'][$type])) {
154 1
                foreach ($config['definitions']['builders'][$type] as $params) {
155 1
                    $object = $useObjectToAddResource ? $params['class'] : new \ReflectionClass($params['class']);
156 1
                    $container->$objectToAddResourceMethod($object);
157 19
                    BuilderProcessor::addBuilderClass($params['alias'], $type, $params['class']);
158
                }
159
            }
160
        }
161 19
    }
162
163 19
    private function treatConfigs(array $configs, ContainerBuilder $container, $forceReload = false)
164
    {
165 19
        static $config = null;
166
167 19
        if ($forceReload || null === $config) {
168 19
            $configuration = $this->getConfiguration($configs, $container);
169 19
            $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
Bug introduced by
It seems like $configuration defined by $this->getConfiguration($configs, $container) on line 168 can be null; however, Symfony\Component\Depend...:processConfiguration() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
170
        }
171
172 19
        return $config;
173
    }
174
175 19
    private function setSecurity(array $config, ContainerBuilder $container)
176
    {
177 19
        foreach ($config['security'] as $key => $value) {
178 19
            $container->setParameter(sprintf('%s.%s', $this->getAlias(), $key), $value);
179
        }
180 19
    }
181
182 19
    private function setErrorHandler(array $config, ContainerBuilder $container)
183
    {
184 19
        if ($config['errors_handler']['enabled']) {
185 19
            $id = $this->getAlias().'.error_handler';
186 19
            $errorHandlerDefinition = $container->setDefinition($id, new Definition(ErrorHandler::class));
187 19
            $errorHandlerDefinition->setPublic(false)
188 19
                ->setArguments(
189
                    [
190 19
                        new Reference('event_dispatcher'),
191 19
                        $config['errors_handler']['internal_error_message'],
192 19
                        $this->buildExceptionMap($config['errors_handler']['exceptions']),
193 19
                        $config['errors_handler']['map_exceptions_to_parent'],
194
                    ]
195
                )
196
            ;
197
198 19
            $errorHandlerListenerDefinition = $container->setDefinition(ErrorHandlerListener::class, new Definition(ErrorHandlerListener::class));
199 19
            $errorHandlerListenerDefinition->setPublic(true)
200 19
                ->setArguments([new Reference($id), $config['errors_handler']['rethrow_internal_exceptions'], $config['errors_handler']['debug']])
201 19
                ->addTag('kernel.event_listener', ['event' => Events::POST_EXECUTOR, 'method' => 'onPostExecutor'])
202
            ;
203
204 19
            if ($config['errors_handler']['log']) {
205 19
                $loggerServiceId = $config['errors_handler']['logger_service'];
206 19
                $invalidBehavior = ErrorLoggerListener::DEFAULT_LOGGER_SERVICE === $loggerServiceId ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
207 19
                $errorHandlerListenerDefinition = $container->setDefinition(ErrorLoggerListener::class, new Definition(ErrorLoggerListener::class));
208 19
                $errorHandlerListenerDefinition->setPublic(true)
209 19
                    ->setArguments([new Reference($loggerServiceId, $invalidBehavior)])
210 19
                    ->addTag('kernel.event_listener', ['event' => Events::ERROR_FORMATTING, 'method' => 'onErrorFormatting'])
211
                ;
212
            }
213
        }
214 19
    }
215
216 19
    private function setSchemaBuilderArguments(array $config, ContainerBuilder $container)
217
    {
218 19
        $container->getDefinition($this->getAlias().'.schema_builder')
219 19
            ->replaceArgument(1, $config['definitions']['config_validation']);
220 19
    }
221
222 19
    private function setSchemaArguments(array $config, ContainerBuilder $container)
223
    {
224 19
        if (isset($config['definitions']['schema'])) {
225 19
            $executorDefinition = $container->getDefinition($this->getAlias().'.request_executor');
226
227 19
            foreach ($config['definitions']['schema'] as $schemaName => $schemaConfig) {
228 15
                $schemaID = sprintf('%s.schema_%s', $this->getAlias(), $schemaName);
229 15
                $definition = new Definition(Schema::class);
230 15
                $definition->setFactory([new Reference('overblog_graphql.schema_builder'), 'create']);
231 15
                $definition->setArguments([
232 15
                    $schemaConfig['query'],
233 15
                    $schemaConfig['mutation'],
234 15
                    $schemaConfig['subscription'],
235 15
                    array_map(function ($id) {
236
                        return new Reference($id);
237 15
                    }, $schemaConfig['resolver_maps']),
238 15
                    $schemaConfig['types'],
239
                ]);
240 15
                $definition->setPublic(false);
241 15
                $container->setDefinition($schemaID, $definition);
242
243 15
                $executorDefinition->addMethodCall('addSchema', [$schemaName, new Reference($schemaID)]);
244
            }
245
        }
246 19
    }
247
248 19
    private function setServicesAliases(array $config, ContainerBuilder $container)
249
    {
250 19
        if (isset($config['services'])) {
251 19
            foreach ($config['services'] as $name => $id) {
252 19
                $alias = sprintf('%s.%s', $this->getAlias(), $name);
253 19
                $container->setAlias($alias, $id);
254
            }
255
        }
256 19
    }
257
258
    /**
259
     * Returns a list of custom exceptions mapped to error/warning classes.
260
     *
261
     * @param array $exceptionConfig
262
     *
263
     * @return array Custom exception map, [exception => UserError/UserWarning]
264
     */
265 19
    private function buildExceptionMap(array $exceptionConfig)
266
    {
267 19
        $exceptionMap = [];
268
        $errorsMapping = [
269 19
            'errors' => UserError::class,
270
            'warnings' => UserWarning::class,
271
        ];
272
273 19
        foreach ($exceptionConfig as $type => $exceptionList) {
274 19
            foreach ($exceptionList as $exception) {
275 19
                $exceptionMap[$exception] = $errorsMapping[$type];
276
            }
277
        }
278
279 19
        return $exceptionMap;
280
    }
281
}
282