ReflectionMethodMiddleware   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Test Coverage

Coverage 98.21%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 48
c 1
b 0
f 0
dl 0
loc 122
ccs 55
cts 56
cp 0.9821
rs 10
wmc 23

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getFieldDeprecationReason() 0 16 6
A process() 0 24 4
A hasDefaultValue() 0 3 2
A __construct() 0 4 1
A getFieldType() 0 27 4
A getDefaultValue() 0 7 2
A getFieldDescription() 0 11 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Andi\GraphQL\InputObjectFieldResolver\Middleware;
6
7
use Andi\GraphQL\Attribute\InputObjectField;
8
use Andi\GraphQL\Common\InputObjectFieldNameTrait;
9
use Andi\GraphQL\Common\LazyParserType;
10
use Andi\GraphQL\Common\LazyTypeByReflectionParameter;
11
use Andi\GraphQL\Common\ReflectionMethodWithAttribute;
12
use Andi\GraphQL\Exception\CantResolveGraphQLTypeException;
13
use Andi\GraphQL\InputObjectFieldResolver\InputObjectFieldResolverInterface;
14
use Andi\GraphQL\TypeRegistryInterface;
15
use GraphQL\Type\Definition as Webonyx;
16
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
17
use phpDocumentor\Reflection\DocBlockFactory;
18
use ReflectionMethod;
19
use ReflectionParameter;
20
use Spiral\Attributes\ReaderInterface;
21
22
final class ReflectionMethodMiddleware implements MiddlewareInterface
23
{
24
    use InputObjectFieldNameTrait;
0 ignored issues
show
Bug introduced by
The trait Andi\GraphQL\Common\InputObjectFieldNameTrait requires the property $name which is not provided by Andi\GraphQL\InputObject...lectionMethodMiddleware.
Loading history...
25
26
    public const PRIORITY = 3072;
27
28 9
    public function __construct(
29
        private readonly ReaderInterface $reader,
30
        private readonly TypeRegistryInterface $typeRegistry,
31
    ) {
32 9
    }
33
34 8
    public function process(mixed $field, InputObjectFieldResolverInterface $fieldResolver): Webonyx\InputObjectField
35
    {
36 8
        if (! $field instanceof ReflectionMethodWithAttribute) {
37 1
            return $fieldResolver->resolve($field);
38
        }
39
40 7
        if (! $field->attribute instanceof InputObjectField) {
41
            return $fieldResolver->resolve($field);
42
        }
43
44 7
        $config = [
45 7
            'name' => $this->getInputObjectFieldName($field->method, $field->attribute),
46 7
            'description' => $this->getFieldDescription($field->method, $field->attribute),
47 7
            'type' => $this->getFieldType($field->method, $field->attribute),
48 7
            'deprecationReason' => $this->getFieldDeprecationReason($field->method, $field->attribute),
49 7
        ];
50
51 5
        $parameter = $field->method->getParameters()[0];
52
53 5
        if ($this->hasDefaultValue($parameter, $field->attribute)) {
54 3
            $config['defaultValue'] = $this->getDefaultValue($parameter, $field->attribute);
55
        }
56
57 5
        return new Webonyx\InputObjectField($config);
58
    }
59
60
    /**
61
     * @param ReflectionMethod $method
62
     * @param InputObjectField|null $attribute
63
     *
64
     * @return string|null
65
     */
66 7
    private function getFieldDescription(ReflectionMethod $method, ?InputObjectField $attribute): ?string
67
    {
68 7
        if ($attribute?->description) {
69 1
            return $attribute->description;
70
        }
71
72 6
        if ($docComment = $method->getDocComment()) {
73 2
            return DocBlockFactory::createInstance()->create($docComment)->getSummary() ?: null;
74
        }
75
76 4
        return null;
77
    }
78
79 7
    private function getFieldType(ReflectionMethod $method, ?InputObjectField $attribute): callable
80
    {
81 7
        if ($attribute?->type) {
82 2
            return new LazyParserType($attribute->type, $attribute->mode ?? 0, $this->typeRegistry);
83
        }
84
85 5
        $parameters = $method->getParameters();
86
87 5
        if (1 !== \count($parameters)) {
88 1
            throw new CantResolveGraphQLTypeException(\sprintf(
89 1
                'Can\'t resolve GraphQL type "%s" for field "%s". Method must have a single parameter.',
90 1
                $method->getDeclaringClass()->getName(),
91 1
                $method->getName(),
92 1
            ));
93
        }
94
95 4
        $parameter = $parameters[0];
96
97 4
        if (! $parameter->hasType()) {
98 1
            throw new CantResolveGraphQLTypeException(\sprintf(
99 1
                'Can\'t resolve GraphQL type "%s" for field "%s". Parameter has no type.',
100 1
                $method->getDeclaringClass()->getName(),
101 1
                $method->getName(),
102 1
            ));
103
        }
104
105 3
        return new LazyTypeByReflectionParameter($parameter, $this->typeRegistry);
106
    }
107
108
    /**
109
     * @param ReflectionMethod $method
110
     * @param InputObjectField|null $attribute
111
     *
112
     * @return string|null
113
     */
114 5
    private function getFieldDeprecationReason(ReflectionMethod $method, ?InputObjectField $attribute): ?string
115
    {
116 5
        if ($attribute?->deprecationReason) {
117 1
            return $attribute->deprecationReason;
118
        }
119
120 4
        if ($docComment = $method->getDocComment()) {
121 2
            $docBlock = DocBlockFactory::createInstance()->create($docComment);
122 2
            foreach ($docBlock->getTags() as $tag) {
123 2
                if ($tag instanceof Deprecated) {
124 2
                    return (string) $tag->getDescription() ?: null;
125
                }
126
            }
127
        }
128
129 2
        return null;
130
    }
131
132 5
    private function hasDefaultValue(ReflectionParameter $parameter, ?InputObjectField $attribute): bool
133
    {
134 5
        return $attribute?->hasDefaultValue() || $parameter->isDefaultValueAvailable();
135
    }
136
137 3
    private function getDefaultValue(ReflectionParameter $parameter, ?InputObjectField $attribute): mixed
138
    {
139 3
        if ($attribute?->hasDefaultValue()) {
140 1
            return $attribute->defaultValue;
141
        }
142
143 2
        return $parameter->getDefaultValue();
144
    }
145
}
146