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 (#254)
by Jérémiah
09:17
created

GraphQLParser::parse()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 15
cts 15
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 16
nc 7
nop 2
crap 5
1
<?php
2
3
namespace Overblog\GraphQLBundle\Config\Parser;
4
5
use GraphQL\Language\AST\FieldDefinitionNode;
6
use GraphQL\Language\AST\InputValueDefinitionNode;
7
use GraphQL\Language\AST\Node;
8
use GraphQL\Language\AST\NodeKind;
9
use GraphQL\Language\AST\TypeNode;
10
use GraphQL\Language\AST\ValueNode;
11
use GraphQL\Language\Parser;
12
use Symfony\Component\Config\Resource\FileResource;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
15
16
class GraphQLParser implements ParserInterface
17
{
18
    /** @var self */
19
    private static $parser;
20
21
    const DEFINITION_TYPE_MAPPING = [
22
        NodeKind::OBJECT_TYPE_DEFINITION => 'object',
23
        NodeKind::INTERFACE_TYPE_DEFINITION => 'interface',
24
        NodeKind::ENUM_TYPE_DEFINITION => 'enum',
25
        NodeKind::UNION_TYPE_DEFINITION => 'union',
26
        NodeKind::INPUT_OBJECT_TYPE_DEFINITION => 'input-object',
27
    ];
28
29
    /**
30
     * {@inheritdoc}
31
     */
32 6
    public static function parse(\SplFileInfo $file, ContainerBuilder $container)
33
    {
34 6
        $container->addResource(new FileResource($file->getRealPath()));
35 6
        $content = trim(file_get_contents($file->getPathname()));
36 6
        $typesConfig = [];
37
38
        // allow empty files
39 6
        if (empty($content)) {
40 1
            return [];
41
        }
42 5
        if (!self::$parser) {
43 1
            self::$parser = new static();
44
        }
45
        try {
46 5
            $ast = Parser::parse($content);
47 1
        } catch (\Exception $e) {
48 1
            throw new InvalidArgumentException(sprintf('An error occurred while parsing the file "%s".', $file), $e->getCode(), $e);
49
        }
50
51
        /** @var Node $typeDef */
52 4
        foreach ($ast->definitions as $typeDef) {
53 4
            $typeConfig = self::$parser->typeDefinitionToConfig($typeDef);
0 ignored issues
show
Documentation introduced by
$typeDef is of type object<GraphQL\Language\AST\DefinitionNode>, but the function expects a object<GraphQL\Language\AST\Node>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
54 2
            $typesConfig[$typeDef->name->value] = $typeConfig;
0 ignored issues
show
Bug introduced by
Accessing name on the interface GraphQL\Language\AST\DefinitionNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
55
        }
56
57 2
        return $typesConfig;
58
    }
59
60 4
    protected function typeDefinitionToConfig(Node $typeDef)
61
    {
62 4
        switch ($typeDef->kind) {
63 4
            case NodeKind::OBJECT_TYPE_DEFINITION:
64 4
            case NodeKind::INTERFACE_TYPE_DEFINITION:
65 4
            case NodeKind::INPUT_OBJECT_TYPE_DEFINITION:
66 4
            case NodeKind::ENUM_TYPE_DEFINITION:
67 4
            case NodeKind::UNION_TYPE_DEFINITION:
68 2
                $config = [];
69 2
                $this->addTypeFields($typeDef, $config);
70 2
                $this->addDescription($typeDef, $config);
71 2
                $this->addInterfaces($typeDef, $config);
72 2
                $this->addTypes($typeDef, $config);
73 2
                $this->addValues($typeDef, $config);
74
75
                return [
76 2
                    'type' => self::DEFINITION_TYPE_MAPPING[$typeDef->kind],
77 2
                    'config' => $config,
78
                ];
79
80
            default:
81 2
                throw new InvalidArgumentException(
82 2
                    sprintf(
83 2
                        '%s definition is not supported right now.',
84 2
                        preg_replace('@Definition$@', '', $typeDef->kind)
85
                    )
86
                );
87
        }
88
    }
89
90
    /**
91
     * @param Node  $typeDef
92
     * @param array $config
93
     */
94 2
    private function addTypeFields(Node $typeDef, array &$config)
95
    {
96 2
        if (!empty($typeDef->fields)) {
97 2
            $fields = [];
98
            /** @var FieldDefinitionNode|InputValueDefinitionNode $fieldDef */
99 2
            foreach ($typeDef->fields as $fieldDef) {
0 ignored issues
show
Bug introduced by
The property fields does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
100 2
                $fieldName = $fieldDef->name->value;
101 2
                $fields[$fieldName] = [];
102 2
                $this->addType($fieldDef, $fields[$fieldName]);
103 2
                $this->addDescription($fieldDef, $fields[$fieldName]);
104 2
                $this->addDefaultValue($fieldDef, $fields[$fieldName]);
105 2
                $this->addFieldArguments($fieldDef, $fields[$fieldName]);
106
            }
107 2
            $config['fields'] = $fields;
108
        }
109 2
    }
110
111
    /**
112
     * @param Node  $fieldDef
113
     * @param array $fieldConf
114
     */
115 2
    private function addFieldArguments(Node $fieldDef, array &$fieldConf)
116
    {
117 2
        if (!empty($fieldDef->arguments)) {
118 1
            $arguments = [];
119
            /** @var InputValueDefinitionNode $definition */
120 1
            foreach ($fieldDef->arguments as $definition) {
0 ignored issues
show
Bug introduced by
The property arguments does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
121 1
                $name = $definition->name->value;
122 1
                $arguments[$name] = [];
123 1
                $this->addType($definition, $arguments[$name]);
124 1
                $this->addDescription($definition, $arguments[$name]);
125 1
                $this->addDefaultValue($definition, $arguments[$name]);
126
            }
127 1
            $fieldConf['arguments'] = $arguments;
128
        }
129 2
    }
130
131
    /**
132
     * @param Node  $typeDef
133
     * @param array $config
134
     */
135 2 View Code Duplication
    private function addInterfaces(Node $typeDef, array &$config)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
136
    {
137 2
        if (!empty($typeDef->interfaces)) {
138 2
            $interfaces = [];
139 2
            foreach ($typeDef->interfaces as $interface) {
0 ignored issues
show
Bug introduced by
The property interfaces does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
140 2
                $interfaces[] = $this->astTypeNodeToString($interface);
141
            }
142 2
            $config['interfaces'] = $interfaces;
143
        }
144 2
    }
145
146
    /**
147
     * @param Node  $typeDef
148
     * @param array $config
149
     */
150 2 View Code Duplication
    private function addTypes(Node $typeDef, array &$config)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
    {
152 2
        if (!empty($typeDef->types)) {
153 2
            $types = [];
154 2
            foreach ($typeDef->types as $type) {
0 ignored issues
show
Bug introduced by
The property types does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
155 2
                $types[] = $this->astTypeNodeToString($type);
156
            }
157 2
            $config['types'] = $types;
158
        }
159 2
    }
160
161
    /**
162
     * @param Node  $typeDef
163
     * @param array $config
164
     */
165 2 View Code Duplication
    private function addValues(Node $typeDef, array &$config)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
    {
167 2
        if (!empty($typeDef->values)) {
168 1
            $values = [];
169 1
            foreach ($typeDef->values as $value) {
0 ignored issues
show
Bug introduced by
The property values does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
170 1
                $values[] = ['value' => $value->name->value];
171
            }
172 1
            $config['values'] = $values;
173
        }
174 2
    }
175
176
    /**
177
     * @param Node  $definition
178
     * @param array $config
179
     */
180 2
    private function addType(Node $definition, array &$config)
181
    {
182 2
        if (!empty($definition->type)) {
183 2
            $config['type'] = $this->astTypeNodeToString($definition->type);
0 ignored issues
show
Bug introduced by
The property type does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
184
        }
185 2
    }
186
187
    /**
188
     * @param Node  $definition
189
     * @param array $config
190
     */
191 2
    private function addDescription(Node $definition, array &$config)
192
    {
193
        if (
194 2
            !empty($definition->description)
0 ignored issues
show
Bug introduced by
The property description does not seem to exist in GraphQL\Language\AST\Node.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
195 2
            && $description = $this->cleanAstDescription($definition->description)
196
        ) {
197 2
            $config['description'] = $description;
198
        }
199 2
    }
200
201
    /**
202
     * @param InputValueDefinitionNode|FieldDefinitionNode $definition
203
     * @param array                                        $config
204
     */
205 2
    private function addDefaultValue($definition, array &$config)
206
    {
207 2
        if (!empty($definition->defaultValue)) {
208 2
            $config['defaultValue'] = $this->astValueNodeToConfig($definition->defaultValue);
209
        }
210 2
    }
211
212 2
    private function astTypeNodeToString(TypeNode $typeNode)
213
    {
214 2
        $type = '';
215 2
        switch ($typeNode->kind) {
0 ignored issues
show
Bug introduced by
Accessing kind on the interface GraphQL\Language\AST\TypeNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
216 2
            case NodeKind::NAMED_TYPE:
217 2
                $type = $typeNode->name->value;
0 ignored issues
show
Bug introduced by
Accessing name on the interface GraphQL\Language\AST\TypeNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
218 2
                break;
219
220 2
            case NodeKind::NON_NULL_TYPE:
221 2
                $type = $this->astTypeNodeToString($typeNode->type).'!';
0 ignored issues
show
Bug introduced by
Accessing type on the interface GraphQL\Language\AST\TypeNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
222 2
                break;
223
224 1
            case NodeKind::LIST_TYPE:
225 1
                $type = '['.$this->astTypeNodeToString($typeNode->type).']';
0 ignored issues
show
Bug introduced by
Accessing type on the interface GraphQL\Language\AST\TypeNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
226 1
                break;
227
        }
228
229 2
        return $type;
230
    }
231
232 2
    private function astValueNodeToConfig(ValueNode $valueNode)
233
    {
234 2
        $config = null;
235 2
        switch ($valueNode->kind) {
0 ignored issues
show
Bug introduced by
Accessing kind on the interface GraphQL\Language\AST\ValueNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
236 2
            case NodeKind::INT:
237 1
            case NodeKind::FLOAT:
238 1
            case NodeKind::STRING:
239 1
            case NodeKind::BOOLEAN:
240 1
            case NodeKind::ENUM:
241 2
                $config = $valueNode->value;
0 ignored issues
show
Bug introduced by
Accessing value on the interface GraphQL\Language\AST\ValueNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
242 2
                break;
243
244 1
            case NodeKind::LST:
245 1
                $config = [];
246 1
                foreach ($valueNode->values as $node) {
0 ignored issues
show
Bug introduced by
Accessing values on the interface GraphQL\Language\AST\ValueNode suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
247 1
                    $config[] = $this->astValueNodeToConfig($node);
248
                }
249 1
                break;
250
251 1
            case NodeKind::NULL:
252 1
                $config = null;
253 1
                break;
254
        }
255
256 2
        return $config;
257
    }
258
259 2
    private function cleanAstDescription($description)
260
    {
261 2
        $description = trim($description);
262
263 2
        return empty($description) ? null : $description;
264
    }
265
}
266