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

FieldsConfigSolution::builderToMappingDefinition()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 11
cts 11
cp 1
rs 9.4285
cc 3
eloc 9
nc 4
nop 4
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 Overblog\GraphQLBundle\Definition\Argument;
15
use Overblog\GraphQLBundle\Definition\Builder\MappingInterface;
16
use Overblog\GraphQLBundle\Error\UserError;
17
use Overblog\GraphQLBundle\Relay\Connection\Output\Connection;
18
use Overblog\GraphQLBundle\Relay\Connection\Output\Edge;
19
use Overblog\GraphQLBundle\Resolver\ResolverInterface;
20
21
class FieldsConfigSolution extends AbstractConfigSolution
22
{
23
    /**
24
     * @var TypeConfigSolution
25
     */
26
    private $typeConfigSolution;
27
28
    /**
29
     * @var ResolveCallbackConfigSolution
30
     */
31
    private $resolveCallbackConfigSolution;
32
33 32
    public function __construct(
34
        TypeConfigSolution $typeConfigSolution,
35
        ResolveCallbackConfigSolution $resolveCallbackConfigSolution
36
    ) {
37 32
        $this->typeConfigSolution = $typeConfigSolution;
38 32
        $this->resolveCallbackConfigSolution = $resolveCallbackConfigSolution;
39 32
    }
40
41 27
    public function solve($values, array &$config = null)
42
    {
43
        // builder must be last
44 27
        $fieldsTreated = ['complexity', 'type', 'args', 'argsBuilder', 'deprecationReason', 'builder'];
45
46 27
        $fieldsDefaultAccess = isset($config['fieldsDefaultAccess']) ? $config['fieldsDefaultAccess'] : null;
47 27
        unset($config['fieldsDefaultAccess']);
48
49 27
        foreach ($values as $field => &$options) {
50
            //init access with fields default access if needed
51 27
            $options['access'] = isset($options['access']) ? $options['access'] : $fieldsDefaultAccess;
52
53 27
            foreach ($fieldsTreated as $fieldTreated) {
54 27
                if (isset($options[$fieldTreated])) {
55 27
                    $method = 'solve'.ucfirst($fieldTreated);
56 27
                    $options = $this->$method($options, $field, $config);
57 27
                }
58 27
            }
59 27
            $options = $this->resolveResolveAndAccessIfNeeded($options);
60 27
        }
61
62 27
        return $values;
63
    }
64
65
    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...
66
    {
67
        $treatedOptions = $options;
68
69
        $value = $treatedOptions['complexity'];
70
71
        $treatedOptions['complexity'] = function () use ($value) {
72
            $args = func_get_args();
73
            $complexity = $this->solveUsingExpressionLanguageIfNeeded(
74
                $value,
75
                [
76
                    'childrenComplexity' => $args[0],
77
                    'args' => new Argument($args[1]),
78
                ]
79
            );
80
81
            return (int) $complexity;
82
        };
83
84
        return $treatedOptions;
85
    }
86
87 19
    private function solveBuilder($options, $field)
88
    {
89 19
        $builderConfig = isset($options['builderConfig']) ? $options['builderConfig'] : [];
90
91 19
        $access = isset($options['access']) ? $options['access'] : null;
92 19
        $options = $this->builderToMappingDefinition($options['builder'], $builderConfig, $this->fieldResolver, $field);
93 19
        $options['access'] = $access;
94 19
        $options = $this->resolveResolveAndAccessIfNeeded($options);
95
96 19
        unset($options['builderConfig'], $options['builder']);
97
98 19
        return $options;
99
    }
100
101 27
    private function solveType($options)
102
    {
103 27
        $options['type'] = $this->typeConfigSolution->solveTypeCallback($options['type']);
104
105 27
        return $options;
106
    }
107
108
    private function solveArgs($options)
109
    {
110
        foreach ($options['args'] as &$argsOptions) {
111
            $argsOptions['type'] = $this->typeConfigSolution->solveTypeCallback($argsOptions['type']);
112
            if (isset($argsOptions['defaultValue'])) {
113
                $argsOptions['defaultValue'] = $this->solveUsingExpressionLanguageIfNeeded($argsOptions['defaultValue']);
114
            }
115
        }
116
117
        return $options;
118
    }
119
120 8
    private function solveArgsBuilder($options)
121
    {
122 8
        $argsBuilderConfig = isset($options['argsBuilder']['config']) ? $options['argsBuilder']['config'] : [];
123
124 8
        $options['args'] = array_merge(
125 8
            $this->builderToMappingDefinition($options['argsBuilder']['builder'], $argsBuilderConfig, $this->argResolver),
126 8
            isset($options['args']) ? $options['args'] : []
127 8
        );
128
129 8
        unset($options['argsBuilder']);
130
131 8
        return $options;
132
    }
133
134
    private function solveDeprecationReason($options)
135
    {
136
        $options['deprecationReason'] = $this->solveUsingExpressionLanguageIfNeeded($options['deprecationReason']);
137
138
        return $options;
139
    }
140
141 27
    private function builderToMappingDefinition($rawBuilder, array $rawBuilderConfig, ResolverInterface $builderResolver, $name = null)
142
    {
143
        /** @var MappingInterface $builder */
144 27
        $builder = $builderResolver->resolve($rawBuilder);
145 27
        $builderConfig = [];
146 27
        if (!empty($rawBuilderConfig)) {
147 19
            $builderConfig = $rawBuilderConfig;
148 19
            $builderConfig = $this->configResolver->resolve($builderConfig);
149 19
        }
150
151 27
        if (null !== $name) {
152 19
            $builderConfig['name'] = $name;
153 19
        }
154
155 27
        return $builder->toMappingDefinition($builderConfig);
156
    }
157
158 27
    private function resolveResolveAndAccessIfNeeded(array $options)
159
    {
160 27
        $treatedOptions = $options;
161
162 27
        if (isset($treatedOptions['resolve'])) {
163 27
            $treatedOptions['resolve'] = $this->resolveCallbackConfigSolution->solve($treatedOptions['resolve']);
164 27
        }
165
166 27
        if (isset($treatedOptions['access'])) {
167
            $resolveCallback = $this->configResolver->getDefaultResolveFn();
168
169
            if (isset($treatedOptions['resolve'])) {
170
                $resolveCallback = $treatedOptions['resolve'];
171
            }
172
173
            $treatedOptions['resolve'] = $this->resolveAccessAndWrapResolveCallback($treatedOptions['access'], $resolveCallback);
174
        }
175 27
        unset($treatedOptions['access']);
176
177 27
        return $treatedOptions;
178
    }
179
180 5
    private function resolveAccessAndWrapResolveCallback($expression, callable $resolveCallback = null)
181
    {
182
        return function () use ($expression, $resolveCallback) {
183 5
            $args = func_get_args();
184
185 5
            $result = null !== $resolveCallback  ? call_user_func_array($resolveCallback, $args) : null;
186
187 5
            $values = call_user_func_array([$this, 'solveResolveCallbackArgs'], $args);
188
189 5
            return $this->filterResultUsingAccess($result, $expression, $values);
190 5
        };
191
    }
192
193 5
    private function filterResultUsingAccess($result, $expression, $values)
194
    {
195 5
        $checkAccess = $this->checkAccessCallback($expression, $values);
196
197 5
        switch (true) {
198 5
            case is_array($result):
199 1
                $result = array_map(
200
                    function ($object) use ($checkAccess) {
201 1
                        return $checkAccess($object) ? $object : null;
202 1
                    },
203
                    $result
204 1
                );
205 1
                break;
206
207 4
            case $result instanceof Connection:
208 1
                $result->edges = array_map(
209
                    function (Edge $edge) use ($checkAccess) {
210 1
                        $edge->node = $checkAccess($edge->node) ? $edge->node : null;
211
212 1
                        return $edge;
213 1
                    },
214 1
                    $result->edges
215 1
                );
216 1
                break;
217
218 3
            default:
219 3
                $checkAccess($result, true);
220 1
                break;
221 3
        }
222
223 3
        return $result;
224
    }
225
226
    private function checkAccessCallback($expression, $values)
227
    {
228 5
        return function ($object, $throwException = false) use ($expression, $values) {
229
            try {
230 5
                $access = $this->solveUsingExpressionLanguageIfNeeded(
231 5
                    $expression,
232 5
                    array_merge($values, ['object' => $object])
233 5
                );
234 5
            } catch (\Exception $e) {
235 1
                $access = false;
236
            }
237
238 5
            if ($throwException && !$access) {
239 2
                throw new UserError('Access denied to this field.');
240
            }
241
242 3
            return $access;
243 5
        };
244
    }
245
}
246