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 (#33)
by Jérémiah
13:33
created

resolveAccessAndWrapResolveCallback()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.3244

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 19
ccs 8
cts 11
cp 0.7272
rs 9.2
cc 4
eloc 11
nc 1
nop 2
crap 4.3244
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 41
    public function __construct(
35
        TypeConfigSolution $typeConfigSolution,
36
        ResolveCallbackConfigSolution $resolveCallbackConfigSolution
37
    ) {
38 41
        $this->typeConfigSolution = $typeConfigSolution;
39 41
        $this->resolveCallbackConfigSolution = $resolveCallbackConfigSolution;
40 41
    }
41
42 36
    public function solve($values, array &$config = null)
43
    {
44
        // builder must be last
45 36
        $fieldsTreated = ['complexity', 'type', 'args', 'argsBuilder', 'deprecationReason', 'builder'];
46
47 36
        $fieldsDefaultAccess = isset($config['fieldsDefaultAccess']) ? $config['fieldsDefaultAccess'] : null;
48 36
        unset($config['fieldsDefaultAccess']);
49
50 36
        foreach ($values as $field => &$options) {
51
            //init access with fields default access if needed
52 36
            $options['access'] = isset($options['access']) ? $options['access'] : $fieldsDefaultAccess;
53
54 36
            foreach ($fieldsTreated as $fieldTreated) {
55 36
                if (isset($options[$fieldTreated])) {
56 36
                    $method = 'solve'.ucfirst($fieldTreated);
57 36
                    $options = $this->$method($options, $field, $config);
58 36
                }
59 36
            }
60 36
            $options = $this->resolveResolveAndAccessIfNeeded($options);
61 36
        }
62
63 36
        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 19
    private function solveBuilder($options, $field)
89
    {
90 19
        $builderConfig = isset($options['builderConfig']) ? $options['builderConfig'] : [];
91
92 19
        $access = isset($options['access']) ? $options['access'] : null;
93 19
        $options = $this->builderToMappingDefinition($options['builder'], $builderConfig, $this->fieldResolver, $field);
94 19
        $options['access'] = $access;
95 19
        $options = $this->resolveResolveAndAccessIfNeeded($options);
96
97 19
        unset($options['builderConfig'], $options['builder']);
98
99 19
        return $options;
100
    }
101
102 36
    private function solveType($options)
103
    {
104 36
        $options['type'] = $this->typeConfigSolution->solveTypeCallback($options['type']);
105
106 36
        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 17
    private function solveArgsBuilder($options)
122
    {
123 17
        $argsBuilderConfig = isset($options['argsBuilder']['config']) ? $options['argsBuilder']['config'] : [];
124
125 17
        $options['args'] = array_merge(
126 17
            $this->builderToMappingDefinition($options['argsBuilder']['builder'], $argsBuilderConfig, $this->argResolver),
127 17
            isset($options['args']) ? $options['args'] : []
128 17
        );
129
130 17
        unset($options['argsBuilder']);
131
132 17
        return $options;
133
    }
134
135
    private function solveDeprecationReason($options)
136
    {
137
        $options['deprecationReason'] = $this->solveUsingExpressionLanguageIfNeeded($options['deprecationReason']);
138
139
        return $options;
140
    }
141
142 36
    private function builderToMappingDefinition($rawBuilder, array $rawBuilderConfig, ResolverInterface $builderResolver, $name = null)
143
    {
144
        /** @var MappingInterface $builder */
145 36
        $builder = $builderResolver->resolve($rawBuilder);
146 36
        $builderConfig = [];
147 36
        if (!empty($rawBuilderConfig)) {
148 19
            $builderConfig = $rawBuilderConfig;
149 19
            $builderConfig = $this->configResolver->resolve($builderConfig);
150 19
        }
151
152 36
        if (null !== $name) {
153 19
            $builderConfig['name'] = $name;
154 19
        }
155
156 36
        return $builder->toMappingDefinition($builderConfig);
157
    }
158
159 36
    private function resolveResolveAndAccessIfNeeded(array $options)
160
    {
161 36
        $treatedOptions = $options;
162
163 36
        if (isset($treatedOptions['resolve'])) {
164 36
            $treatedOptions['resolve'] = $this->resolveCallbackConfigSolution->solve($treatedOptions['resolve']);
165 36
        }
166
167 36
        if (isset($treatedOptions['access'])) {
168 7
            $resolveCallback = $this->configResolver->getDefaultResolveFn();
169
170 7
            if (isset($treatedOptions['resolve'])) {
171 7
                $resolveCallback = $treatedOptions['resolve'];
172 7
            }
173
174 7
            $treatedOptions['resolve'] = $this->resolveAccessAndWrapResolveCallback($treatedOptions['access'], $resolveCallback);
175 7
        }
176 36
        unset($treatedOptions['access']);
177
178 36
        return $treatedOptions;
179
    }
180
181 12
    private function resolveAccessAndWrapResolveCallback($expression, callable $resolveCallback)
182
    {
183
        return function () use ($expression, $resolveCallback) {
184 12
            $args = func_get_args();
185
186 12
            $values = call_user_func_array([$this, 'solveResolveCallbackArgs'], $args);
187
188 12
            $info = $values['info'];
189
190 12
            if ($info instanceof ResolveInfo && $info->operation->operation === 'mutation') {
191
                $checkAccess = $this->checkAccessCallback($expression, $values);
192
                $result = $checkAccess(null, $values) ? call_user_func_array($resolveCallback, $args) : null;
193
            } else {
194 12
                $result = $this->filterResultUsingAccess(call_user_func_array($resolveCallback, $args), $expression, $values);
195
            }
196
197 8
            return $result;
198 12
        };
199
    }
200
201 12
    private function filterResultUsingAccess($result, $expression, $values)
202
    {
203 12
        $checkAccess = $this->checkAccessCallback($expression, $values);
204
205 12
        switch (true) {
206 12
            case is_array($result):
207 4
                $result = array_map(
208
                    function ($object) use ($checkAccess) {
209 4
                        return $checkAccess($object) ? $object : null;
210 4
                    },
211
                    $result
212 4
                );
213 4
                break;
214
215 8
            case $result instanceof Connection:
216 2
                $result->edges = array_map(
217
                    function (Edge $edge) use ($checkAccess) {
218 2
                        $edge->node = $checkAccess($edge->node) ? $edge->node : null;
219
220 2
                        return $edge;
221 2
                    },
222 2
                    $result->edges
223 2
                );
224 2
                break;
225
226 7
            default:
227 7
                $checkAccess($result, true);
228 3
                break;
229 7
        }
230
231 8
        return $result;
232
    }
233
234
    private function checkAccessCallback($expression, $values)
235
    {
236 12
        return function ($object, $throwException = false) use ($expression, $values) {
237
            try {
238 12
                $access = $this->solveUsingExpressionLanguageIfNeeded(
239 12
                    $expression,
240 12
                    array_merge($values, ['object' => $object])
241 12
                );
242 12
            } catch (\Exception $e) {
243 2
                $access = false;
244
            }
245
246 12
            if ($throwException && !$access) {
247 4
                throw new UserError('Access denied to this field.');
248
            }
249
250 8
            return $access;
251 12
        };
252
    }
253
}
254