Completed
Push — master ( 5d7827...c80c5c )
by Adrien
01:49
created

InputFieldsConfigurationFactory::completeField()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 4
nop 3
crap 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Doctrine\Factory;
6
7
use GraphQL\Doctrine\Annotation\Input;
8
use GraphQL\Doctrine\DocBlockReader;
9
use GraphQL\Type\Definition\Type;
10
use ReflectionMethod;
11
use ReflectionParameter;
12
13
/**
14
 * A factory to create a configuration for all setters of an entity
15
 */
16
class InputFieldsConfigurationFactory extends AbstractFieldsConfigurationFactory
17
{
18 5
    protected function getMethodPattern(): string
19
    {
20 5
        return '~^set[A-Z]~';
21
    }
22
23
    /**
24
     * Get the entire configuration for a method
25
     *
26
     * @param ReflectionMethod $method
27
     *
28
     * @return null|array
29
     */
30 5
    protected function methodToConfiguration(ReflectionMethod $method): ?array
31
    {
32
        // Silently ignore setter with anything than exactly 1 parameter
33 5
        $params = $method->getParameters();
34 5
        if (count($params) !== 1) {
35 2
            return null;
36
        }
37 5
        $param = reset($params);
38
39
        // Get a field from annotation, or an empty one
40 5
        $field = $this->getAnnotationReader()->getMethodAnnotation($method, Input::class) ?? new Input();
41
42 5
        if (!$field->type instanceof Type) {
0 ignored issues
show
introduced by
$field->type is never a sub-type of GraphQL\Type\Definition\Type.
Loading history...
43 5
            $this->convertTypeDeclarationsToInstances($method, $field);
44 5
            $this->completeField($field, $method, $param);
45
        }
46
47 4
        return $field->toArray();
48
    }
49
50
    /**
51
     * All its types will be converted from string to real instance of Type
52
     *
53
     * @param ReflectionMethod $method
54
     * @param Input $field
55
     */
56 5
    private function convertTypeDeclarationsToInstances(ReflectionMethod $method, Input $field): void
57
    {
58 5
        $field->type = $this->getTypeFromPhpDeclaration($method, $field->type);
59 5
    }
60
61
    /**
62
     * Complete field with info from doc blocks and type hints
63
     *
64
     * @param Input $field
65
     * @param ReflectionMethod $method
66
     * @param ReflectionParameter $param
67
     *
68
     * @throws \GraphQL\Doctrine\Exception
69
     */
70 5
    private function completeField(Input $field, ReflectionMethod $method, ReflectionParameter $param): void
71
    {
72 5
        $fieldName = lcfirst(preg_replace('~^set~', '', $method->getName()));
73 5
        if (!$field->name) {
74 5
            $field->name = $fieldName;
75
        }
76
77 5
        $docBlock = new DocBlockReader($method);
78 5
        if (!$field->description) {
79 5
            $field->description = $docBlock->getMethodDescription();
80
        }
81
82 5
        $this->completeFieldDefaultValue($field, $param, $fieldName);
83 5
        $this->completeFieldType($field, $method, $param, $docBlock);
84 4
    }
85
86
    /**
87
     * Complete field default value from argument and property
88
     *
89
     * @param Input $field
90
     * @param ReflectionParameter $param
91
     * @param string $fieldName
92
     */
93 5
    private function completeFieldDefaultValue(Input $field, ReflectionParameter $param, string $fieldName): void
94
    {
95 5
        if (!isset($field->defaultValue) && $param->isDefaultValueAvailable()) {
96 4
            $field->defaultValue = $param->getDefaultValue();
97
        }
98
99 5
        if (!isset($field->defaultValue)) {
100 5
            $field->defaultValue = $this->getPropertyDefaultValue($fieldName);
101
        }
102 5
    }
103
104
    /**
105
     * Complete field type  from doc blocks and type hints
106
     *
107
     * @param Input $field
108
     * @param ReflectionMethod $method
109
     * @param ReflectionParameter $param
110
     * @param DocBlockReader $docBlock
111
     *
112
     * @throws \GraphQL\Doctrine\Exception
113
     */
114 5
    private function completeFieldType(Input $field, ReflectionMethod $method, ReflectionParameter $param, DocBlockReader $docBlock): void
115
    {
116
        // If still no type, look for docblock
117 5
        if (!$field->type) {
118 5
            $typeDeclaration = $docBlock->getParameterType($param);
119 5
            $this->throwIfArray($param, $typeDeclaration);
120 5
            $field->type = $this->getTypeFromPhpDeclaration($method, $typeDeclaration, true);
121
        }
122
123
        // If still no type, look for type hint
124 5
        $type = $param->getType();
125 5
        if (!$field->type && $type) {
126 4
            $this->throwIfArray($param, (string) $type);
127 4
            $field->type = $this->reflectionTypeToType($type, true);
128
        }
129
130 5
        $field->type = $this->nonNullIfHasDefault($field->type, $field->defaultValue);
131
132
        // If still no type, cannot continue
133 5
        $this->throwIfNotInputType($param, $field->type, 'Input');
134 4
    }
135
}
136