InputFieldsConfigurationFactory   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 17
eloc 36
c 1
b 0
f 0
dl 0
loc 97
ccs 41
cts 41
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getMethodPattern() 0 3 1
A completeField() 0 14 3
A convertTypeDeclarationsToInstances() 0 3 1
A completeFieldType() 0 20 4
A methodToConfiguration() 0 18 3
A completeFieldDefaultValue() 0 10 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Doctrine\Factory;
6
7
use GraphQL\Doctrine\Attribute\Input;
8
use GraphQL\Doctrine\DocBlockReader;
9
use ReflectionMethod;
10
use ReflectionNamedType;
11
use ReflectionParameter;
12
13
/**
14
 * A factory to create a configuration for all setters of an entity.
15
 */
16
final class InputFieldsConfigurationFactory extends AbstractFieldsConfigurationFactory
17
{
18 9
    protected function getMethodPattern(): string
19
    {
20 9
        return '~^set[A-Z]~';
21
    }
22
23
    /**
24
     * Get the entire configuration for a method.
25
     */
26 9
    protected function methodToConfiguration(ReflectionMethod $method): ?array
27
    {
28
        // Silently ignore setter with anything than exactly 1 parameter
29 9
        $params = $method->getParameters();
30 9
        if (count($params) !== 1) {
31 2
            return null;
32
        }
33 9
        $param = reset($params);
34
35
        // Get a field from attribute, or an empty one
36 9
        $field = $this->reader->getAttribute($method, Input::class) ?? new Input();
37
38 9
        if (!$field->getTypeInstance()) {
0 ignored issues
show
Bug introduced by
The method getTypeInstance() does not exist on GraphQL\Doctrine\Attribute\ApiAttribute. It seems like you code against a sub-type of GraphQL\Doctrine\Attribute\ApiAttribute such as GraphQL\Doctrine\Attribute\AbstractAttribute. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

38
        if (!$field->/** @scrutinizer ignore-call */ getTypeInstance()) {
Loading history...
39 9
            $this->convertTypeDeclarationsToInstances($method, $field);
40 9
            $this->completeField($field, $method, $param);
41
        }
42
43 8
        return $field->toArray();
0 ignored issues
show
Bug introduced by
The method toArray() does not exist on GraphQL\Doctrine\Attribute\ApiAttribute. It seems like you code against a sub-type of GraphQL\Doctrine\Attribute\ApiAttribute such as GraphQL\Doctrine\Attribute\Field or GraphQL\Doctrine\Attribute\AbstractAttribute. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
        return $field->/** @scrutinizer ignore-call */ toArray();
Loading history...
44
    }
45
46
    /**
47
     * All its types will be converted from string to real instance of Type.
48
     */
49 9
    private function convertTypeDeclarationsToInstances(ReflectionMethod $method, Input $field): void
50
    {
51 9
        $field->setTypeInstance($this->getTypeFromPhpDeclaration($method->getDeclaringClass(), $field->getType()));
52
    }
53
54
    /**
55
     * Complete field with info from doc blocks and type hints.
56
     */
57 9
    private function completeField(Input $field, ReflectionMethod $method, ReflectionParameter $param): void
58
    {
59 9
        $fieldName = lcfirst(preg_replace('~^set~', '', $method->getName()) ?? '');
60 9
        if (!$field->getName()) {
61 9
            $field->setName($fieldName);
62
        }
63
64 9
        $docBlock = new DocBlockReader($method);
65 9
        if (!$field->getDescription()) {
66 9
            $field->setDescription($docBlock->getMethodDescription());
67
        }
68
69 9
        $this->completeFieldDefaultValue($field, $param, $fieldName);
70 9
        $this->completeFieldType($field, $method, $param, $docBlock);
71
    }
72
73
    /**
74
     * Complete field default value from argument and property.
75
     */
76 9
    private function completeFieldDefaultValue(Input $field, ReflectionParameter $param, string $fieldName): void
77
    {
78 9
        if (!$field->hasDefaultValue() && $param->isDefaultValueAvailable()) {
79 4
            $field->setDefaultValue($param->getDefaultValue());
80
        }
81
82 9
        if (!$field->hasDefaultValue()) {
83 9
            $defaultValue = $this->getPropertyDefaultValue($fieldName);
84 9
            if ($defaultValue !== null) {
85 4
                $field->setDefaultValue($defaultValue);
86
            }
87
        }
88
    }
89
90
    /**
91
     * Complete field type from doc blocks and type hints.
92
     */
93 9
    private function completeFieldType(Input $field, ReflectionMethod $method, ReflectionParameter $param, DocBlockReader $docBlock): void
94
    {
95
        // If still no type, look for docBlock
96 9
        if (!$field->getTypeInstance()) {
97 8
            $typeDeclaration = $docBlock->getParameterType($param);
98 8
            $this->throwIfArray($param, $typeDeclaration);
99 8
            $field->setTypeInstance($this->getTypeFromPhpDeclaration($method->getDeclaringClass(), $typeDeclaration, true));
100
        }
101
102
        // If still no type, look for type hint
103 9
        $type = $param->getType();
104 9
        if (!$field->getTypeInstance() && $type instanceof ReflectionNamedType) {
105 6
            $this->throwIfArray($param, $type->getName());
106 6
            $field->setTypeInstance($this->reflectionTypeToType($type, true));
107
        }
108
109 9
        $this->nonNullIfHasDefault($field);
110
111
        // If still no type, cannot continue
112 9
        $this->throwIfNotInputType($param, $field);
113
    }
114
}
115