Failed Conditions
Pull Request — master (#12)
by Tom
02:34 queued 11s
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 Doctrine\Common\Util\Inflector;
10
use GraphQL\Doctrine\Definition\EntityID;
11
use GraphQL\Type\Definition\ResolveInfo;
12
use ReflectionClass;
13
use ReflectionMethod;
14
15
/**
16
 * A field resolver that will allow access to public properties and getter.
17
 * Arguments, if any, will be forwarded as is to the method.
18
 */
19
final class DefaultFieldResolver
20
{
21 14
    public function __invoke($source, $args, $context, ResolveInfo $info)
22
    {
23 14
        $fieldName = $info->fieldName;
24 14
        $property = null;
25
26 14
        if (is_object($source)) {
27 13
            $property = $this->resolveObject($source, $args, $fieldName);
28 1
        } elseif (is_array($source) || $source instanceof ArrayAccess) {
29 1
            $property = $this->resolveArray($source, $fieldName);
30
        }
31
32 14
        return $property instanceof Closure ? $property($source, $args, $context) : $property;
33
    }
34
35
    /**
36
     * Resolve for an object
37
     *
38
     * @param mixed $source
39
     * @param mixed $args
40
     * @param string $fieldName
41
     *
42
     * @return mixed
43
     */
44 13
    private function resolveObject($source, ?array $args, string $fieldName)
45
    {
46 13
        $getter = $this->getGetter($source, $fieldName);
47 13
        if ($getter) {
48 6
            $args = $this->orderArguments($getter, $args);
49
50 6
            return $getter->invoke($source, ...$args);
51
        }
52
53 7
        return $source->{$fieldName} ?? null;
54
    }
55
56
    /**
57
     * Resolve for an array
58
     *
59
     * @param mixed $source
60
     * @param string $fieldName
61
     *
62
     * @return mixed
63
     */
64 1
    private function resolveArray($source, string $fieldName)
65
    {
66 1
        return $source[$fieldName] ?? null;
67
    }
68
69
    /**
70
     * Return the getter/isser method if any valid one exists
71
     *
72
     * @param mixed $source
73
     * @param string $name
74
     *
75
     * @return null|ReflectionMethod
76
     */
77 13
    private function getGetter($source, string $fieldName): ?ReflectionMethod
78
    {
79 13
        $methodName = null;
80
        // Note get_class_methods will only return public methods in this scope
81 13
        $methods = get_class_methods($source);
82 13
        $class = new ReflectionClass($source);
83
84 13
        if (!preg_match('~^(is|has)[A-Z]~', $fieldName)) {
85 11
            $getter = 'get' . Inflector::classify($fieldName);
86 11
            $isser = 'is' . Inflector::classify($fieldName);
87
        } else {
88 2
            $getter = $isser = $fieldName;
89
        }
90
91 13
        if (in_array($getter, $methods, true)) {
92 6
            $methodName = $getter;
93 7
        } elseif (in_array($isser, $methods, true)) {
94
            $methodName = $isser;
95 7
        } elseif (mb_substr($fieldName, 0, 2) === 'is'
96 7
            && ctype_upper(mb_substr($fieldName, 2, 1))
97 7
            && in_array($fieldName, $methods, true)
98
        ) {
99
            $methodName = $fieldName;
100
        }
101
102 13
        return $methodName && $class->hasMethod($methodName)
103 6
            ? $class->getMethod($methodName)
104 13
            : null;
105
    }
106
107
    /**
108
     * Re-order associative args to ordered args
109
     *
110
     * @param ReflectionMethod $method
111
     * @param array $args
112
     *
113
     * @return array
114
     */
115 6
    private function orderArguments(ReflectionMethod $method, ?array $args): array
116
    {
117 6
        $result = [];
118 6
        if (!$args) {
119 4
            return $result;
120
        }
121
122 2
        foreach ($method->getParameters() as $param) {
123 2
            if (array_key_exists($param->getName(), $args)) {
124 2
                $arg = $args[$param->getName()];
125
126
                // Fetch entity from DB
127 2
                if ($arg instanceof EntityID) {
128 1
                    $arg = $arg->getEntity();
129
                }
130
131 2
                $result[] = $arg;
132
            }
133
        }
134
135 2
        return $result;
136
    }
137
}
138