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

Test Setup Failed
Pull Request — 0.9 (#389)
by Jérémiah
23:29
created

AccessResolver   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 5
dl 0
loc 95
ccs 42
cts 42
cp 1
rs 10
c 0
b 0
f 0

6 Methods

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