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 (#277)
by Jérémiah
20:41
created

OverblogGraphQLExtension::load()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 16
cts 16
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 16
nc 1
nop 2
crap 1
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 25
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
23
use Symfony\Component\DependencyInjection\Reference;
24 25
use Symfony\Component\ExpressionLanguage\ParserCache\ArrayParserCache;
25 25
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
26 25
use Symfony\Component\HttpKernel\Kernel;
27 25
28
class OverblogGraphQLExtension extends Extension implements PrependExtensionInterface
29 25
{
30
    public function load(array $configs, ContainerBuilder $container)
31 25
    {
32 25
        $this->loadConfigFiles($container);
33 25
        $config = $this->treatConfigs($configs, $container);
34 25
35 25
        $this->setBatchingMethod($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...on::setBatchingMethod() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
36 25
        $this->setExpressionLanguageDefaultParser($container);
37 25
        $this->setServicesAliases($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...n::setServicesAliases() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
38 25
        $this->setSchemaBuilderArguments($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...chemaBuilderArguments() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
39 25
        $this->setSchemaArguments($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...n::setSchemaArguments() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
40 25
        $this->setErrorHandler($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...sion::setErrorHandler() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
41 25
        $this->setSecurity($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...xtension::setSecurity() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
42 25
        $this->setConfigBuilders($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...on::setConfigBuilders() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
43
        $this->setDebugListener($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...ion::setDebugListener() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
44 25
        $this->setDefinitionParameters($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...tDefinitionParameters() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
45 25
        $this->setClassLoaderListener($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...etClassLoaderListener() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
46
        $this->setCompilerCacheWarmer($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container) on line 33 can also be of type null; however, Overblog\GraphQLBundle\D...etCompilerCacheWarmer() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
47 23
48
        $container->setParameter($this->getAlias().'.resources_dir', realpath(__DIR__.'/../Resources'));
49 23
    }
50 23
51 23
    public function prepend(ContainerBuilder $container)
52
    {
53
        $configs = $container->getExtensionConfig($this->getAlias());
54 23
        $configs = $container->getParameterBag()->resolveValue($configs);
55 23
        $config = $this->treatConfigs($configs, $container, true);
56 23
57
        /** @var OverblogGraphQLTypesExtension $typesExtension */
58 25
        $typesExtension = $container->getExtension($this->getAlias().'_types');
59
        $typesExtension->containerPrependExtensionConfig($config, $container);
0 ignored issues
show
Bug introduced by
It seems like $config defined by $this->treatConfigs($configs, $container, true) on line 55 can also be of type null; however, Overblog\GraphQLBundle\D...rependExtensionConfig() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
60 25
    }
61
62
    public function getAlias()
63 25
    {
64
        return Configuration::NAME;
65 25
    }
66 25
67 25
    public function getConfiguration(array $config, ContainerBuilder $container)
68
    {
69
        return new Configuration(
70
            $container->getParameter('kernel.debug'),
71 25
            $container->hasParameter('kernel.cache_dir') ? $container->getParameter('kernel.cache_dir') : null
72
        );
73 25
    }
74 24
75 24
    private function loadConfigFiles(ContainerBuilder $container)
76 24
    {
77
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
78 24
        $loader->load('services.yml');
79 24
        $loader->load('graphql_types.yml');
80
        $loader->load('expression_language_functions.yml');
81 25
        $loader->load('definition_config_processors.yml');
82
    }
83 25
84
    private function setCompilerCacheWarmer(array $config, ContainerBuilder $container)
85 25
    {
86 25
        if ($config['definitions']['auto_compile']) {
87 24
            $definition = $container->setDefinition(
88 24
                CompileCacheWarmer::class,
89 24
                new Definition(CompileCacheWarmer::class)
90
            );
91 24
            $definition->setArguments([new Reference($this->getAlias().'.cache_compiler')]);
92 24
            $definition->addTag('kernel.cache_warmer', ['priority' => 50]);
93 24
        }
94
    }
95 25
96
    private function setClassLoaderListener(array $config, ContainerBuilder $container)
97 25
    {
98
        $container->setParameter($this->getAlias().'.use_classloader_listener', $config['definitions']['use_classloader_listener']);
99
        if ($config['definitions']['use_classloader_listener']) {
100 25
            $definition = $container->setDefinition(
101 25
                $this->getAlias().'.event_listener.classloader_listener',
102
                new Definition(ClassLoaderListener::class)
103 25
            );
104 25
            $definition->setPublic(true);
105 25
            $definition->setArguments([new Reference($this->getAlias().'.cache_compiler')]);
106 25
            $definition->addTag('kernel.event_listener', ['event' => 'kernel.request', 'method' => 'load', 'priority' => 255]);
107
            $definition->addTag('kernel.event_listener', ['event' => 'console.command', 'method' => 'load', 'priority' => 255]);
108 25
        }
109
    }
110 25
111 25
    private function setDefinitionParameters(array $config, ContainerBuilder $container)
112
    {
113 25
        // auto mapping
114
        $container->setParameter($this->getAlias().'.auto_mapping.enabled', $config['definitions']['auto_mapping']['enabled']);
115 25
        $container->setParameter($this->getAlias().'.auto_mapping.directories', $config['definitions']['auto_mapping']['directories']);
116 25
        // generator and config
117 25
        $container->setParameter($this->getAlias().'.default_resolver', $config['definitions']['default_resolver']);
118 25
        $container->setParameter($this->getAlias().'.class_namespace', $config['definitions']['class_namespace']);
119 25
        $container->setParameter($this->getAlias().'.cache_dir', $config['definitions']['cache_dir']);
120
    }
121 25
122
    private function setBatchingMethod(array $config, ContainerBuilder $container)
123 25
    {
124 25
        $container->setParameter($this->getAlias().'.batching_method', $config['batching_method']);
125
    }
126 25
127
    private function setExpressionLanguageDefaultParser(ContainerBuilder $container)
128 25
    {
129 25
        $class = version_compare(Kernel::VERSION, '3.2.0', '>=') ? ArrayAdapter::class : ArrayParserCache::class;
130
        $definition = new Definition($class);
131 25
        $definition->setPublic(false);
132 25
        $container->setDefinition($this->getAlias().'.cache_expression_language_parser.default', $definition);
133 1
    }
134 1
135 1
    private function setDebugListener(array $config, ContainerBuilder $container)
136 25
    {
137
        if ($config['definitions']['show_debug_info']) {
138
            $definition = $container->setDefinition(
139
                DebugListener::class,
140 25
                new Definition(DebugListener::class)
141
            );
142 25
            $definition->addTag('kernel.event_listener', ['event' => Events::PRE_EXECUTOR, 'method' => 'onPreExecutor']);
143
            $definition->addTag('kernel.event_listener', ['event' => Events::POST_EXECUTOR, 'method' => 'onPostExecutor']);
144 25
        }
145
    }
146 25
147 25
    private function setConfigBuilders(array $config, ContainerBuilder $container)
148 25
    {
149
        $useObjectToAddResource = method_exists($container, 'addObjectResource');
150
        $objectToAddResourceMethod = $useObjectToAddResource ? 'addObjectResource' : 'addClassResource';
151 25
152
        foreach (BuilderProcessor::BUILDER_TYPES as $type) {
153
            if (!empty($config['definitions']['builders'][$type])) {
154 25
                foreach ($config['definitions']['builders'][$type] as $params) {
155
                    $object = $useObjectToAddResource ? $params['class'] : new \ReflectionClass($params['class']);
156 25
                    $container->$objectToAddResourceMethod($object);
157 25
                    BuilderProcessor::addBuilderClass($params['alias'], $type, $params['class']);
158
                }
159 25
            }
160
        }
161 25
    }
162
163 25
    private function treatConfigs(array $configs, ContainerBuilder $container, $forceReload = false)
164
    {
165 25
        static $config = null;
166 2
167
        if ($forceReload || null === $config) {
168
            $configuration = $this->getConfiguration($configs, $container);
169 25
            $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 25
        }
171 25
172 25
        return $config;
173
    }
174
175
    private function setSecurity(array $config, ContainerBuilder $container)
176 25
    {
177
        foreach ($config['security'] as $key => $value) {
178 25
            $container->setParameter(sprintf('%s.%s', $this->getAlias(), $key), $value);
179 25
        }
180 25
    }
181
182
    private function setErrorHandler(array $config, ContainerBuilder $container)
183 25
    {
184
        if ($config['errors_handler']['enabled']) {
185 25
            $id = $this->getAlias().'.error_handler';
186
            $errorHandlerDefinition = $container->setDefinition($id, new Definition(ErrorHandler::class));
187 25
            $errorHandlerDefinition->setPublic(false)
188 25
                ->setArguments(
189 25
                    [
190
                        new Reference('event_dispatcher'),
191 25
                        $config['errors_handler']['internal_error_message'],
192
                        $this->buildExceptionMap($config['errors_handler']['exceptions']),
193 25
                        $config['errors_handler']['map_exceptions_to_parent'],
194 25
                    ]
195
                )
196 25
            ;
197 21
198 21
            $errorHandlerListenerDefinition = $container->setDefinition(ErrorHandlerListener::class, new Definition(ErrorHandlerListener::class));
199 21
            $errorHandlerListenerDefinition->setPublic(true)
200 21
                ->setArguments([new Reference($id), $config['errors_handler']['rethrow_internal_exceptions'], $config['errors_handler']['debug']])
201 21
                ->addTag('kernel.event_listener', ['event' => Events::POST_EXECUTOR, 'method' => 'onPostExecutor'])
202 21
            ;
203
204 21
            if ($config['errors_handler']['log']) {
205
                $loggerServiceId = $config['errors_handler']['logger_service'];
206
                $invalidBehavior = ErrorLoggerListener::DEFAULT_LOGGER_SERVICE === $loggerServiceId ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
207 25
                $errorHandlerListenerDefinition = $container->setDefinition(ErrorLoggerListener::class, new Definition(ErrorLoggerListener::class));
208
                $errorHandlerListenerDefinition->setPublic(true)
209 25
                    ->setArguments([new Reference($loggerServiceId, $invalidBehavior)])
210
                    ->addTag('kernel.event_listener', ['event' => Events::ERROR_FORMATTING, 'method' => 'onErrorFormatting'])
211 25
                ;
212 25
            }
213 25
        }
214 25
    }
215
216
    private function setSchemaBuilderArguments(array $config, ContainerBuilder $container)
217 25
    {
218
        $container->getDefinition($this->getAlias().'.schema_builder')
219
            ->replaceArgument(2, $config['definitions']['config_validation']);
220
    }
221
222
    private function setSchemaArguments(array $config, ContainerBuilder $container)
223
    {
224
        if (isset($config['definitions']['schema'])) {
225
            $executorDefinition = $container->getDefinition($this->getAlias().'.request_executor');
226 25
227
            foreach ($config['definitions']['schema'] as $schemaName => $schemaConfig) {
228 25
                $schemaID = sprintf('%s.schema_%s', $this->getAlias(), $schemaName);
229 25
                $definition = new Definition(Schema::class);
230
                $definition->setFactory([new Reference('overblog_graphql.schema_builder'), 'create']);
231 25
                $definition->setArguments([
232 25
                    $schemaConfig['query'],
233 25
                    $schemaConfig['mutation'],
234
                    $schemaConfig['subscription'],
235
                    array_map(function ($id) {
236 25
                        return new Reference($id);
237 25
                    }, $schemaConfig['resolver_maps']),
238
                ]);
239
                $definition->setPublic(false);
240
                $container->setDefinition($schemaID, $definition);
241 25
242
                $executorDefinition->addMethodCall('addSchema', [$schemaName, new Reference($schemaID)]);
243
            }
244
        }
245
    }
246
247
    private function setServicesAliases(array $config, ContainerBuilder $container)
248
    {
249
        if (isset($config['services'])) {
250
            foreach ($config['services'] as $name => $id) {
251
                $alias = sprintf('%s.%s', $this->getAlias(), $name);
252
                $container->setAlias($alias, $id);
253
            }
254
        }
255
    }
256
257
    /**
258
     * Returns a list of custom exceptions mapped to error/warning classes.
259
     *
260
     * @param array $exceptionConfig
261
     *
262
     * @return array Custom exception map, [exception => UserError/UserWarning]
263
     */
264
    private function buildExceptionMap(array $exceptionConfig)
265
    {
266
        $exceptionMap = [];
267
        $errorsMapping = [
268
            'errors' => UserError::class,
269
            'warnings' => UserWarning::class,
270
        ];
271
272
        foreach ($exceptionConfig as $type => $exceptionList) {
273
            foreach ($exceptionList as $exception) {
274
                $exceptionMap[$exception] = $errorsMapping[$type];
275
            }
276
        }
277
278
        return $exceptionMap;
279
    }
280
}
281