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 — 0.12 (#797)
by Jérémiah
22:42 queued 19:44
created

ConfigParserPass::getAliasPrefix()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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