Issues (169)

AbstractFieldByReflectionMethodMiddleware.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Andi\GraphQL\ObjectFieldResolver\Middleware;
6
7
use Andi\GraphQL\ArgumentResolver\ArgumentResolverInterface;
8
use Andi\GraphQL\Attribute\AbstractField;
9
use Andi\GraphQL\Attribute\Argument;
10
use Andi\GraphQL\Common\LazyParserType;
11
use Andi\GraphQL\Common\LazyTypeByReflectionType;
12
use Andi\GraphQL\Common\ReflectionMethodWithAttribute;
13
use Andi\GraphQL\Exception\CantResolveGraphQLTypeException;
14
use Andi\GraphQL\ObjectFieldResolver\ObjectFieldResolverInterface;
15
use Andi\GraphQL\TypeRegistryInterface;
16
use GraphQL\Type\Definition as Webonyx;
17
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
18
use phpDocumentor\Reflection\DocBlockFactory;
19
use Spiral\Attributes\ReaderInterface;
20
21
/**
22
 * @see Webonyx\FieldDefinition
23
 *
24
 * @phpstan-import-type FieldDefinitionConfig from Webonyx\FieldDefinition
25
 */
26
abstract class AbstractFieldByReflectionMethodMiddleware implements MiddlewareInterface
27
{
28
    /**
29
     * @var class-string<AbstractField>
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<AbstractField> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<AbstractField>.
Loading history...
30
     */
31
    protected string $targetAttribute;
32
33 14
    public function __construct(
34
        private readonly ReaderInterface $reader,
35
        private readonly TypeRegistryInterface $typeRegistry,
36
        private readonly ArgumentResolverInterface $argumentResolver,
37
    ) {
38 14
    }
39
40 12
    public function process(mixed $field, ObjectFieldResolverInterface $fieldResolver): Webonyx\FieldDefinition
41
    {
42 12
        if (! $field instanceof ReflectionMethodWithAttribute) {
43 2
            return $fieldResolver->resolve($field);
44
        }
45
46 10
        if (! $field->attribute instanceof $this->targetAttribute) {
47 2
            return $fieldResolver->resolve($field);
48
        }
49
50 8
        $config = [
51 8
            'name' => $this->getFieldName($field->method, $field->attribute),
52 8
            'description' => $this->getFieldDescription($field->method, $field->attribute),
53 8
            'type' => $this->getFieldType($field->method, $field->attribute),
54 8
            'deprecationReason' => $this->getFieldDeprecationReason($field->method, $field->attribute),
55 8
        ];
56
57 6
        return $this->buildField($config, $field->method);
58
    }
59
60 8
    private function getFieldName(\ReflectionMethod $method, AbstractField $attribute): ?string
61
    {
62 8
        if ($attribute->name) {
63 2
            return $attribute->name;
64
        }
65
66 6
        $name = $method->getName();
67
68 6
        if (\str_starts_with($name, 'get')) {
69 2
            $name = \substr($name, 3);
70
        }
71
72 6
        return \lcfirst($name);
73
    }
74
75 8
    private function getFieldDescription(\ReflectionMethod $method, AbstractField $attribute): ?string
76
    {
77 8
        if ($attribute->description) {
78 2
            return $attribute->description;
79
        }
80
81 6
        if ($docComment = $method->getDocComment()) {
82 2
            return DocBlockFactory::createInstance()->create($docComment)->getSummary() ?: null;
83
        }
84
85 4
        return null;
86
87
    }
88
89 8
    private function getFieldType(\ReflectionMethod $method, AbstractField $attribute): callable
90
    {
91 8
        if ($attribute->type) {
92 2
            return new LazyParserType($attribute->type, $attribute->mode ?? 0, $this->typeRegistry);
93
        }
94
95 6
        if (! $method->hasReturnType()) {
96 2
            throw new CantResolveGraphQLTypeException(\sprintf(
97 2
                'Can\'t resolve GraphQL type for field "%s"',
98 2
                $method->getName()
99 2
            ));
100
        }
101
102 4
        return new LazyTypeByReflectionType(
103 4
            $method->getReturnType(),
104 4
            $this->typeRegistry,
105 4
            $method->getDeclaringClass()->getName(),
106 4
        );
107
    }
108
109 6
    protected function getFieldArguments(\ReflectionMethod $method): \Generator
110
    {
111 6
        $map = [];
112 6
        foreach ($method->getParameters() as $parameter) {
113 2
            if (null !== $this->reader->firstParameterMetadata($parameter, Argument::class)) {
114 2
                $argument = $this->argumentResolver->resolve($parameter);
115 2
                $map[$argument['name']] = $parameter->getName();
116
117 2
                yield $argument;
118
            }
119
        }
120
121 6
        return $map;
122
    }
123
124
    /**
125
     * @param FieldDefinitionConfig $config
0 ignored issues
show
The type Andi\GraphQL\ObjectField...e\FieldDefinitionConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
126
     * @param \ReflectionMethod $method
127
     *
128
     * @return Webonyx\FieldDefinition
129
     */
130
    abstract protected function buildField(array $config, \ReflectionMethod $method): Webonyx\FieldDefinition;
131
132 6
    private function getFieldDeprecationReason(\ReflectionMethod $method, AbstractField $attribute): ?string
133
    {
134 6
        if ($attribute->deprecationReason) {
135 2
            return $attribute->deprecationReason;
136
        }
137
138 4
        if ($docComment = $method->getDocComment()) {
139 2
            $docBlock = DocBlockFactory::createInstance()->create($docComment);
140 2
            foreach ($docBlock->getTags() as $tag) {
141 2
                if ($tag instanceof Deprecated) {
142 2
                    return (string) $tag->getDescription() ?: null;
143
                }
144
            }
145
        }
146
147 2
        return null;
148
    }
149
}
150