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

Completed
Push — master ( 7e5601...2a112f )
by Jérémiah
16:11 queued 15s
created

preParseTypeConfigFiles()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.0312

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 11
ccs 7
cts 8
cp 0.875
rs 10
c 0
b 0
f 0
cc 4
nc 4
nop 4
crap 4.0312
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\DependencyInjection;
6
7
use Overblog\GraphQLBundle\Config\Parser\AnnotationParser;
8
use Overblog\GraphQLBundle\Config\Parser\GraphQLParser;
9
use Overblog\GraphQLBundle\Config\Parser\PreParserInterface;
10
use Overblog\GraphQLBundle\Config\Parser\XmlParser;
11
use Overblog\GraphQLBundle\Config\Parser\YamlParser;
12
use Overblog\GraphQLBundle\OverblogGraphQLBundle;
13
use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
14
use Symfony\Component\Config\Resource\FileResource;
15
use Symfony\Component\DependencyInjection\ContainerBuilder;
16
use Symfony\Component\Finder\Finder;
17
use Symfony\Component\Finder\SplFileInfo;
18
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
19
20
class OverblogGraphQLTypesExtension extends Extension
21
{
22
    public const SUPPORTED_TYPES_EXTENSIONS = [
23
        'yaml' => '{yaml,yml}',
24
        'xml' => 'xml',
25
        'graphql' => '{graphql,graphqls}',
26
        'annotation' => 'php',
27
    ];
28
29
    public const PARSERS = [
30
        'yaml' => YamlParser::class,
31
        'xml' => XmlParser::class,
32
        'graphql' => GraphQLParser::class,
33
        'annotation' => AnnotationParser::class,
34
    ];
35
36
    private static $defaultDefaultConfig = [
37
        'definitions' => [
38
            'mappings' => [
39
                'auto_discover' => [
40
                    'root_dir' => true,
41
                    'bundles' => true,
42
                ],
43
                'types' => [],
44
            ],
45
        ],
46
    ];
47
48
    private $treatedFiles = [];
49
    private $preTreatedFiles = [];
50
51
    public const DEFAULT_TYPES_SUFFIX = '.types';
52
53 42
    public function load(array $configs, ContainerBuilder $container): void
54
    {
55 42
        $configs = \array_filter($configs);
56 42
        if (\count($configs) > 1) {
57 1
            throw new \InvalidArgumentException('Configs type should never contain more than one config to deal with inheritance.');
58
        }
59 41
        $configuration = $this->getConfiguration($configs, $container);
60 41
        $config = $this->processConfiguration($configuration, $configs);
61
62 32
        $container->setParameter($this->getAlias().'.config', $config);
63 32
    }
64
65 34
    public function containerPrependExtensionConfig(array $configs, ContainerBuilder $container): void
66
    {
67 34
        $container->setParameter('overblog_graphql_types.classes_map', []);
68 34
        $typesMappings = $this->mappingConfig($configs, $container);
69
        // reset treated files
70 34
        $this->treatedFiles = [];
71 34
        $typesMappings = \array_merge(...$typesMappings);
72 34
        $typeConfigs = [];
73
74
        // treats mappings
75
        // Pre-parse all files
76 34
        $typesNeedPreParsing = $this->typesNeedPreParsing();
77 34
        foreach ($typesMappings as $params) {
78 34
            if ($typesNeedPreParsing[$params['type']]) {
79 1
                $this->parseTypeConfigFiles($params['type'], $params['files'], $container, $configs, true);
80
            }
81
        }
82
83
        // Parse all files and get related config
84 34
        foreach ($typesMappings as $params) {
85 34
            $typeConfigs = \array_merge($typeConfigs, $this->parseTypeConfigFiles($params['type'], $params['files'], $container, $configs));
86
        }
87
88 32
        $this->checkTypesDuplication($typeConfigs);
89
        // flatten config is a requirement to support inheritance
90 32
        $flattenTypeConfig = \array_merge(...$typeConfigs);
91
92 32
        $container->prependExtensionConfig($this->getAlias(), $flattenTypeConfig);
93 32
    }
94
95 34
    private function typesNeedPreParsing(): array
96
    {
97 34
        $needPreParsing = [];
98 34
        foreach (self::PARSERS as $type => $className) {
99 34
            $needPreParsing[$type] = \is_a($className, PreParserInterface::class, true);
100
        }
101
102 34
        return $needPreParsing;
103
    }
104
105
    /**
106
     * @param $type
107
     * @param SplFileInfo[]    $files
108
     * @param ContainerBuilder $container
109
     * @param array            $configs
110
     * @param bool             $preParse
111
     *
112
     * @return array
113
     */
114 34
    private function parseTypeConfigFiles($type, $files, ContainerBuilder $container, array $configs, bool $preParse = false)
115
    {
116 34
        if ($preParse) {
117 1
            $method = 'preParse';
118 1
            $treatedFiles = &$this->preTreatedFiles;
119
        } else {
120 34
            $method = 'parse';
121 34
            $treatedFiles = &$this->treatedFiles;
122
        }
123
124 34
        $config = [];
125 34
        foreach ($files as $file) {
126 34
            $fileRealPath = $file->getRealPath();
127 34
            if (isset($treatedFiles[$fileRealPath])) {
128 1
                continue;
129
            }
130
131 34
            $config[] = \call_user_func([self::PARSERS[$type], $method], $file, $container, $configs);
132 32
            $treatedFiles[$file->getRealPath()] = true;
133
        }
134
135 32
        return $config;
136
    }
137
138 32
    private function checkTypesDuplication(array $typeConfigs): void
139
    {
140 32
        $types = \array_merge(...\array_map('array_keys', $typeConfigs));
141
        $duplications = \array_keys(\array_filter(\array_count_values($types), function ($count) {
142 32
            return $count > 1;
143 32
        }));
144 32
        if (!empty($duplications)) {
145
            throw new ForbiddenOverwriteException(\sprintf(
146
                'Types (%s) cannot be overwritten. See inheritance doc section for more details.',
147
                \implode(', ', \array_map('json_encode', $duplications))
148
            ));
149
        }
150 32
    }
151
152 34
    private function mappingConfig(array $config, ContainerBuilder $container)
153
    {
154
        // use default value if needed
155 34
        $config = \array_replace_recursive(self::$defaultDefaultConfig, $config);
156
157 34
        $mappingConfig = $config['definitions']['mappings'];
158 34
        $typesMappings = $mappingConfig['types'];
159
160
        // app only config files (yml or xml or graphql)
161 34
        if ($mappingConfig['auto_discover']['root_dir'] && $container->hasParameter('kernel.root_dir')) {
162 1
            $typesMappings[] = ['dir' => $container->getParameter('kernel.root_dir').'/config/graphql', 'types' => null];
163
        }
164 34
        if ($mappingConfig['auto_discover']['bundles']) {
165 4
            $mappingFromBundles = $this->mappingFromBundles($container);
166 4
            $typesMappings = \array_merge($typesMappings, $mappingFromBundles);
167
        } else {
168
            // enabled only for this bundle
169 30
            $typesMappings[] = [
170 30
                'dir' => $this->bundleDir(OverblogGraphQLBundle::class).'/Resources/config/graphql',
171
                'types' => ['yaml'],
172
            ];
173
        }
174
175
        // from config
176 34
        $typesMappings = $this->detectFilesFromTypesMappings($typesMappings, $container);
177
178 34
        return $typesMappings;
179
    }
180
181 34
    private function detectFilesFromTypesMappings(array $typesMappings, ContainerBuilder $container)
182
    {
183 34
        return \array_filter(\array_map(
184
            function (array $typeMapping) use ($container) {
185 34
                $suffix = $typeMapping['suffix'] ?? '';
186 34
                $types = $typeMapping['types'] ?? null;
187 34
                $params = $this->detectFilesByTypes($container, $typeMapping['dir'], $suffix, $types);
188
189 34
                return $params;
190 34
            },
191 34
            $typesMappings
192
        ));
193
    }
194
195 4
    private function mappingFromBundles(ContainerBuilder $container)
196
    {
197 4
        $typesMappings = [];
198 4
        $bundles = $container->getParameter('kernel.bundles');
199
200
        // auto detect from bundle
201 4
        foreach ($bundles as $name => $class) {
202 1
            $bundleDir = $this->bundleDir($class);
203
204
            // only config files (yml or xml)
205 1
            $typesMappings[] = ['dir' => $bundleDir.'/Resources/config/graphql', 'types' => null];
206
        }
207
208 4
        return $typesMappings;
209
    }
210
211 34
    private function detectFilesByTypes(ContainerBuilder $container, $path, $suffix, array $types = null)
212
    {
213
        // add the closest existing directory as a resource
214 34
        $resource = $path;
215 34
        while (!\is_dir($resource)) {
216 1
            $resource = \dirname($resource);
217
        }
218 34
        $container->addResource(new FileResource($resource));
219
220 34
        $stopOnFirstTypeMatching = empty($types);
221
222 34
        $types = $stopOnFirstTypeMatching ? \array_keys(self::SUPPORTED_TYPES_EXTENSIONS) : $types;
223 34
        $files = [];
224
225 34
        foreach ($types as $type) {
226 34
            $finder = Finder::create();
227
            try {
228 34
                $finder->files()->in($path)->name(\sprintf('*%s.%s', $suffix, self::SUPPORTED_TYPES_EXTENSIONS[$type]));
229 1
            } catch (\InvalidArgumentException $e) {
230 1
                continue;
231
            }
232 34
            if ($finder->count() > 0) {
233 34
                $files[] = [
234 34
                    'type' => $type,
235 34
                    'files' => $finder,
236
                ];
237 34
                if ($stopOnFirstTypeMatching) {
238 1
                    break;
239
                }
240
            }
241
        }
242
243 34
        return $files;
244
    }
245
246 31
    private function bundleDir($bundleClass)
247
    {
248 31
        $bundle = new \ReflectionClass($bundleClass);
249 31
        $bundleDir = \dirname($bundle->getFileName());
250
251 31
        return $bundleDir;
252
    }
253
254 33
    public function getAliasPrefix()
255
    {
256 33
        return 'overblog_graphql';
257
    }
258
259 33
    public function getAlias()
260
    {
261 33
        return $this->getAliasPrefix().'_types';
262
    }
263
264 41
    public function getConfiguration(array $config, ContainerBuilder $container)
265
    {
266 41
        return new TypesConfiguration();
267
    }
268
}
269