Completed
Push — master ( 4bb4eb...402013 )
by Arthur
03:35
created

YamlDriver::createType()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
c 5
b 1
f 1
dl 0
loc 20
rs 8.8571
cc 5
eloc 12
nc 4
nop 2
1
<?php
2
namespace Arthem\GraphQLMapper\Mapping\Driver;
3
4
use Arthem\GraphQLMapper\Mapping\AbstractType;
5
use Arthem\GraphQLMapper\Mapping\Field;
6
use Arthem\GraphQLMapper\Mapping\FieldContainer;
7
use Arthem\GraphQLMapper\Mapping\InterfaceType;
8
use Arthem\GraphQLMapper\Mapping\Query;
9
use Arthem\GraphQLMapper\Mapping\SchemaContainer;
10
use Arthem\GraphQLMapper\Mapping\Type;
11
use Symfony\Component\Yaml\Yaml;
12
13
class YamlDriver extends FileDriver
14
{
15
    /**
16
     * {@inheritdoc}
17
     */
18
    public function load(SchemaContainer $schema)
19
    {
20
        $paths = $this->getPaths();
21
22
        foreach ($paths as $path) {
23
            $this->loadFile($path, $schema);
24
        }
25
    }
26
27
    /**
28
     * @param string          $path
29
     * @param SchemaContainer $schemaContainer
30
     */
31
    private function loadFile($path, SchemaContainer $schemaContainer)
32
    {
33
        $config = Yaml::parse($this->getFileContent($path));
34
35
        foreach ($config as $type => $mapping) {
0 ignored issues
show
Bug introduced by
The expression $config of type array|string|object<stdClass> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
36
            switch ($type) {
37
                case 'query':
38
                    $this->mapQuery($schemaContainer, $mapping);
39
                    break;
40
                case 'mutation':
41
                    $this->mapMutation($schemaContainer, $mapping);
42
                    break;
43
                case 'types':
44
                    $this->mapTypes($schemaContainer, $mapping);
45
                    break;
46
                case 'interfaces':
47
                    $this->mapInterfaces($schemaContainer, $mapping);
48
                    break;
49
                default:
50
                    throw new \UnexpectedValueException(sprintf('Unsupported key "%s"', $type));
51
            }
52
        }
53
    }
54
55
    /**
56
     * @param SchemaContainer $schemaContainer
57
     * @param array           $mapping
58
     */
59 View Code Duplication
    private function mapQuery(SchemaContainer $schemaContainer, array $mapping)
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...
60
    {
61
        $querySchema = $schemaContainer->getQuerySchema();
62
        if (null === $querySchema) {
63
            $querySchema = new Query();
64
            $schemaContainer->setQuerySchema($querySchema);
65
        }
66
67
        $this->populateFieldContainer($querySchema, $mapping);
68
    }
69
70
    /**
71
     * @param SchemaContainer $schemaContainer
72
     * @param array           $mapping
73
     */
74 View Code Duplication
    private function mapMutation(SchemaContainer $schemaContainer, array $mapping)
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...
75
    {
76
        $mutationSchema = $schemaContainer->getMutationSchema();
77
        if (null === $mutationSchema) {
78
            $mutationSchema = new Query();
79
            $schemaContainer->setMutationSchema($mutationSchema);
80
        }
81
82
        $this->populateFieldContainer($mutationSchema, $mapping);
83
    }
84
85
    /**
86
     * @param SchemaContainer $schemaContainer
87
     * @param array           $mapping
88
     */
89
    private function mapTypes(SchemaContainer $schemaContainer, array $mapping)
90
    {
91
        foreach ($mapping as $name => $typeMapping) {
92
            $type = $this->createType($name, $typeMapping);
93
            $schemaContainer->addType($type);
94
        }
95
    }
96
97
    /**
98
     * @param SchemaContainer $schemaContainer
99
     * @param array           $mapping
100
     */
101
    private function mapInterfaces(SchemaContainer $schemaContainer, array $mapping)
102
    {
103
        foreach ($mapping as $name => $interfaceMapping) {
104
            $interface = $this->createInterface($name, $interfaceMapping);
105
            $schemaContainer->addInterface($interface);
106
        }
107
    }
108
109
    /**
110
     * @param string $name
111
     * @param array  $mapping
112
     * @return Type
113
     */
114
    private function createType($name, array $mapping)
115
    {
116
        $type = new Type();
117
        $type
118
            ->setName($name)
119
            ->setExtends(isset($mapping['extends']) ? $mapping['extends'] : null)
120
            ->setResolveConfig(isset($mapping['resolve']) ? $mapping['resolve'] : []);
121
122
        if (isset($mapping['values'])) {
123
            $type->setValues($mapping['values']);
124
        }
125
126
        if (isset($mapping['model'])) {
127
            $type->setModel($mapping['model']);
128
        }
129
130
        $this->populateFieldContainer($type, $mapping);
131
132
        return $type;
133
    }
134
135
    /**
136
     * @param AbstractType $type
137
     * @param array        $mapping
138
     */
139
    private function populateType(AbstractType $type, array $mapping)
140
    {
141
        if (isset($mapping['description'])) {
142
            $type->setDescription($mapping['description']);
143
        }
144
    }
145
146
    /**
147
     * @param FieldContainer $type
148
     * @param array          $mapping
149
     */
150
    private function populateFieldContainer(FieldContainer $type, array $mapping)
151
    {
152
        $this->populateType($type, $mapping);
153
154
        if (!isset($mapping['fields'])) {
155
            return;
156
        }
157
158
        $fields = [];
159
        foreach ($mapping['fields'] as $name => $fieldMapping) {
160
            $fields[] = $this->createField($name, $fieldMapping);
161
        }
162
        $type->setFields($fields);
163
    }
164
165
    /**
166
     * @param string $name
167
     * @param array  $mapping
168
     * @return InterfaceType
169
     */
170
    private function createInterface($name, array $mapping)
171
    {
172
        $interface = new InterfaceType();
173
        $interface->setName($name);
174
        $this->populateFieldContainer($interface, $mapping);
175
176
        return $interface;
177
    }
178
179
    /**
180
     * @param string $name
181
     * @param array  $mapping
182
     * @return Field
183
     */
184
    private function createField($name, array $mapping)
185
    {
186
        $field = new Field();
187
        $field
188
            ->setName($name)
189
            ->setType(isset($mapping['type']) ? $mapping['type'] : null)
190
            ->setProperty(isset($mapping['property']) ? $mapping['property'] : null)
191
            ->setResolveConfig(isset($mapping['resolve']) ? $mapping['resolve'] : []);
192
193
        $this->populateType($field, $mapping);
194
195
        if (isset($mapping['args'])) {
196
            $args = [];
197
            foreach ($mapping['args'] as $argName => $argMapping) {
198
                $args[] = $this->createField($argName, $argMapping);
199
            }
200
            $field->setArguments($args);
201
        }
202
203
        return $field;
204
    }
205
}
206