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 (#237)
by Jérémiah
08:39
created

checkTypesDuplication()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Overblog\GraphQLBundle\DependencyInjection;
4
5
use Overblog\GraphQLBundle\OverblogGraphQLBundle;
6
use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
7
use Symfony\Component\Config\Resource\FileResource;
8
use Symfony\Component\DependencyInjection\ContainerBuilder;
9
use Symfony\Component\Finder\Finder;
10
use Symfony\Component\Finder\SplFileInfo;
11
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
12
13
class OverblogGraphQLTypesExtension extends Extension
14
{
15
    private static $configTypes = ['yaml', 'xml'];
16
17
    private static $typeExtensions = ['yaml' => '{yaml,yml}', 'xml' => 'xml'];
18
19
    private static $defaultDefaultConfig = [
20
        'definitions' => [
21
            'mappings' => [
22
                'auto_discover' => [
23
                    'root_dir' => true,
24
                    'bundles' => true,
25
                ],
26
                'types' => [],
27
            ],
28
        ],
29
    ];
30
31
    private $treatedFiles = [];
32
33
    const DEFAULT_TYPES_SUFFIX = '.types';
34
35 31
    public function load(array $configs, ContainerBuilder $container)
36
    {
37 31
        $this->checkTypesDuplication($configs);
38
        // flatten config is a requirement to support inheritance
39 30
        $flattenConfig = [call_user_func_array('array_merge', $configs)];
40 30
        $configuration = $this->getConfiguration($flattenConfig, $container);
41 30
        $config = $this->processConfiguration($configuration, $flattenConfig);
0 ignored issues
show
Bug introduced by
It seems like $configuration defined by $this->getConfiguration(...ttenConfig, $container) on line 40 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...
42
43 25
        $container->setParameter($this->getAlias().'.config', $config);
44 25
    }
45
46 26
    public function containerPrependExtensionConfig(array $config, ContainerBuilder $container)
47
    {
48 26
        $typesMappings = $this->mappingConfig($config, $container);
49
        // reset treated files
50 26
        $this->treatedFiles = [];
51
        // treats mappings
52 26
        foreach ($typesMappings as $params) {
53 26
            $this->prependExtensionConfigFromFiles($params['type'], $params['files'], $container);
54
        }
55 24
    }
56
57
    /**
58
     * @param $type
59
     * @param SplFileInfo[]    $files
60
     * @param ContainerBuilder $container
61
     */
62 26
    private function prependExtensionConfigFromFiles($type, $files, ContainerBuilder $container)
63
    {
64 26
        foreach ($files as $file) {
65 26
            $fileRealPath = $file->getRealPath();
66 26
            if (isset($this->treatedFiles[$fileRealPath])) {
67 1
                continue;
68
            }
69
70 26
            $parserClass = sprintf('Overblog\\GraphQLBundle\\Config\\Parser\\%sParser', ucfirst($type));
71
72 26
            $typeConfig = call_user_func($parserClass.'::parse', $file, $container);
73 24
            $container->prependExtensionConfig($this->getAlias(), $typeConfig);
74 24
            $this->treatedFiles[$file->getRealPath()] = true;
75
        }
76 24
    }
77
78 31
    private function checkTypesDuplication(array $typeConfigs)
79
    {
80 31
        $types = call_user_func_array('array_merge', array_map('array_keys', $typeConfigs));
81 31
        $duplications = array_keys(array_filter(array_count_values($types), function ($count) {
82 31
            return $count > 1;
83 31
        }));
84 31
        if (!empty($duplications)) {
85 1
            throw new ForbiddenOverwriteException(sprintf(
86 1
                'Types (%s) cannot be overwritten. See inheritance doc section for more details.',
87 1
                implode(', ', array_map('json_encode', $duplications))
88
            ));
89
        }
90 30
    }
91
92 26
    private function mappingConfig(array $config, ContainerBuilder $container)
93
    {
94
        // use default value if needed
95 26
        $config = array_replace_recursive(self::$defaultDefaultConfig, $config);
96
97 26
        $mappingConfig = $config['definitions']['mappings'];
98 26
        $typesMappings = $mappingConfig['types'];
99
100
        // app only config files (yml or xml)
101 26
        if ($mappingConfig['auto_discover']['root_dir'] && $container->hasParameter('kernel.root_dir')) {
102 1
            $typesMappings[] = ['dir' => $container->getParameter('kernel.root_dir').'/config/graphql', 'type' => null];
103
        }
104 26
        if ($mappingConfig['auto_discover']['bundles']) {
105 3
            $mappingFromBundles = $this->mappingFromBundles($container);
106 3
            $typesMappings = array_merge($typesMappings, $mappingFromBundles);
107
        } else {
108
            // enabled only for this bundle
109 23
            $typesMappings[] = [
110 23
                'dir' => $this->bundleDir(OverblogGraphQLBundle::class).'/Resources/config/graphql',
111 23
                'type' => 'yaml',
112
            ];
113
        }
114
115
        // from config
116 26
        $typesMappings = $this->detectFilesFromTypesMappings($typesMappings, $container);
117
118 26
        return $typesMappings;
119
    }
120
121 26
    private function detectFilesFromTypesMappings(array $typesMappings, ContainerBuilder $container)
122
    {
123 26
        return array_filter(array_map(
124 26
            function (array $typeMapping) use ($container) {
125 26
                $params = $this->detectFilesByType(
126 26
                    $container,
127 26
                    $typeMapping['dir'],
128 26
                    $typeMapping['type'],
129 26
                    isset($typeMapping['suffix']) ? $typeMapping['suffix'] : ''
130
                );
131
132 26
                return $params;
133 26
            },
134 26
            $typesMappings
135
        ));
136
    }
137
138 3
    private function mappingFromBundles(ContainerBuilder $container)
139
    {
140 3
        $typesMappings = [];
141 3
        $bundles = $container->getParameter('kernel.bundles');
142
143
        // auto detect from bundle
144 3
        foreach ($bundles as $name => $class) {
145 1
            $bundleDir = $this->bundleDir($class);
146
147
            // only config files (yml or xml)
148 1
            $typesMappings[] = ['dir' => $bundleDir.'/Resources/config/graphql', 'type' => null];
149
        }
150
151 3
        return $typesMappings;
152
    }
153
154 26
    private function detectFilesByType(ContainerBuilder $container, $path, $type, $suffix)
155
    {
156
        // add the closest existing directory as a resource
157 26
        $resource = $path;
158 26
        while (!is_dir($resource)) {
159 1
            $resource = dirname($resource);
160
        }
161 26
        $container->addResource(new FileResource($resource));
162
163 26
        $finder = new Finder();
164
165 26
        $types = null === $type ? self::$configTypes : [$type];
166
167 26
        foreach ($types as $type) {
168
            try {
169 26
                $finder->files()->in($path)->name('*'.$suffix.'.'.self::$typeExtensions[$type]);
170 1
            } catch (\InvalidArgumentException $e) {
171 1
                continue;
172
            }
173 26
            if ($finder->count() > 0) {
174
                return [
175 26
                    'type' => $type,
176 26
                    'files' => $finder,
177
                ];
178
            }
179
        }
180
181 1
        return;
182
    }
183
184 24
    private function bundleDir($bundleClass)
185
    {
186 24
        $bundle = new \ReflectionClass($bundleClass);
187 24
        $bundleDir = dirname($bundle->getFileName());
188
189 24
        return $bundleDir;
190
    }
191
192 25
    public function getAliasPrefix()
193
    {
194 25
        return 'overblog_graphql';
195
    }
196
197 25
    public function getAlias()
198
    {
199 25
        return $this->getAliasPrefix().'_types';
200
    }
201
202 30
    public function getConfiguration(array $config, ContainerBuilder $container)
203
    {
204 30
        return new TypesConfiguration();
205
    }
206
}
207