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->getTypeInstance()) { |
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->setTypeInstance($this->getTypeFromPhpDeclaration($method, $field->getType())); |
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->getName()) { |
74
|
5 |
|
$field->setName($fieldName); |
75
|
|
|
} |
76
|
|
|
|
77
|
5 |
|
$docBlock = new DocBlockReader($method); |
78
|
5 |
|
if (!$field->getDescription()) { |
79
|
5 |
|
$field->setDescription($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 (!$field->hasDefaultValue() && $param->isDefaultValueAvailable()) { |
96
|
4 |
|
$field->setDefaultValue($param->getDefaultValue()); |
97
|
|
|
} |
98
|
|
|
|
99
|
5 |
|
if (!$field->hasDefaultValue()) { |
100
|
5 |
|
$defaultValue = $this->getPropertyDefaultValue($fieldName); |
101
|
5 |
|
if ($defaultValue !== null) { |
102
|
4 |
|
$field->setDefaultValue($defaultValue); |
103
|
|
|
} |
104
|
|
|
} |
105
|
5 |
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Complete field type from doc blocks and type hints |
109
|
|
|
* |
110
|
|
|
* @param Input $field |
111
|
|
|
* @param ReflectionMethod $method |
112
|
|
|
* @param ReflectionParameter $param |
113
|
|
|
* @param DocBlockReader $docBlock |
114
|
|
|
* |
115
|
|
|
* @throws \GraphQL\Doctrine\Exception |
116
|
|
|
*/ |
117
|
5 |
|
private function completeFieldType(Input $field, ReflectionMethod $method, ReflectionParameter $param, DocBlockReader $docBlock): void |
118
|
|
|
{ |
119
|
|
|
// If still no type, look for docblock |
120
|
5 |
|
if (!$field->getTypeInstance()) { |
121
|
5 |
|
$typeDeclaration = $docBlock->getParameterType($param); |
122
|
5 |
|
$this->throwIfArray($param, $typeDeclaration); |
123
|
5 |
|
$field->setTypeInstance($this->getTypeFromPhpDeclaration($method, $typeDeclaration, true)); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
// If still no type, look for type hint |
127
|
5 |
|
$type = $param->getType(); |
128
|
5 |
|
if (!$field->getTypeInstance() && $type) { |
|
|
|
|
129
|
4 |
|
$this->throwIfArray($param, (string) $type); |
130
|
4 |
|
$field->setTypeInstance($this->reflectionTypeToType($type, true)); |
131
|
|
|
} |
132
|
|
|
|
133
|
5 |
|
$this->nonNullIfHasDefault($field); |
134
|
|
|
|
135
|
|
|
// If still no type, cannot continue |
136
|
5 |
|
$this->throwIfNotInputType($param, $field); |
137
|
4 |
|
} |
138
|
|
|
} |
139
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.