1
|
|
<?php
|
2
|
|
|
3
|
|
namespace Nuwave\Lighthouse\Validation;
|
4
|
|
|
5
|
|
use GraphQL\Language\AST\FieldDefinitionNode;
|
6
|
|
use GraphQL\Language\AST\InputValueDefinitionNode;
|
7
|
|
use GraphQL\Language\AST\ObjectTypeDefinitionNode;
|
8
|
|
use Nuwave\Lighthouse\Exceptions\DefinitionException;
|
9
|
|
use Nuwave\Lighthouse\Schema\AST\DocumentAST;
|
10
|
|
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
|
11
|
|
use Nuwave\Lighthouse\Support\Contracts\ArgManipulator;
|
12
|
|
use Nuwave\Lighthouse\Support\Contracts\ArgumentValidation;
|
13
|
|
|
14
|
|
abstract class BaseRulesDirective extends BaseDirective implements ArgumentValidation, ArgManipulator
|
15
|
|
{
|
16
|
1
|
public function rules(): array
|
17
|
|
{
|
18
|
1
|
$rules = $this->directiveArgValue('apply');
|
19
|
|
|
20
|
|
// Custom rules may be referenced through their fully qualified class name.
|
21
|
|
// The Laravel validator expects a class instance to be passed, so we
|
22
|
|
// resolve any given rule where a corresponding class exists.
|
23
|
1
|
foreach ($rules as $key => $rule) {
|
24
|
1
|
if (class_exists($rule)) {
|
25
|
1
|
$rules[$key] = app($rule);
|
26
|
|
}
|
27
|
|
}
|
28
|
|
|
29
|
1
|
return $rules;
|
30
|
|
}
|
31
|
|
|
32
|
1
|
public function messages(): array
|
33
|
|
{
|
34
|
1
|
$messages = $this->directiveArgValue('messages');
|
35
|
1
|
if ($messages === null) {
|
36
|
1
|
return [];
|
37
|
|
}
|
38
|
|
|
39
|
1
|
if (isset($messages[0])) {
|
40
|
|
/** @var array<string, string> $flattened */
|
41
|
1
|
$flattened = [];
|
42
|
|
|
43
|
|
/**
|
44
|
|
* We know this holds true, because it has been validated before.
|
45
|
|
*
|
46
|
|
* @var array{rule: string, message: string} $messageMap
|
47
|
|
*/
|
48
|
1
|
foreach ($messages as $messageMap) {
|
49
|
1
|
$flattened[$messageMap['rule']] = $messageMap['message'];
|
50
|
|
}
|
51
|
|
|
52
|
1
|
return $flattened;
|
53
|
|
}
|
54
|
|
|
55
|
1
|
return $messages;
|
56
|
|
}
|
57
|
|
|
58
|
1
|
public function attribute(): ?string
|
59
|
|
{
|
60
|
1
|
return $this->directiveArgValue('attribute');
|
61
|
|
}
|
62
|
|
|
63
|
1
|
public function manipulateArgDefinition(
|
64
|
|
DocumentAST &$documentAST,
|
65
|
|
InputValueDefinitionNode &$argDefinition,
|
66
|
|
FieldDefinitionNode &$parentField,
|
67
|
|
ObjectTypeDefinitionNode &$parentType
|
68
|
|
) {
|
69
|
1
|
$this->validateRulesArg();
|
70
|
1
|
$this->validateMessageArg();
|
71
|
|
}
|
72
|
|
|
73
|
1
|
protected function validateRulesArg(): void
|
74
|
|
{
|
75
|
1
|
$rules = $this->directiveArgValue('apply');
|
76
|
|
|
77
|
1
|
if (! is_array($rules)) {
|
78
|
1
|
$this->invalidApplyArgument($rules);
|
79
|
|
}
|
80
|
|
|
81
|
1
|
if (count($rules) === 0) {
|
82
|
1
|
$this->invalidApplyArgument($rules);
|
83
|
|
}
|
84
|
|
|
85
|
1
|
foreach ($rules as $rule) {
|
86
|
1
|
if (! is_string($rule)) {
|
87
|
1
|
$this->invalidApplyArgument($rules);
|
88
|
|
}
|
89
|
|
}
|
90
|
|
}
|
91
|
|
|
92
|
1
|
protected function validateMessageArg(): void
|
93
|
|
{
|
94
|
1
|
$messages = $this->directiveArgValue('messages');
|
95
|
1
|
if ($messages === null) {
|
96
|
1
|
return;
|
97
|
|
}
|
98
|
|
|
99
|
1
|
if (! is_array($messages)) {
|
100
|
1
|
$this->invalidMessageArgument($messages);
|
101
|
|
}
|
102
|
|
|
103
|
1
|
if (isset($messages[0])) {
|
104
|
1
|
foreach ($messages as $messageMap) {
|
105
|
1
|
if (! is_array($messageMap)) {
|
106
|
1
|
$this->invalidMessageArgument($messages);
|
107
|
|
}
|
108
|
|
|
109
|
1
|
$rule = $messageMap['rule'] ?? null;
|
110
|
1
|
if (! is_string($rule)) {
|
111
|
1
|
$this->invalidMessageArgument($messages);
|
112
|
|
}
|
113
|
|
|
114
|
1
|
$message = $messageMap['message'] ?? null;
|
115
|
1
|
if (! is_string($message)) {
|
116
|
1
|
$this->invalidMessageArgument($messages);
|
117
|
|
}
|
118
|
|
}
|
119
|
|
} else {
|
120
|
1
|
foreach ($messages as $rule => $message) {
|
121
|
1
|
if (! is_string($rule)) {
|
122
|
0
|
$this->invalidMessageArgument($messages);
|
123
|
|
}
|
124
|
|
|
125
|
1
|
if (! is_string($message)) {
|
126
|
1
|
$this->invalidMessageArgument($messages);
|
127
|
|
}
|
128
|
|
}
|
129
|
|
}
|
130
|
|
}
|
131
|
|
|
132
|
|
/**
|
133
|
|
* @param mixed $messages Whatever faulty value was given for messages
|
134
|
|
* @throws DefinitionException
|
135
|
|
*/
|
136
|
1
|
protected function invalidMessageArgument($messages): void
|
137
|
|
{
|
138
|
1
|
$encoded = \Safe\json_encode($messages);
|
139
|
1
|
throw new DefinitionException(
|
140
|
1
|
"The `messages` argument of @`{$this->name()}` on `{$this->nodeName()} must be a list of input values with the string keys `rule` and `message`, got: {$encoded}"
|
141
|
|
);
|
142
|
|
}
|
143
|
|
|
144
|
|
/**
|
145
|
|
* @param mixed $apply Any invalid value
|
146
|
|
*
|
147
|
|
* @throws \Nuwave\Lighthouse\Exceptions\DefinitionException
|
148
|
|
*/
|
149
|
1
|
protected function invalidApplyArgument($apply): void
|
150
|
|
{
|
151
|
1
|
$encoded = \Safe\json_encode($apply);
|
152
|
1
|
throw new DefinitionException(
|
153
|
1
|
"The `apply` argument of @`{$this->name()}` on `{$this->nodeName()}` has to be a list of strings, got: {$encoded}"
|
154
|
|
);
|
155
|
|
}
|
156
|
|
}
|