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

detectFilesByTypes()   C

Complexity

Conditions 7
Paths 20

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7

Importance

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