/
Directive.php
182 lines (153 loc) · 5.65 KB
/
Directive.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<?php
declare(strict_types=1);
namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\DirectiveDefinitionNode;
use GraphQL\Language\DirectiveLocation;
use function array_key_exists;
use function is_array;
class Directive
{
public const DEFAULT_DEPRECATION_REASON = 'No longer supported';
public const INCLUDE_NAME = 'include';
public const IF_ARGUMENT_NAME = 'if';
public const SKIP_NAME = 'skip';
public const DEPRECATED_NAME = 'deprecated';
public const REASON_ARGUMENT_NAME = 'reason';
/** @var Directive[]|null */
public static $internalDirectives;
// Schema Definitions
/** @var string */
public $name;
/** @var string|null */
public $description;
/** @var FieldArgument[] */
public $args = [];
/** @var bool */
public $isRepeatable;
/** @var string[] */
public $locations;
/** @var DirectiveDefinitionNode|null */
public $astNode;
/** @var mixed[] */
public $config;
/**
* @param mixed[] $config
*/
public function __construct(array $config)
{
if (! isset($config['name'])) {
throw new InvariantViolation('Directive must be named.');
}
$this->name = $config['name'];
$this->description = $config['description'] ?? null;
if (isset($config['args'])) {
$args = [];
foreach ($config['args'] as $name => $arg) {
if (is_array($arg)) {
$args[] = new FieldArgument($arg + ['name' => $name]);
} else {
$args[] = $arg;
}
}
$this->args = $args;
}
if (! isset($config['locations']) || ! is_array($config['locations'])) {
throw new InvariantViolation('Must provide locations for directive.');
}
$this->locations = $config['locations'];
$this->isRepeatable = $config['isRepeatable'] ?? false;
$this->astNode = $config['astNode'] ?? null;
$this->config = $config;
}
/**
* @return Directive
*/
public static function includeDirective()
{
$internal = self::getInternalDirectives();
return $internal['include'];
}
/**
* @return Directive[]
*/
public static function getInternalDirectives() : array
{
if (self::$internalDirectives === null) {
self::$internalDirectives = [
'include' => new self([
'name' => self::INCLUDE_NAME,
'description' => 'Directs the executor to include this field or fragment only when the `if` argument is true.',
'locations' => [
DirectiveLocation::FIELD,
DirectiveLocation::FRAGMENT_SPREAD,
DirectiveLocation::INLINE_FRAGMENT,
],
'args' => [new FieldArgument([
'name' => self::IF_ARGUMENT_NAME,
'type' => Type::nonNull(Type::boolean()),
'description' => 'Included when true.',
]),
],
]),
'skip' => new self([
'name' => self::SKIP_NAME,
'description' => 'Directs the executor to skip this field or fragment when the `if` argument is true.',
'locations' => [
DirectiveLocation::FIELD,
DirectiveLocation::FRAGMENT_SPREAD,
DirectiveLocation::INLINE_FRAGMENT,
],
'args' => [new FieldArgument([
'name' => self::IF_ARGUMENT_NAME,
'type' => Type::nonNull(Type::boolean()),
'description' => 'Skipped when true.',
]),
],
]),
'deprecated' => new self([
'name' => self::DEPRECATED_NAME,
'description' => 'Marks an element of a GraphQL schema as no longer supported.',
'locations' => [
DirectiveLocation::FIELD_DEFINITION,
DirectiveLocation::ENUM_VALUE,
],
'args' => [new FieldArgument([
'name' => self::REASON_ARGUMENT_NAME,
'type' => Type::string(),
'description' =>
'Explains why this element was deprecated, usually also including a ' .
'suggestion for how to access supported similar data. Formatted ' .
'in [Markdown](https://daringfireball.net/projects/markdown/).',
'defaultValue' => self::DEFAULT_DEPRECATION_REASON,
]),
],
]),
];
}
return self::$internalDirectives;
}
/**
* @return Directive
*/
public static function skipDirective()
{
$internal = self::getInternalDirectives();
return $internal['skip'];
}
/**
* @return Directive
*/
public static function deprecatedDirective()
{
$internal = self::getInternalDirectives();
return $internal['deprecated'];
}
/**
* @return bool
*/
public static function isSpecifiedDirective(Directive $directive)
{
return array_key_exists($directive->name, self::getInternalDirectives());
}
}