Completed
Push — master ( 8edae9...5d7827 )
by Adrien
01:53
created

DefaultFieldResolver::orderArguments()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
ccs 11
cts 11
cp 1
cc 5
eloc 10
nc 5
nop 2
crap 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Doctrine;
6
7
use ArrayAccess;
8
use Closure;
9
use GraphQL\Doctrine\Definition\EntityID;
10
use GraphQL\Type\Definition\ResolveInfo;
11
use ReflectionClass;
12
use ReflectionMethod;
13
14
/**
15
 * A field resolver that will allow access to public properties and getter.
16
 * Arguments, if any, will be forwarded as is to the method.
17
 */
18
class DefaultFieldResolver
19
{
20 14
    public function __invoke($source, $args, $context, ResolveInfo $info)
21
    {
22 14
        $fieldName = $info->fieldName;
23 14
        $property = null;
24
25 14
        if (is_object($source)) {
26 13
            $property = $this->resolveObject($source, $args, $fieldName);
27 1
        } elseif (is_array($source) || $source instanceof ArrayAccess) {
28 1
            $property = $this->resolveArray($source, $fieldName);
29
        }
30
31 14
        return $property instanceof Closure ? $property($source, $args, $context) : $property;
32
    }
33
34
    /**
35
     * Resolve for an object
36
     *
37
     * @param mixed $source
38
     * @param mixed $args
39
     * @param string $fieldName
40
     *
41
     * @return mixed
42
     */
43 13
    private function resolveObject($source, ?array $args, string $fieldName)
44
    {
45 13
        $getter = $this->getGetter($source, $fieldName);
46 13
        if ($getter) {
47 6
            $args = $this->orderArguments($getter, $args);
48
49 6
            return $getter->invoke($source, ...$args);
50
        }
51
52 7
        if (isset($source->{$fieldName})) {
53 1
            return $source->{$fieldName};
54
        }
55
56 6
        return null;
57
    }
58
59
    /**
60
     * Resolve for an array
61
     *
62
     * @param mixed $source
63
     * @param string $fieldName
64
     *
65
     * @return mixed
66
     */
67 1
    private function resolveArray($source, string $fieldName)
68
    {
69 1
        return $source[$fieldName] ?? null;
70
    }
71
72
    /**
73
     * Return the getter/isser method if any valid one exists
74
     *
75
     * @param mixed $source
76
     * @param string $name
77
     *
78
     * @return null|ReflectionMethod
79
     */
80 13
    private function getGetter($source, string $name): ?ReflectionMethod
81
    {
82 13
        if (!preg_match('~^(is|has)[A-Z]~', $name)) {
83 11
            $name = 'get' . ucfirst($name);
84
        }
85
86 13
        $class = new ReflectionClass($source);
87 13
        if ($class->hasMethod($name)) {
88 8
            $method = $class->getMethod($name);
89 8
            if ($method->getModifiers() & ReflectionMethod::IS_PUBLIC) {
90 6
                return $method;
91
            }
92
        }
93
94 7
        return null;
95
    }
96
97
    /**
98
     * Re-order associative args to ordered args
99
     *
100
     * @param ReflectionMethod $method
101
     * @param array $args
102
     *
103
     * @return array
104
     */
105 6
    private function orderArguments(ReflectionMethod $method, ?array $args): array
106
    {
107 6
        $result = [];
108 6
        if (!$args) {
109 4
            return $result;
110
        }
111
112 2
        foreach ($method->getParameters() as $param) {
113 2
            if (array_key_exists($param->getName(), $args)) {
114 2
                $arg = $args[$param->getName()];
115
116
                // Fetch entity from DB
117 2
                if ($arg instanceof EntityID) {
118 1
                    $arg = $arg->getEntity();
119
                }
120
121 2
                $result[] = $arg;
122
            }
123
        }
124
125 2
        return $result;
126
    }
127
}
128