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 ( 0cc865...29f953 )
by Jérémiah
19s queued 10s
created

BuilderProcessor::getFieldBuilderMapping()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 23
dl 0
loc 37
ccs 23
cts 23
cp 1
rs 8.9297
c 0
b 0
f 0
cc 6
nc 9
nop 4
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\Config\Processor;
6
7
use Overblog\GraphQLBundle\Definition\Builder\MappingInterface;
8
use Overblog\GraphQLBundle\Relay\Connection\BackwardConnectionArgsDefinition;
9
use Overblog\GraphQLBundle\Relay\Connection\ConnectionArgsDefinition;
10
use Overblog\GraphQLBundle\Relay\Connection\ForwardConnectionArgsDefinition;
11
use Overblog\GraphQLBundle\Relay\Mutation\MutationFieldDefinition;
12
use Overblog\GraphQLBundle\Relay\Node\GlobalIdFieldDefinition;
13
use Overblog\GraphQLBundle\Relay\Node\NodeFieldDefinition;
14
use Overblog\GraphQLBundle\Relay\Node\PluralIdentifyingRootFieldDefinition;
15
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
16
17
final class BuilderProcessor implements ProcessorInterface
18
{
19
    public const BUILDER_FIELD_TYPE = 'field';
20
    public const BUILDER_FIELDS_TYPE = 'fields';
21
    public const BUILDER_ARGS_TYPE = 'args';
22
23
    public const BUILDER_TYPES = [
24
        self::BUILDER_FIELD_TYPE,
25
        self::BUILDER_FIELDS_TYPE,
26
        self::BUILDER_ARGS_TYPE,
27
    ];
28
29
    /** @var MappingInterface[] */
30
    private static $builderClassMap = [
31
        self::BUILDER_ARGS_TYPE => [
32
            'Relay::ForwardConnection' => ForwardConnectionArgsDefinition::class,
33
            'Relay::BackwardConnection' => BackwardConnectionArgsDefinition::class,
34
            'Relay::Connection' => ConnectionArgsDefinition::class,
35
        ],
36
        self::BUILDER_FIELD_TYPE => [
37
            'Relay::Mutation' => MutationFieldDefinition::class,
38
            'Relay::GlobalId' => GlobalIdFieldDefinition::class,
39
            'Relay::Node' => NodeFieldDefinition::class,
40
            'Relay::PluralIdentifyingRoot' => PluralIdentifyingRootFieldDefinition::class,
41
        ],
42
        self::BUILDER_FIELDS_TYPE => [],
43
    ];
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 43
    public static function process(array $configs): array
49
    {
50 43
        $addedTypes = [];
51
        // map: "type name" => "provided by" for better DX, while debugging accidental type overrides in builders
52 43
        $reservedTypesMap = \array_combine(
53 43
            \array_keys($configs),
54 43
            \array_fill(0, \count($configs), 'configs')
55
        );
56
57 43
        foreach ($configs as &$config) {
58 43
            if (isset($config['config']['builders']) && \is_array($config['config']['builders'])) {
59 3
                ['fields' => $buildersFields, 'types' => $buildersTypes] = self::processFieldsBuilders(
60 3
                    $config['config']['builders'],
61 3
                    $reservedTypesMap
0 ignored issues
show
Bug introduced by
It seems like $reservedTypesMap can also be of type false; however, parameter $reservedTypesMap of Overblog\GraphQLBundle\C...processFieldsBuilders() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
                    /** @scrutinizer ignore-type */ $reservedTypesMap
Loading history...
62
                );
63
64 2
                $config['config']['fields'] = isset($config['config']['fields'])
65 1
                    ? \array_merge($buildersFields, $config['config']['fields'])
66 2
                    : $buildersFields;
67
68 2
                $addedTypes = \array_merge($addedTypes, $buildersTypes);
69
70 2
                unset($config['config']['builders']);
71
            }
72
73 42
            if (isset($config['config']['fields']) && \is_array($config['config']['fields'])) {
74 37
                ['fields' => $buildersFields, 'types' => $buildersTypes] = self::processFieldBuilders(
75 37
                    $config['config']['fields'],
76 37
                    $reservedTypesMap
77
                );
78
79 33
                $config['config']['fields'] = $buildersFields;
80
81 33
                $addedTypes = \array_merge($addedTypes, $buildersTypes);
82
            }
83
        }
84
85 37
        return \array_merge($configs, $addedTypes);
86
    }
87
88 15
    public static function addBuilderClass($name, $type, $builderClass): void
89
    {
90 15
        self::checkBuilderClass($builderClass, $type);
91 5
        self::$builderClassMap[$type][$name] = $builderClass;
92 5
    }
93
94
    /**
95
     * @param string $builderClass
96
     * @param string $type
97
     */
98 15
    private static function checkBuilderClass($builderClass, $type): void
99
    {
100 15
        $interface = MappingInterface::class;
101
102 15
        if (!\is_string($builderClass)) {
0 ignored issues
show
introduced by
The condition is_string($builderClass) is always true.
Loading history...
103 5
            throw new \InvalidArgumentException(
104 5
                \sprintf('%s builder class should be string, but %s given.', \ucfirst($type), \gettype($builderClass))
105
            );
106
        }
107
108 10
        if (!\class_exists($builderClass)) {
109 2
            throw new \InvalidArgumentException(
110 2
                \sprintf('%s builder class "%s" not found.', \ucfirst($type), $builderClass)
111
            );
112
        }
113
114 8
        if (!\is_subclass_of($builderClass, $interface)) {
115 3
            throw new \InvalidArgumentException(
116 3
                \sprintf(
117 3
                    '%s builder class should implement "%s", but "%s" given.',
118 3
                    \ucfirst($type),
119 3
                    $interface,
120 3
                    $builderClass
121
                )
122
            );
123
        }
124 5
    }
125
126 37
    private static function processFieldBuilders(array $fields, array &$reservedTypesMap)
127
    {
128 37
        $newTypes = [];
129
130 37
        foreach ($fields as &$field) {
131 37
            $fieldBuilderName = null;
132
133 37
            if (isset($field['builder']) && \is_string($field['builder'])) {
134 11
                $fieldBuilderName = $field['builder'];
135 11
                unset($field['builder']);
136 34
            } elseif (\is_string($field)) {
137 2
                @\trigger_error(
138
                    'The builder short syntax (Field: Builder => Field: {builder: Builder}) is deprecated as of 0.7 and will be removed in 0.12. '.
139 2
                    'It will be replaced by the field type short syntax (Field: Type => Field: {type: Type})',
140 2
                    \E_USER_DEPRECATED
141
                );
142 2
                $fieldBuilderName = $field;
143
            }
144
145 37
            $builderConfig = [];
146 37
            if (isset($field['builderConfig'])) {
147 10
                if (\is_array($field['builderConfig'])) {
148 10
                    $builderConfig = $field['builderConfig'];
149
                }
150 10
                unset($field['builderConfig']);
151
            }
152
153 37
            if ($fieldBuilderName) {
154 11
                $mapping = self::getFieldBuilderMapping($fieldBuilderName, self::BUILDER_FIELD_TYPE, $builderConfig, $reservedTypesMap);
155
156 9
                $fieldMapping = $mapping['field'];
157 9
                $field = \is_array($field) ? \array_merge($fieldMapping, $field) : $fieldMapping;
158 9
                $newTypes = \array_merge($newTypes, $mapping['types']);
159
            }
160 35
            if (isset($field['argsBuilder'])) {
161 15
                $field = self::processFieldArgumentsBuilders($field);
162
            }
163
        }
164
165
        return [
166 33
            'fields' => $fields,
167 33
            'types' => $newTypes,
168
        ];
169
    }
170
171 3
    private static function processFieldsBuilders(array $builders, array &$reservedTypesMap)
172
    {
173 3
        $fields = [];
174 3
        $newTypes = [];
175
176 3
        foreach ($builders as $builder) {
177 3
            $builderName = $builder['builder'];
178 3
            $builderConfig = $builder['builderConfig'] ?? null;
179
180 3
            $mapping = self::getFieldBuilderMapping($builderName, self::BUILDER_FIELDS_TYPE, $builderConfig, $reservedTypesMap);
0 ignored issues
show
Bug introduced by
It seems like $builderConfig can also be of type null; however, parameter $builderConfig of Overblog\GraphQLBundle\C...etFieldBuilderMapping() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

180
            $mapping = self::getFieldBuilderMapping($builderName, self::BUILDER_FIELDS_TYPE, /** @scrutinizer ignore-type */ $builderConfig, $reservedTypesMap);
Loading history...
181
182 2
            $fields = \array_merge($fields, $mapping['fields']);
183 2
            $newTypes = \array_merge($newTypes, $mapping['types']);
184
        }
185
186
        return [
187 2
            'fields' => $fields,
188 2
            'types' => $newTypes,
189
        ];
190
    }
191
192
    /**
193
     * @param string $builderName
194
     * @param string $builderType
195
     * @param array  $builderConfig
196
     * @param array  $reservedTypesMap
197
     *
198
     * @return array
199
     *
200
     * @throws InvalidConfigurationException
201
     */
202 13
    private static function getFieldBuilderMapping(string $builderName, string $builderType, array $builderConfig, array &$reservedTypesMap)
203
    {
204 13
        $builder = self::getBuilder($builderName, $builderType);
205 12
        $mapping = $builder->toMappingDefinition($builderConfig);
206
207 12
        $fieldMappingKey = null;
208
209 12
        if (self::BUILDER_FIELD_TYPE === $builderType) {
210 10
            $fieldMappingKey = 'field';
211 3
        } elseif (self::BUILDER_FIELDS_TYPE === $builderType) {
212 3
            $fieldMappingKey = 'fields';
213
        }
214
215 12
        $fieldMapping = $mapping[$fieldMappingKey] ?? $mapping;
216 12
        $typesMapping = [];
217
218 12
        if (isset($mapping[$fieldMappingKey], $mapping['types'])) {
219 5
            $builderClass = \get_class($builder);
220
221 5
            foreach ($mapping['types'] as $typeName => $typeConfig) {
222 5
                if (isset($reservedTypesMap[$typeName])) {
223 4
                    throw new InvalidConfigurationException(\sprintf(
224 4
                        'Type "%s" emitted by builder "%s" already exists. Type was provided by "%s". Builder may only emit new types. Overriding is not allowed.',
225 4
                        $typeName,
226 4
                        $builderClass,
227 4
                        $reservedTypesMap[$typeName]
228
                    ));
229
                }
230
231 3
                $reservedTypesMap[$typeName] = $builderClass;
232 3
                $typesMapping[$typeName] = $typeConfig;
233
            }
234
        }
235
236
        return [
237 10
            $fieldMappingKey => $fieldMapping,
238 10
            'types' => $typesMapping,
239
        ];
240
    }
241
242
    /**
243
     * @param string $name
244
     * @param string $type
245
     *
246
     * @return MappingInterface
247
     *
248
     * @throws InvalidConfigurationException if builder class not define
249
     */
250 26
    private static function getBuilder($name, $type)
251
    {
252 26
        static $builders = [];
253 26
        if (isset($builders[$type][$name])) {
254 21
            return $builders[$type][$name];
255
        }
256
257 12
        $builderClassMap = self::$builderClassMap[$type];
258
259 12
        if (isset($builderClassMap[$name])) {
260 9
            return $builders[$type][$name] = new $builderClassMap[$name]();
261
        }
262
        // deprecated relay builder name ?
263 3
        $newName = 'Relay::'.\rtrim($name, 'Args');
264 3
        if (isset($builderClassMap[$newName])) {
265 1
            @\trigger_error(
266 1
                \sprintf('The "%s" %s builder is deprecated as of 0.7 and will be removed in 0.12. Use "%s" instead.', $name, $type, $newName),
267 1
                \E_USER_DEPRECATED
268
            );
269
270 1
            return $builders[$type][$newName] = new $builderClassMap[$newName]();
271
        }
272
273 2
        throw new InvalidConfigurationException(\sprintf('%s builder "%s" not found.', \ucfirst($type), $name));
274
    }
275
276 15
    private static function processFieldArgumentsBuilders(array $field)
277
    {
278 15
        $argsBuilderName = null;
279
280 15
        if (\is_string($field['argsBuilder'])) {
281 15
            $argsBuilderName = $field['argsBuilder'];
282 1
        } elseif (isset($field['argsBuilder']['builder']) && \is_string($field['argsBuilder']['builder'])) {
283 1
            $argsBuilderName = $field['argsBuilder']['builder'];
284
        }
285
286 15
        $builderConfig = [];
287 15
        if (isset($field['argsBuilder']['config']) && \is_array($field['argsBuilder']['config'])) {
288 1
            $builderConfig = $field['argsBuilder']['config'];
289
        }
290
291 15
        if ($argsBuilderName) {
292 15
            $args = self::getBuilder($argsBuilderName, self::BUILDER_ARGS_TYPE)->toMappingDefinition($builderConfig);
293 14
            $field['args'] = isset($field['args']) && \is_array($field['args']) ? \array_merge($args, $field['args']) : $args;
294
        }
295
296 14
        unset($field['argsBuilder']);
297
298 14
        return $field;
299
    }
300
}
301