Completed
Pull Request — master (#3)
by
unknown
02:55
created

DefaultFieldResolver::getGetter()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

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