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
Push — master ( 03b41e...519a64 )
by Jérémiah
25:22
created

OverblogGraphQLTypesExtension::bundleDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
crap 1
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
        ],
36
    ];
37
38
    private $treatedFiles = [];
39
40
    const DEFAULT_TYPES_SUFFIX = '.types';
41
42 35
    public function load(array $configs, ContainerBuilder $container)
43
    {
44 35
        $configs = array_filter($configs);
45
        //$configs = array_filter($configs);
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
46 34
        if (count($configs) > 1) {
47 34
            throw new \InvalidArgumentException('Configs type should never contain more than one config to deal with inheritance.');
48 34
        }
49
        $configuration = $this->getConfiguration($configs, $container);
50 29
        $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
Bug introduced by
It seems like $configuration defined by $this->getConfiguration($configs, $container) on line 49 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...
51 29
52
        $container->setParameter($this->getAlias().'.config', $config);
53 30
    }
54
55 30
    public function containerPrependExtensionConfig(array $configs, ContainerBuilder $container)
56
    {
57 30
        $typesMappings = $this->mappingConfig($configs, $container);
58 30
        // reset treated files
59
        $this->treatedFiles = [];
60 30
        $typesMappings = call_user_func_array('array_merge', $typesMappings);
61 30
        $typeConfigs = [];
62
        // treats mappings
63 28
        foreach ($typesMappings as $params) {
64
            $typeConfigs = array_merge($typeConfigs, $this->parseTypeConfigFiles($params['type'], $params['files'], $container));
65
        }
66
67
        $this->checkTypesDuplication($typeConfigs);
68
        // flatten config is a requirement to support inheritance
69
        $flattenTypeConfig = call_user_func_array('array_merge', $typeConfigs);
70 30
71
        $container->prependExtensionConfig($this->getAlias(), $flattenTypeConfig);
72 30
    }
73 30
74 30
    /**
75 1
     * @param $type
76
     * @param SplFileInfo[]    $files
77
     * @param ContainerBuilder $container
78 30
     *
79 28
     * @return array
80 28
     */
81
    private function parseTypeConfigFiles($type, $files, ContainerBuilder $container)
82 28
    {
83
        $config = [];
84 35
        foreach ($files as $file) {
85
            $fileRealPath = $file->getRealPath();
86 35
            if (isset($this->treatedFiles[$fileRealPath])) {
87 35
                continue;
88 35
            }
89 35
90 35
            $config[] = call_user_func(self::PARSERS[$type].'::parse', $file, $container);
91 1
            $this->treatedFiles[$file->getRealPath()] = true;
92 1
        }
93 1
94
        return $config;
95
    }
96 34
97
    private function checkTypesDuplication(array $typeConfigs)
98 30
    {
99
        $types = call_user_func_array('array_merge', array_map('array_keys', $typeConfigs));
100
        $duplications = array_keys(array_filter(array_count_values($types), function ($count) {
101 30
            return $count > 1;
102
        }));
103 30
        if (!empty($duplications)) {
104 30
            throw new ForbiddenOverwriteException(sprintf(
105
                'Types (%s) cannot be overwritten. See inheritance doc section for more details.',
106
                implode(', ', array_map('json_encode', $duplications))
107 30
            ));
108 1
        }
109
    }
110 30
111 3
    private function mappingConfig(array $config, ContainerBuilder $container)
112 3
    {
113
        // use default value if needed
114
        $config = array_replace_recursive(self::$defaultDefaultConfig, $config);
115 27
116 27
        $mappingConfig = $config['definitions']['mappings'];
117
        $typesMappings = $mappingConfig['types'];
118
119
        // app only config files (yml or xml or graphql)
120
        if ($mappingConfig['auto_discover']['root_dir'] && $container->hasParameter('kernel.root_dir')) {
121
            $typesMappings[] = ['dir' => $container->getParameter('kernel.root_dir').'/config/graphql', 'types' => null];
122 30
        }
123
        if ($mappingConfig['auto_discover']['bundles']) {
124 30
            $mappingFromBundles = $this->mappingFromBundles($container);
125
            $typesMappings = array_merge($typesMappings, $mappingFromBundles);
126
        } else {
127 30
            // enabled only for this bundle
128
            $typesMappings[] = [
129 30
                'dir' => $this->bundleDir(OverblogGraphQLBundle::class).'/Resources/config/graphql',
130 30
                'types' => ['yaml'],
131 30
            ];
132 30
        }
133 30
134
        // from config
135 30
        $typesMappings = $this->detectFilesFromTypesMappings($typesMappings, $container);
136 30
137 30
        return $typesMappings;
138
    }
139
140
    private function detectFilesFromTypesMappings(array $typesMappings, ContainerBuilder $container)
141 3
    {
142
        return array_filter(array_map(
143 3
            function (array $typeMapping) use ($container) {
144 3
                $suffix = isset($typeMapping['suffix']) ? $typeMapping['suffix'] : '';
145
                $types = isset($typeMapping['types']) ? $typeMapping['types'] : null;
146
                $params = $this->detectFilesByTypes($container, $typeMapping['dir'], $suffix, $types);
147 3
148 1
                return $params;
149
            },
150
            $typesMappings
151 1
        ));
152
    }
153
154 3
    private function mappingFromBundles(ContainerBuilder $container)
155
    {
156
        $typesMappings = [];
157 30
        $bundles = $container->getParameter('kernel.bundles');
158
159
        // auto detect from bundle
160 30
        foreach ($bundles as $name => $class) {
161 30
            $bundleDir = $this->bundleDir($class);
162 1
163
            // only config files (yml or xml)
164 30
            $typesMappings[] = ['dir' => $bundleDir.'/Resources/config/graphql', 'types' => null];
165
        }
166 30
167
        return $typesMappings;
168 30
    }
169 30
170
    private function detectFilesByTypes(ContainerBuilder $container, $path, $suffix, array $types = null)
171 30
    {
172 30
        // add the closest existing directory as a resource
173
        $resource = $path;
174 30
        while (!is_dir($resource)) {
175 1
            $resource = dirname($resource);
176 1
        }
177
        $container->addResource(new FileResource($resource));
178 30
179 30
        $stopOnFirstTypeMatching = empty($types);
180 30
181 30
        $types = $stopOnFirstTypeMatching ? array_keys(self::SUPPORTED_TYPES_EXTENSIONS) : $types;
182
        $files = [];
183 30
184 30
        foreach ($types as $type) {
185
            $finder = Finder::create();
186
            try {
187
                $finder->files()->in($path)->name(sprintf('*%s.%s', $suffix, self::SUPPORTED_TYPES_EXTENSIONS[$type]));
188
            } catch (\InvalidArgumentException $e) {
189 30
                continue;
190
            }
191
            if ($finder->count() > 0) {
192 28
                $files[] = [
193
                    'type' => $type,
194 28
                    'files' => $finder,
195 28
                ];
196
                if ($stopOnFirstTypeMatching) {
197 28
                    break;
198
                }
199
            }
200 29
        }
201
202 29
        return $files;
203
    }
204
205 29
    private function bundleDir($bundleClass)
206
    {
207 29
        $bundle = new \ReflectionClass($bundleClass);
208
        $bundleDir = dirname($bundle->getFileName());
209
210 34
        return $bundleDir;
211
    }
212 34
213
    public function getAliasPrefix()
214
    {
215
        return 'overblog_graphql';
216
    }
217
218
    public function getAlias()
219
    {
220
        return $this->getAliasPrefix().'_types';
221
    }
222
223
    public function getConfiguration(array $config, ContainerBuilder $container)
224
    {
225
        return new TypesConfiguration();
226
    }
227
}
228