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
Pull Request — master (#35)
by Jérémiah
13:35
created

FieldsConfigSolution::solveArgsBuilder()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 9.4285
cc 3
eloc 7
nc 2
nop 1
crap 3
1
<?php
2
3
/*
4
 * This file is part of the OverblogGraphQLBundle package.
5
 *
6
 * (c) Overblog <http://github.com/overblog/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Overblog\GraphQLBundle\Resolver\Config;
13
14
use GraphQL\Type\Definition\ResolveInfo;
15
use Overblog\GraphQLBundle\Definition\Argument;
16
use Overblog\GraphQLBundle\Definition\Builder\MappingInterface;
17
use Overblog\GraphQLBundle\Error\UserError;
18
use Overblog\GraphQLBundle\Relay\Connection\Output\Connection;
19
use Overblog\GraphQLBundle\Relay\Connection\Output\Edge;
20
use Overblog\GraphQLBundle\Resolver\ResolverInterface;
21
22
class FieldsConfigSolution extends AbstractConfigSolution
23
{
24
    /**
25
     * @var TypeConfigSolution
26
     */
27
    private $typeConfigSolution;
28
29
    /**
30
     * @var ResolveCallbackConfigSolution
31
     */
32
    private $resolveCallbackConfigSolution;
33
34 44
    public function __construct(
35
        TypeConfigSolution $typeConfigSolution,
36
        ResolveCallbackConfigSolution $resolveCallbackConfigSolution
37
    ) {
38 44
        $this->typeConfigSolution = $typeConfigSolution;
39 44
        $this->resolveCallbackConfigSolution = $resolveCallbackConfigSolution;
40 44
    }
41
42 39
    public function solve($values, array &$config = null)
43
    {
44
        // builder must be last
45 39
        $fieldsTreated = ['complexity', 'type', 'args', 'argsBuilder', 'deprecationReason', 'builder'];
46
47 39
        $fieldsDefaultAccess = isset($config['fieldsDefaultAccess']) ? $config['fieldsDefaultAccess'] : null;
48 39
        unset($config['fieldsDefaultAccess']);
49
50 39
        foreach ($values as $field => &$options) {
51
            //init access with fields default access if needed
52 39
            $options['access'] = isset($options['access']) ? $options['access'] : $fieldsDefaultAccess;
53
54 39
            foreach ($fieldsTreated as $fieldTreated) {
55 39
                if (isset($options[$fieldTreated])) {
56 39
                    $method = 'solve'.ucfirst($fieldTreated);
57 39
                    $options = $this->$method($options, $field, $config);
58 39
                }
59 39
            }
60 39
            $options = $this->resolveResolveAndAccessIfNeeded($options);
61 39
        }
62
63 39
        return $values;
64
    }
65
66 2
    private function solveComplexity($options, $field)
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
67
    {
68 2
        $treatedOptions = $options;
69
70 2
        $value = $treatedOptions['complexity'];
71
72
        $treatedOptions['complexity'] = function () use ($value) {
73 2
            $args = func_get_args();
74 2
            $complexity = $this->solveUsingExpressionLanguageIfNeeded(
75 2
                $value,
76
                [
77 2
                    'childrenComplexity' => $args[0],
78 2
                    'args' => new Argument($args[1]),
79
                ]
80 2
            );
81
82 2
            return (int) $complexity;
83
        };
84
85 2
        return $treatedOptions;
86
    }
87
88 29
    private function solveBuilder($options, $field)
89
    {
90 29
        $builderConfig = isset($options['builderConfig']) ? $options['builderConfig'] : [];
91
92 29
        $access = isset($options['access']) ? $options['access'] : null;
93 29
        $options = $this->builderToMappingDefinition($options['builder'], $builderConfig, $this->fieldResolver, $field);
94 29
        $options['access'] = $access;
95 29
        $options = $this->resolveResolveAndAccessIfNeeded($options);
96
97 29
        unset($options['builderConfig'], $options['builder']);
98
99 29
        return $options;
100
    }
101
102 39
    private function solveType($options)
103
    {
104 39
        $options['type'] = $this->typeConfigSolution->solveTypeCallback($options['type']);
105
106 39
        return $options;
107
    }
108
109
    private function solveArgs($options)
110
    {
111
        foreach ($options['args'] as &$argsOptions) {
112
            $argsOptions['type'] = $this->typeConfigSolution->solveTypeCallback($argsOptions['type']);
113
            if (isset($argsOptions['defaultValue'])) {
114
                $argsOptions['defaultValue'] = $this->solveUsingExpressionLanguageIfNeeded($argsOptions['defaultValue']);
115
            }
116
        }
117
118
        return $options;
119
    }
120
121 20
    private function solveArgsBuilder($options)
122
    {
123 20
        $argsBuilderConfig = isset($options['argsBuilder']['config']) ? $options['argsBuilder']['config'] : [];
124
125 20
        $options['args'] = array_merge(
126 20
            $this->builderToMappingDefinition($options['argsBuilder']['builder'], $argsBuilderConfig, $this->argResolver),
127 20
            isset($options['args']) ? $options['args'] : []
128 20
        );
129
130 20
        unset($options['argsBuilder']);
131
132 20
        return $options;
133
    }
134
135
    private function solveDeprecationReason($options)
136
    {
137
        $options['deprecationReason'] = $this->solveUsingExpressionLanguageIfNeeded($options['deprecationReason']);
138
139
        return $options;
140
    }
141
142 39
    private function builderToMappingDefinition($rawBuilder, array $rawBuilderConfig, ResolverInterface $builderResolver, $name = null)
143
    {
144
        /** @var MappingInterface $builder */
145 39
        $builder = $builderResolver->resolve($rawBuilder);
146 39
        $builderConfig = [];
147 39
        if (!empty($rawBuilderConfig)) {
148 29
            $builderConfig = $rawBuilderConfig;
149 29
            $builderConfig = $this->configResolver->resolve($builderConfig);
150 29
        }
151
152 39
        if (null !== $name) {
153 29
            $builderConfig['name'] = $name;
154 29
        }
155
156 39
        return $builder->toMappingDefinition($builderConfig);
157
    }
158
159 39
    private function resolveResolveAndAccessIfNeeded(array $options)
160
    {
161 39
        $treatedOptions = $options;
162
163 39
        if (isset($treatedOptions['resolve'])) {
164 39
            $treatedOptions['resolve'] = $this->resolveCallbackConfigSolution->solve($treatedOptions['resolve']);
165 39
        }
166
167 39
        if (isset($treatedOptions['access'])) {
168 10
            $resolveCallback = $this->configResolver->getDefaultResolveFn();
169
170 10
            if (isset($treatedOptions['resolve'])) {
171 10
                $resolveCallback = $treatedOptions['resolve'];
172 10
            }
173
174 10
            $treatedOptions['resolve'] = $this->resolveAccessAndWrapResolveCallback($treatedOptions['access'], $resolveCallback);
175 10
        }
176 39
        unset($treatedOptions['access']);
177
178 39
        return $treatedOptions;
179
    }
180
181 15
    private function resolveAccessAndWrapResolveCallback($expression, callable $resolveCallback)
182
    {
183
        return function () use ($expression, $resolveCallback) {
184 15
            $args = func_get_args();
185
186 15
            $values = call_user_func_array([$this, 'solveResolveCallbackArgs'], $args);
187
188 15
            $info = $values['info'];
189
190
            // operation is mutation and is mutation field
191 15
            if ($info instanceof ResolveInfo && $info->operation->operation === 'mutation' && $info->parentType === $info->schema->getMutationType()) {
192 3
                $checkAccess = $this->checkAccessCallback($expression, $values);
193 3
                $result = $checkAccess(null, $values) ? call_user_func_array($resolveCallback, $args) : null;
194 2
            } else {
195 14
                $result = $this->filterResultUsingAccess(call_user_func_array($resolveCallback, $args), $expression, $values);
196
            }
197
198 10
            return $result;
199 15
        };
200
    }
201
202 14
    private function filterResultUsingAccess($result, $expression, $values)
203
    {
204 14
        $checkAccess = $this->checkAccessCallback($expression, $values);
205
206 14
        switch (true) {
207 14
            case is_array($result):
208 4
                $result = array_map(
209
                    function ($object) use ($checkAccess) {
210 4
                        return $checkAccess($object) ? $object : null;
211 4
                    },
212
                    $result
213 4
                );
214 4
                break;
215
216 10
            case $result instanceof Connection:
217 2
                $result->edges = array_map(
218
                    function (Edge $edge) use ($checkAccess) {
219 2
                        $edge->node = $checkAccess($edge->node) ? $edge->node : null;
220
221 2
                        return $edge;
222 2
                    },
223 2
                    $result->edges
224 2
                );
225 2
                break;
226
227 9
            default:
228 9
                $checkAccess($result, true);
229 4
                break;
230 9
        }
231
232 9
        return $result;
233
    }
234
235
    private function checkAccessCallback($expression, $values)
236
    {
237 15
        return function ($object, $throwException = false) use ($expression, $values) {
238
            try {
239 15
                $access = $this->solveUsingExpressionLanguageIfNeeded(
240 15
                    $expression,
241 15
                    array_merge($values, ['object' => $object])
242 15
                );
243 15
            } catch (\Exception $e) {
244 2
                $access = false;
245
            }
246
247 15
            if ($throwException && !$access) {
248 6
                throw new UserError('Access denied to this field.');
249
            }
250
251 10
            return $access;
252 15
        };
253
    }
254
}
255