DefaultFieldResolver::getGetter()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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