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 — 0.13 ( ff6287...cab464 )
by Jérémiah
16s queued 11s
created

ArgumentsTransformer::populateObject()   B

Complexity

Conditions 11
Paths 21

Size

Total Lines 53
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 11.0069

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 33
dl 0
loc 53
ccs 25
cts 26
cp 0.9615
rs 7.3166
c 1
b 1
f 0
cc 11
nc 21
nop 4
crap 11.0069

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\Transformer;
6
7
use GraphQL\Type\Definition\EnumType;
8
use GraphQL\Type\Definition\InputObjectType;
9
use GraphQL\Type\Definition\ListOfType;
10
use GraphQL\Type\Definition\NonNull;
11
use GraphQL\Type\Definition\ResolveInfo;
12
use GraphQL\Type\Definition\Type;
13
use Overblog\GraphQLBundle\Error\InvalidArgumentError;
14
use Overblog\GraphQLBundle\Error\InvalidArgumentsError;
15
use Symfony\Component\PropertyAccess\PropertyAccess;
16
use Symfony\Component\PropertyAccess\PropertyAccessor;
17
use Symfony\Component\Validator\ConstraintViolationList;
18
use Symfony\Component\Validator\Validator\ValidatorInterface;
19
20
class ArgumentsTransformer
21
{
22
    /**
23
     * @var ValidatorInterface
24
     */
25
    protected $validator;
26
27
    /**
28
     * @var array
29
     */
30
    protected $classesMap;
31
32
    /**
33
     * @var PropertyAccessor
34
     */
35
    protected $accessor;
36 2
37
    public function __construct(ValidatorInterface $validator = null, $classesMap = [])
38 2
    {
39 2
        $this->validator = $validator;
40 2
        $this->accessor = PropertyAccess::createPropertyAccessor();
41 2
        $this->classesMap = $classesMap;
42
    }
43
44
    /**
45
     * Get the PHP class for a given type.
46
     *
47
     * @param string $type
48
     *
49
     * @return object|false
50 2
     */
51
    private function getTypeClassInstance(string $type)
52 2
    {
53
        $classname = isset($this->classesMap[$type]) ? $this->classesMap[$type]['class'] : false;
54 2
55
        return $classname ? new $classname() : false;
56
    }
57
58
    /**
59
     * Extract given type from Resolve Info.
60
     *
61
     * @param string      $type
62
     * @param ResolveInfo $info
63
     *
64
     * @return Type
65 2
     */
66
    private function getType(string $type, ResolveInfo $info): Type
67 2
    {
68
        return $info->schema->getType($type);
69
    }
70
71
    /**
72
     * Populate an object based on type with given data.
73
     *
74
     * @param Type        $type
75
     * @param mixed       $data
76
     * @param bool        $multiple
77
     * @param ResolveInfo $info
78
     *
79
     * @return mixed
80 2
     */
81
    private function populateObject(Type $type, $data, bool $multiple, ResolveInfo $info)
82 2
    {
83 2
        if (null === $data) {
84
            return $data;
85
        }
86 2
87 1
        if ($type instanceof NonNull) {
88
            $type = $type->getWrappedType();
89
        }
90 2
91
        if ($multiple) {
92 2
            return \array_map(function ($data) use ($type, $info) {
93 2
                return $this->populateObject($type, $data, false, $info);
94
            }, $data);
95
        }
96 2
97 2
        if ($type instanceof EnumType) {
98 2
            $instance = $this->getTypeClassInstance($type->name);
99 1
            if ($instance) {
100
                $this->accessor->setValue($instance, 'value', $data);
101 1
102
                return $instance;
103 2
            } else {
104
                return $data;
105 2
            }
106 2
        } elseif ($type instanceof InputObjectType) {
107 2
            $instance = $this->getTypeClassInstance($type->name);
108
            if (!$instance) {
109
                return $data;
110
            }
111 2
112
            $fields = $type->getFields();
113 2
114 2
            foreach ($fields as $name => $field) {
115
                $fieldData = $this->accessor->getValue($data, \sprintf('[%s]', $name));
116 2
                $fieldType = $field->getType();
117 2
118
                if ($fieldType instanceof NonNull) {
119 2
                    $fieldType = $fieldType->getWrappedType();
120
                }
121
122 2
                if ($fieldType instanceof ListOfType) {
123
                    $fieldValue = $this->populateObject($fieldType->getWrappedType(), $fieldData, true, $info);
124
                } else {
125 2
                    $fieldValue = $this->populateObject($fieldType, $fieldData, false, $info);
126
                }
127 2
128
                $this->accessor->setValue($instance, $name, $fieldValue);
129
            }
130
131
            return $instance;
132
        } else {
133
            return $data;
134
        }
135
    }
136
137
    /**
138
     * Given a GraphQL type and an array of data, populate corresponding object recursively
139
     * using annoted classes.
140
     *
141 2
     * @param string      $argType
142
     * @param mixed       $data
143 2
     * @param ResolveInfo $info
144 2
     *
145 2
     * @return mixed
146 2
     */
147
    public function getInstanceAndValidate(string $argType, $data, ResolveInfo $info, string $argName)
148 2
    {
149 2
        $isRequired = '!' === $argType[\strlen($argType) - 1];
150 2
        $isMultiple = '[' === $argType[0];
151 2
        $endIndex = ($isRequired ? 1 : 0) + ($isMultiple ? 1 : 0);
152
        $type = \substr($argType, $isMultiple ? 1 : 0, $endIndex > 0 ? -$endIndex : \strlen($argType));
153
154 2
        $result = $this->populateObject($this->getType($type, $info), $data, $isMultiple, $info);
155 1
        $errors = new ConstraintViolationList();
156
        if ($this->validator) {
157 1
            if (\is_object($result)) {
158
                $errors = $this->validator->validate($result);
159
            }
160
            if (\is_array($result) && $isMultiple) {
161
                foreach ($result as $element) {
162
                    if (\is_object($element)) {
163
                        $errors->addAll(
164
                            $this->validator->validate($element)
165
                        );
166
                    }
167
                }
168
            }
169
        }
170 2
171
        if (\count($errors) > 0) {
172 2
            throw new InvalidArgumentError($argName, $errors);
173 2
        } else {
174
            return $result;
175 2
        }
176
    }
177 2
178 1
    /**
179 1
     * Transform a list of arguments into their corresponding php class and validate them.
180 1
     *
181
     * @param array       $mapping
182
     * @param mixed       $data
183
     * @param ResolveInfo $info
184 2
     *
185 1
     * @return array
186
     */
187
    public function getArguments(array $mapping, $data, ResolveInfo $info)
188 1
    {
189
        $args = [];
190
        $exceptions = [];
191
192
        foreach ($mapping as $name => $type) {
193
            try {
194
                $value = $this->getInstanceAndValidate($type, $data[$name], $info, $name);
195
                $args[] = $value;
196
            } catch (InvalidArgumentError $exception) {
197
                $exceptions[] = $exception;
198
            }
199
        }
200
201
        if (!empty($exceptions)) {
202
            throw new InvalidArgumentsError($exceptions);
203
        }
204
205
        return $args;
206
    }
207
}
208