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

Passed
Pull Request — 0.11 (#403)
by Jérémiah
20:22
created

AccessResolver::resolve()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 10
cts 10
cp 1
rs 8.9777
c 0
b 0
f 0
cc 6
nc 8
nop 4
crap 6
1
<?php
2
3
namespace Overblog\GraphQLBundle\Resolver;
4
5
use GraphQL\Executor\Promise\Adapter\SyncPromise;
6
use GraphQL\Executor\Promise\Promise;
7
use GraphQL\Executor\Promise\PromiseAdapter;
8
use GraphQL\Type\Definition\ListOfType;
9
use GraphQL\Type\Definition\ResolveInfo;
10
use Overblog\GraphQLBundle\Error\UserError;
11
use Overblog\GraphQLBundle\Error\UserWarning;
12
use Overblog\GraphQLBundle\Relay\Connection\Output\Connection;
13
use Overblog\GraphQLBundle\Relay\Connection\Output\Edge;
14
15
class AccessResolver
16
{
17
    /** @var PromiseAdapter */
18
    private $promiseAdapter;
19
20 94
    public function __construct(PromiseAdapter $promiseAdapter)
21
    {
22 94
        $this->promiseAdapter = $promiseAdapter;
23 94
    }
24
25 12
    public function resolve(callable $accessChecker, callable $resolveCallback, array $resolveArgs = [], $useStrictAccess = false)
26
    {
27
        /** @var ResolveInfo $info */
28 12
        $info = $resolveArgs[3];
29
        // operation is mutation and is mutation field
30 12
        $isMutation = 'mutation' === $info->operation->operation && $info->parentType === $info->schema->getMutationType();
31
32 12
        if ($isMutation || $useStrictAccess) {
33 11
            if (!$this->hasAccess($accessChecker, null, $resolveArgs)) {
34 5
                $exceptionClassName = $isMutation ? UserError::class : UserWarning::class;
35 5
                throw new $exceptionClassName('Access denied to this field.');
36
            }
37
38 6
            $result = \call_user_func_array($resolveCallback, $resolveArgs);
39
        } else {
40 4
            $result = $this->filterResultUsingAccess($accessChecker, $resolveCallback, $resolveArgs);
41
        }
42
43 7
        return $result;
44
    }
45
46 4
    private function filterResultUsingAccess(callable $accessChecker, callable $resolveCallback, array $resolveArgs = [])
47
    {
48 4
        $result = \call_user_func_array($resolveCallback, $resolveArgs);
49 4
        if ($result instanceof Promise) {
50 1
            $result = $result->adoptedPromise;
51
        }
52
53 4
        if ($this->promiseAdapter->isThenable($result) || $result instanceof SyncPromise) {
54 1
            return $this->promiseAdapter->then(
55 1
                new Promise($result, $this->promiseAdapter),
56
                function ($result) use ($accessChecker, $resolveArgs) {
57 1
                    return $this->processFilter($result, $accessChecker, $resolveArgs);
58 1
                }
59
            );
60
        }
61
62 3
        return $this->processFilter($result, $accessChecker, $resolveArgs);
63
    }
64
65 4
    private function processFilter($result, $accessChecker, $resolveArgs)
66
    {
67
        /** @var ResolveInfo $resolveInfo */
68 4
        $resolveInfo = $resolveArgs[3];
69
70 4
        if (self::isIterable($result) && $resolveInfo->returnType instanceof ListOfType) {
71 1
            foreach ($result as $i => $object) {
72 1
                $result[$i] = $this->hasAccess($accessChecker, $object, $resolveArgs) ? $object : null;
73
            }
74 3
        } elseif ($result instanceof Connection) {
75 1
            $result->edges = \array_map(
76
                function (Edge $edge) use ($accessChecker, $resolveArgs) {
77 1
                    $edge->node = $this->hasAccess($accessChecker, $edge->node, $resolveArgs) ? $edge->node : null;
78
79 1
                    return $edge;
80 1
                },
81 1
                $result->edges
82
            );
83 2
        } elseif (!$this->hasAccess($accessChecker, $result, $resolveArgs)) {
84 1
            throw new UserWarning('Access denied to this field.');
85
        }
86
87 3
        return $result;
88
    }
89
90 12
    private function hasAccess(callable $accessChecker, $object, array $resolveArgs = [])
91
    {
92 12
        $resolveArgs[] = $object;
93 12
        $access = (bool) \call_user_func_array($accessChecker, $resolveArgs);
94
95 12
        return $access;
96
    }
97
98
    /**
99
     * @param mixed $data
100
     *
101
     * @return bool
102
     */
103 4
    private static function isIterable($data)
104
    {
105 4
        if (\function_exists('is_iterable')) {
106 4
            return \is_iterable($data);
107
        } else {
108
            return \is_array($data) || (\is_object($data) && ($data instanceof \Traversable));
109
        }
110
    }
111
}
112