|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
namespace GraphQLAPI\GraphQLAPI\ModuleResolvers; |
|
6
|
|
|
|
|
7
|
|
|
use GraphQLAPI\GraphQLAPI\Plugin; |
|
8
|
|
|
use GraphQLAPI\GraphQLAPI\ModuleSettings\Properties; |
|
9
|
|
|
use GraphQLAPI\GraphQLAPI\Facades\ModuleRegistryFacade; |
|
10
|
|
|
use GraphQLAPI\GraphQLAPI\ModuleResolvers\ModuleResolverTrait; |
|
11
|
|
|
use GraphQLAPI\GraphQLAPI\PostTypes\GraphQLSchemaConfigurationPostType; |
|
12
|
|
|
use PoP\AccessControl\Schema\SchemaModes; |
|
13
|
|
|
use GraphQLAPI\GraphQLAPI\ComponentConfiguration; |
|
14
|
|
|
|
|
15
|
|
|
class SchemaConfigurationFunctionalityModuleResolver extends AbstractFunctionalityModuleResolver |
|
16
|
|
|
{ |
|
17
|
|
|
use ModuleResolverTrait; |
|
18
|
|
|
|
|
19
|
|
|
public const SCHEMA_CONFIGURATION = Plugin::NAMESPACE . '\schema-configuration'; |
|
20
|
|
|
public const SCHEMA_NAMESPACING = Plugin::NAMESPACE . '\schema-namespacing'; |
|
21
|
|
|
public const PUBLIC_PRIVATE_SCHEMA = Plugin::NAMESPACE . '\public-private-schema'; |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* Setting options |
|
25
|
|
|
*/ |
|
26
|
|
|
public const OPTION_SCHEMA_CONFIGURATION_ID = 'schema-configuration-id'; |
|
27
|
|
|
public const OPTION_USE_NAMESPACING = 'use-namespacing'; |
|
28
|
|
|
public const OPTION_MODE = 'mode'; |
|
29
|
|
|
public const OPTION_ENABLE_GRANULAR = 'granular'; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Setting option values |
|
33
|
|
|
*/ |
|
34
|
|
|
public const OPTION_VALUE_NO_VALUE_ID = 0; |
|
35
|
|
|
|
|
36
|
|
|
public static function getModulesToResolve(): array |
|
37
|
|
|
{ |
|
38
|
|
|
return [ |
|
39
|
|
|
self::SCHEMA_CONFIGURATION, |
|
40
|
|
|
self::SCHEMA_NAMESPACING, |
|
41
|
|
|
self::PUBLIC_PRIVATE_SCHEMA, |
|
42
|
|
|
]; |
|
43
|
|
|
} |
|
44
|
|
|
|
|
45
|
|
|
public function getDependedModuleLists(string $module): array |
|
46
|
|
|
{ |
|
47
|
|
|
switch ($module) { |
|
48
|
|
|
case self::SCHEMA_CONFIGURATION: |
|
49
|
|
|
return [ |
|
50
|
|
|
[ |
|
51
|
|
|
EndpointFunctionalityModuleResolver::PERSISTED_QUERIES, |
|
52
|
|
|
EndpointFunctionalityModuleResolver::CUSTOM_ENDPOINTS, |
|
53
|
|
|
], |
|
54
|
|
|
]; |
|
55
|
|
|
case self::SCHEMA_NAMESPACING: |
|
56
|
|
|
return [ |
|
57
|
|
|
[ |
|
58
|
|
|
self::SCHEMA_CONFIGURATION, |
|
59
|
|
|
], |
|
60
|
|
|
]; |
|
61
|
|
|
case self::PUBLIC_PRIVATE_SCHEMA: |
|
62
|
|
|
return [ |
|
63
|
|
|
[ |
|
64
|
|
|
AccessControlFunctionalityModuleResolver::ACCESS_CONTROL, |
|
65
|
|
|
], |
|
66
|
|
|
]; |
|
67
|
|
|
} |
|
68
|
|
|
return parent::getDependedModuleLists($module); |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
public function getName(string $module): string |
|
72
|
|
|
{ |
|
73
|
|
|
$names = [ |
|
74
|
|
|
self::SCHEMA_CONFIGURATION => \__('Schema Configuration', 'graphql-api'), |
|
75
|
|
|
self::SCHEMA_NAMESPACING => \__('Schema Namespacing', 'graphql-api'), |
|
76
|
|
|
self::PUBLIC_PRIVATE_SCHEMA => \__('Public/Private Schema', 'graphql-api'), |
|
77
|
|
|
]; |
|
78
|
|
|
return $names[$module] ?? $module; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
public function getDescription(string $module): string |
|
82
|
|
|
{ |
|
83
|
|
|
switch ($module) { |
|
84
|
|
|
case self::SCHEMA_CONFIGURATION: |
|
85
|
|
|
return \__('Customize the schema accessible to different Custom Endpoints and Persisted Queries, by applying a custom configuration (involving namespacing, access control, cache control, and others) to the grand schema', 'graphql-api'); |
|
86
|
|
|
case self::SCHEMA_NAMESPACING: |
|
87
|
|
|
return \__('Automatically namespace types and interfaces with a vendor/project name, to avoid naming collisions', 'graphql-api'); |
|
88
|
|
|
case self::PUBLIC_PRIVATE_SCHEMA: |
|
89
|
|
|
return \__('Enable to communicate the existence of some field from the schema to certain users only (private mode) or to everyone (public mode). If disabled, fields are always available to everyone (public mode)', 'graphql-api'); |
|
90
|
|
|
} |
|
91
|
|
|
return parent::getDescription($module); |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
public function isEnabledByDefault(string $module): bool |
|
95
|
|
|
{ |
|
96
|
|
|
switch ($module) { |
|
97
|
|
|
case self::SCHEMA_NAMESPACING: |
|
98
|
|
|
return false; |
|
99
|
|
|
} |
|
100
|
|
|
return parent::isEnabledByDefault($module); |
|
101
|
|
|
} |
|
102
|
|
|
|
|
103
|
|
|
/** |
|
104
|
|
|
* Default value for an option set by the module |
|
105
|
|
|
* |
|
106
|
|
|
* @param string $module |
|
107
|
|
|
* @param string $option |
|
108
|
|
|
* @return mixed Anything the setting might be: an array|string|bool|int|null |
|
109
|
|
|
*/ |
|
110
|
|
|
public function getSettingsDefaultValue(string $module, string $option) |
|
111
|
|
|
{ |
|
112
|
|
|
$defaultValues = [ |
|
113
|
|
|
self::SCHEMA_CONFIGURATION => [ |
|
114
|
|
|
self::OPTION_SCHEMA_CONFIGURATION_ID => self::OPTION_VALUE_NO_VALUE_ID, |
|
115
|
|
|
], |
|
116
|
|
|
self::SCHEMA_NAMESPACING => [ |
|
117
|
|
|
self::OPTION_USE_NAMESPACING => false, |
|
118
|
|
|
], |
|
119
|
|
|
self::PUBLIC_PRIVATE_SCHEMA => [ |
|
120
|
|
|
self::OPTION_MODE => SchemaModes::PUBLIC_SCHEMA_MODE, |
|
121
|
|
|
self::OPTION_ENABLE_GRANULAR => true, |
|
122
|
|
|
], |
|
123
|
|
|
]; |
|
124
|
|
|
return $defaultValues[$module][$option]; |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
/** |
|
128
|
|
|
* Array with the inputs to show as settings for the module |
|
129
|
|
|
* |
|
130
|
|
|
* @param string $module |
|
131
|
|
|
* @return array |
|
132
|
|
|
*/ |
|
133
|
|
|
public function getSettings(string $module): array |
|
134
|
|
|
{ |
|
135
|
|
|
$moduleSettings = parent::getSettings($module); |
|
136
|
|
|
$moduleRegistry = ModuleRegistryFacade::getInstance(); |
|
137
|
|
|
// Do the if one by one, so that the SELECT do not get evaluated unless needed |
|
138
|
|
|
if ($module == self::SCHEMA_CONFIGURATION) { |
|
139
|
|
|
$whereModules = []; |
|
140
|
|
|
$maybeWhereModules = [ |
|
141
|
|
|
EndpointFunctionalityModuleResolver::CUSTOM_ENDPOINTS, |
|
142
|
|
|
EndpointFunctionalityModuleResolver::PERSISTED_QUERIES, |
|
143
|
|
|
]; |
|
144
|
|
|
foreach ($maybeWhereModules as $maybeWhereModule) { |
|
145
|
|
|
if ($moduleRegistry->isModuleEnabled($maybeWhereModule)) { |
|
146
|
|
|
$whereModules[] = '▹ ' . $this->getName($maybeWhereModule); |
|
147
|
|
|
} |
|
148
|
|
|
} |
|
149
|
|
|
// Build all the possible values by fetching all the Schema Configuration posts |
|
150
|
|
|
$possibleValues = [ |
|
151
|
|
|
self::OPTION_VALUE_NO_VALUE_ID => \__('None', 'graphql-api'), |
|
152
|
|
|
]; |
|
153
|
|
|
if ($customPosts = \get_posts([ |
|
154
|
|
|
'posts_per_page' => -1, |
|
155
|
|
|
'post_type' => GraphQLSchemaConfigurationPostType::POST_TYPE, |
|
156
|
|
|
'post_status' => 'publish', |
|
157
|
|
|
]) |
|
158
|
|
|
) { |
|
159
|
|
|
foreach ($customPosts as $customPost) { |
|
160
|
|
|
$possibleValues[$customPost->ID] = $customPost->post_title; |
|
161
|
|
|
} |
|
162
|
|
|
} |
|
163
|
|
|
$option = self::OPTION_SCHEMA_CONFIGURATION_ID; |
|
164
|
|
|
$moduleSettings[] = [ |
|
165
|
|
|
Properties::INPUT => $option, |
|
166
|
|
|
Properties::NAME => $this->getSettingOptionName( |
|
167
|
|
|
$module, |
|
168
|
|
|
$option |
|
169
|
|
|
), |
|
170
|
|
|
Properties::TITLE => \__('Default Schema Configuration', 'graphql-api'), |
|
171
|
|
|
Properties::DESCRIPTION => sprintf( |
|
172
|
|
|
\__('Schema Configuration to use when option <code>"Default"</code> is selected (in %s)', 'graphql-api'), |
|
173
|
|
|
implode( |
|
174
|
|
|
\__(', ', 'graphql-api'), |
|
175
|
|
|
$whereModules |
|
176
|
|
|
) |
|
177
|
|
|
), |
|
178
|
|
|
Properties::TYPE => Properties::TYPE_INT, |
|
179
|
|
|
// Fetch all Schema Configurations from the DB |
|
180
|
|
|
Properties::POSSIBLE_VALUES => $possibleValues, |
|
181
|
|
|
]; |
|
182
|
|
|
} elseif ($module == self::SCHEMA_NAMESPACING) { |
|
183
|
|
|
$option = self::OPTION_USE_NAMESPACING; |
|
184
|
|
|
$moduleSettings[] = [ |
|
185
|
|
|
Properties::INPUT => $option, |
|
186
|
|
|
Properties::NAME => $this->getSettingOptionName( |
|
187
|
|
|
$module, |
|
188
|
|
|
$option |
|
189
|
|
|
), |
|
190
|
|
|
Properties::TITLE => \__('Use namespacing?', 'graphql-api'), |
|
191
|
|
|
Properties::DESCRIPTION => \__('Automatically namespace types and interfaces in the schema', 'graphql-api'), |
|
192
|
|
|
Properties::TYPE => Properties::TYPE_BOOL, |
|
193
|
|
|
]; |
|
194
|
|
|
} elseif ($module == self::PUBLIC_PRIVATE_SCHEMA) { |
|
195
|
|
|
$whereModules = [ |
|
196
|
|
|
SchemaConfigurationFunctionalityModuleResolver::SCHEMA_CONFIGURATION, |
|
197
|
|
|
AccessControlFunctionalityModuleResolver::ACCESS_CONTROL, |
|
198
|
|
|
]; |
|
199
|
|
|
$whereModuleNames = array_map( |
|
200
|
|
|
function ($whereModule) use ($moduleRegistry) { |
|
201
|
|
|
return '▹ ' . $moduleRegistry->getModuleResolver($whereModule)->getName($whereModule); |
|
202
|
|
|
}, |
|
203
|
|
|
$whereModules |
|
204
|
|
|
); |
|
205
|
|
|
$option = self::OPTION_MODE; |
|
206
|
|
|
$moduleSettings[] = [ |
|
207
|
|
|
Properties::INPUT => $option, |
|
208
|
|
|
Properties::NAME => $this->getSettingOptionName( |
|
209
|
|
|
$module, |
|
210
|
|
|
$option |
|
211
|
|
|
), |
|
212
|
|
|
Properties::TITLE => \__('Default visibility', 'graphql-api'), |
|
213
|
|
|
Properties::DESCRIPTION => sprintf( |
|
214
|
|
|
\__('Visibility to use for fields and directives in the schema when option <code>"%s"</code> is selected (in %s)', 'graphql-api'), |
|
215
|
|
|
ComponentConfiguration::getSettingsValueLabel(), |
|
216
|
|
|
implode( |
|
217
|
|
|
\__(', ', 'graphql-api'), |
|
218
|
|
|
$whereModuleNames |
|
219
|
|
|
) |
|
220
|
|
|
), |
|
221
|
|
|
Properties::TYPE => Properties::TYPE_STRING, |
|
222
|
|
|
Properties::POSSIBLE_VALUES => [ |
|
223
|
|
|
SchemaModes::PUBLIC_SCHEMA_MODE => \__('Public', 'graphql-api'), |
|
224
|
|
|
SchemaModes::PRIVATE_SCHEMA_MODE => \__('Private', 'graphql-api'), |
|
225
|
|
|
], |
|
226
|
|
|
]; |
|
227
|
|
|
$option = self::OPTION_ENABLE_GRANULAR; |
|
228
|
|
|
$moduleSettings[] = [ |
|
229
|
|
|
Properties::INPUT => $option, |
|
230
|
|
|
Properties::NAME => $this->getSettingOptionName( |
|
231
|
|
|
$module, |
|
232
|
|
|
$option |
|
233
|
|
|
), |
|
234
|
|
|
Properties::TITLE => \__('Enable granular control?', 'graphql-api'), |
|
235
|
|
|
Properties::DESCRIPTION => \__('Enable to select the visibility for a set of fields/directives when editing the Access Control List', 'graphql-api'), |
|
236
|
|
|
Properties::TYPE => Properties::TYPE_BOOL, |
|
237
|
|
|
]; |
|
238
|
|
|
} |
|
239
|
|
|
return $moduleSettings; |
|
240
|
|
|
} |
|
241
|
|
|
} |
|
242
|
|
|
|