GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 573a46...de67c0 )
by Leonardo
03:28
created

getComponentClassConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 2
b 0
f 0
nc 1
nop 0
dl 0
loc 6
ccs 0
cts 6
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLAPI\GraphQLAPI;
6
7
use PoP\APIEndpoints\EndpointUtils;
8
use GraphQLAPI\GraphQLAPI\Environment;
9
use PoP\AccessControl\Schema\SchemaModes;
10
use PoP\ComponentModel\Misc\GeneralUtils;
11
use GraphQLAPI\GraphQLAPI\ComponentConfiguration;
12
use PoPSchema\Tags\Environment as TagsEnvironment;
13
use PoPSchema\Pages\Environment as PagesEnvironment;
14
use PoPSchema\Posts\Environment as PostsEnvironment;
15
use PoPSchema\Users\Environment as UsersEnvironment;
16
use GraphQLAPI\GraphQLAPI\Facades\ModuleRegistryFacade;
17
use GraphQLAPI\GraphQLAPI\Admin\MenuPages\SettingsMenuPage;
18
use GraphQLAPI\GraphQLAPI\Config\PluginConfigurationHelpers;
19
use GraphQLAPI\GraphQLAPI\Facades\UserSettingsManagerFacade;
20
use PoP\CacheControl\Environment as CacheControlEnvironment;
21
use PoP\AccessControl\Environment as AccessControlEnvironment;
22
use GraphQLAPI\GraphQLAPI\ModuleResolvers\SchemaModuleResolver;
23
use PoP\ComponentModel\Facades\Instances\InstanceManagerFacade;
24
use PoP\ComponentModel\Environment as ComponentModelEnvironment;
25
use PoPSchema\CustomPosts\Environment as CustomPostsEnvironment;
26
use GraphQLAPI\GraphQLAPI\Facades\CacheConfigurationManagerFacade;
27
use GraphQLAPI\GraphQLAPI\ModuleResolvers\FunctionalityModuleResolver;
28
use PoPSchema\Tags\ComponentConfiguration as TagsComponentConfiguration;
29
use PoPSchema\Pages\ComponentConfiguration as PagesComponentConfiguration;
30
use PoPSchema\Posts\ComponentConfiguration as PostsComponentConfiguration;
31
use PoPSchema\Users\ComponentConfiguration as UsersComponentConfiguration;
32
use GraphQLAPI\GraphQLAPI\ModuleResolvers\AddonFunctionalityModuleResolver;
33
use GraphQLAPI\GraphQLAPI\ModuleResolvers\CacheFunctionalityModuleResolver;
34
use GraphQLAPI\GraphQLAPI\ModuleResolvers\ClientFunctionalityModuleResolver;
35
use PoP\ComponentModel\ComponentConfiguration\ComponentConfigurationHelpers;
36
use PoPSchema\GenericCustomPosts\Environment as GenericCustomPostsEnvironment;
37
use GraphQLAPI\GraphQLAPI\ModuleResolvers\PioneeringFunctionalityModuleResolver;
38
use PoP\CacheControl\ComponentConfiguration as CacheControlComponentConfiguration;
39
use GraphQLAPI\GraphQLAPI\ModuleResolvers\AccessControlFunctionalityModuleResolver;
40
use GraphQLByPoP\GraphQLClientsForWP\Environment as GraphQLClientsForWPEnvironment;
41
use PoP\AccessControl\ComponentConfiguration as AccessControlComponentConfiguration;
42
use GraphQLByPoP\GraphQLEndpointForWP\Environment as GraphQLEndpointForWPEnvironment;
43
use PoP\ComponentModel\ComponentConfiguration as ComponentModelComponentConfiguration;
44
use PoPSchema\CustomPosts\ComponentConfiguration as CustomPostsComponentConfiguration;
45
use PoPSchema\GenericCustomPosts\ComponentConfiguration as GenericCustomPostsComponentConfiguration;
46
use GraphQLByPoP\GraphQLClientsForWP\ComponentConfiguration as GraphQLClientsForWPComponentConfiguration;
47
use GraphQLByPoP\GraphQLEndpointForWP\ComponentConfiguration as GraphQLEndpointForWPComponentConfiguration;
48
49
/**
50
 * Sets the configuration in all the PoP components.
51
 *
52
 * To set the value for properties, it uses this order:
53
 *
54
 * 1. Retrieve it as an environment value, if defined
55
 * 2. Retrieve as a constant `GRAPHQL_API_...` from wp-config.php, if defined
56
 * 3. Retrieve it from the user settings, if stored
57
 * 4. Use the default value
58
 *
59
 * If a slug is set or updated in the environment variable or wp-config constant,
60
 * it is necessary to flush the rewrite rules for the change to take effect.
61
 * For that, on the WordPress admin, go to Settings => Permalinks and click on Save changes
62
 */
63
class PluginConfiguration
64
{
65
    protected static $normalizedOptionValuesCache;
66
67
    /**
68
     * Initialize all configuration
69
     */
70
    public static function initialize(): void
71
    {
72
        self::mapEnvVariablesToWPConfigConstants();
73
        self::defineEnvironmentConstantsFromSettings();
74
    }
75
76
    /**
77
     * Get the values from the form submitted to options.php, and normalize them
78
     *
79
     * @return array
80
     */
81
    protected static function getNormalizedOptionValues(): array
82
    {
83
        if (is_null(self::$normalizedOptionValuesCache)) {
84
            $instanceManager = InstanceManagerFacade::getInstance();
85
            $settingsMenuPage = $instanceManager->getInstance(SettingsMenuPage::class);
86
            // Obtain the values from the POST and normalize them
87
            $value = $_POST[SettingsMenuPage::SETTINGS_FIELD];
88
            self::$normalizedOptionValuesCache = $settingsMenuPage->normalizeSettings($value);
89
        }
90
        return self::$normalizedOptionValuesCache;
91
    }
92
93
    /**
94
     * If we are in options.php, already set the new slugs in the hook,
95
     * so that the EndpointHandler's `addRewriteEndpoints` (executed on `init`)
96
     * adds the rewrite with the new slug, which will be persisted on
97
     * flushing the rewrite rules
98
     *
99
     * @return mixed
100
     */
101
    protected static function maybeOverrideValueFromForm($value, string $module, string $option)
102
    {
103
        global $pagenow;
104
        if ($pagenow == 'options.php') {
105
            $value = self::getNormalizedOptionValues();
106
            // Return the specific value to this module/option
107
            $moduleRegistry = ModuleRegistryFacade::getInstance();
108
            $moduleResolver = $moduleRegistry->getModuleResolver($module);
109
            $optionName = $moduleResolver->getSettingOptionName($module, $option);
110
            return $value[$optionName];
111
        }
112
        return $value;
113
    }
114
115
    /**
116
     * Process the "URL path" option values
117
     *
118
     * @param string $value
119
     * @param string $module
120
     * @param string $option
121
     * @return string
122
     */
123
    protected static function getURLPathSettingValue(
124
        string $value,
125
        string $module,
126
        string $option
127
    ): string {
128
        // If we are on options.php, use the value submitted to the form,
129
        // so it's updated before doing `add_rewrite_endpoint` and `flush_rewrite_rules`
130
        $value = self::maybeOverrideValueFromForm($value, $module, $option);
131
132
        // Make sure the path has a "/" on both ends
133
        return EndpointUtils::slashURI($value);
134
    }
135
136
    /**
137
     * Process the "URL base path" option values
138
     *
139
     * @param string $value
140
     * @param string $module
141
     * @param string $option
142
     * @return string
143
     */
144
    protected static function getCPTPermalinkBasePathSettingValue(
145
        string $value,
146
        string $module,
147
        string $option
148
    ): string {
149
        // If we are on options.php, use the value submitted to the form,
150
        // so it's updated before doing `add_rewrite_endpoint` and `flush_rewrite_rules`
151
        $value = self::maybeOverrideValueFromForm($value, $module, $option);
152
153
        // Make sure the path does not have "/" on either end
154
        return trim($value, '/');
155
    }
156
157
    /**
158
     * Define the values for certain environment constants from the plugin settings
159
     */
160
    protected static function defineEnvironmentConstantsFromSettings(): void
161
    {
162
        $moduleRegistry = ModuleRegistryFacade::getInstance();
163
        // All the environment variables to override
164
        $mappings = [
165
            // Editing Access Scheme
166
            [
167
                'class' => ComponentConfiguration::class,
168
                'envVariable' => Environment::EDITING_ACCESS_SCHEME,
169
                'module' => FunctionalityModuleResolver::SCHEMA_EDITING_ACCESS,
170
                'option' => FunctionalityModuleResolver::OPTION_EDITING_ACCESS_SCHEME,
171
            ],
172
            // GraphQL single endpoint slug
173
            [
174
                'class' => GraphQLEndpointForWPComponentConfiguration::class,
175
                'envVariable' => GraphQLEndpointForWPEnvironment::GRAPHQL_API_ENDPOINT,
176
                'module' => FunctionalityModuleResolver::SINGLE_ENDPOINT,
177
                'option' => FunctionalityModuleResolver::OPTION_PATH,
178
                'callback' => function ($value) {
179
                    return self::getURLPathSettingValue(
180
                        $value,
181
                        FunctionalityModuleResolver::SINGLE_ENDPOINT,
182
                        FunctionalityModuleResolver::OPTION_PATH
183
                    );
184
                },
185
                'condition' => 'any',
186
            ],
187
            // Custom Endpoint path
188
            [
189
                'class' => ComponentConfiguration::class,
190
                'envVariable' => Environment::ENDPOINT_SLUG_BASE,
191
                'module' => FunctionalityModuleResolver::CUSTOM_ENDPOINTS,
192
                'option' => FunctionalityModuleResolver::OPTION_PATH,
193
                'callback' => function ($value) {
194
                    return self::getCPTPermalinkBasePathSettingValue(
195
                        $value,
196
                        FunctionalityModuleResolver::CUSTOM_ENDPOINTS,
197
                        FunctionalityModuleResolver::OPTION_PATH
198
                    );
199
                },
200
                'condition' => 'any',
201
            ],
202
            // Persisted Query path
203
            [
204
                'class' => ComponentConfiguration::class,
205
                'envVariable' => Environment::PERSISTED_QUERY_SLUG_BASE,
206
                'module' => FunctionalityModuleResolver::PERSISTED_QUERIES,
207
                'option' => FunctionalityModuleResolver::OPTION_PATH,
208
                'callback' => function ($value) {
209
                    return self::getCPTPermalinkBasePathSettingValue(
210
                        $value,
211
                        FunctionalityModuleResolver::PERSISTED_QUERIES,
212
                        FunctionalityModuleResolver::OPTION_PATH
213
                    );
214
                },
215
                'condition' => 'any',
216
            ],
217
            // GraphiQL client slug
218
            [
219
                'class' => GraphQLClientsForWPComponentConfiguration::class,
220
                'envVariable' => GraphQLClientsForWPEnvironment::GRAPHIQL_CLIENT_ENDPOINT,
221
                'module' => ClientFunctionalityModuleResolver::GRAPHIQL_FOR_SINGLE_ENDPOINT,
222
                'option' => FunctionalityModuleResolver::OPTION_PATH,
223
                'callback' => function ($value) {
224
                    return self::getURLPathSettingValue(
225
                        $value,
226
                        ClientFunctionalityModuleResolver::GRAPHIQL_FOR_SINGLE_ENDPOINT,
227
                        FunctionalityModuleResolver::OPTION_PATH
228
                    );
229
                },
230
                'condition' => 'any',
231
            ],
232
            // Voyager client slug
233
            [
234
                'class' => GraphQLClientsForWPComponentConfiguration::class,
235
                'envVariable' => GraphQLClientsForWPEnvironment::VOYAGER_CLIENT_ENDPOINT,
236
                'module' => ClientFunctionalityModuleResolver::INTERACTIVE_SCHEMA_FOR_SINGLE_ENDPOINT,
237
                'option' => FunctionalityModuleResolver::OPTION_PATH,
238
                'callback' => function ($value) {
239
                    return self::getURLPathSettingValue(
240
                        $value,
241
                        ClientFunctionalityModuleResolver::INTERACTIVE_SCHEMA_FOR_SINGLE_ENDPOINT,
242
                        FunctionalityModuleResolver::OPTION_PATH
243
                    );
244
                },
245
                'condition' => 'any',
246
            ],
247
            // Use private schema mode?
248
            [
249
                'class' => AccessControlComponentConfiguration::class,
250
                'envVariable' => AccessControlEnvironment::USE_PRIVATE_SCHEMA_MODE,
251
                'module' => AccessControlFunctionalityModuleResolver::PUBLIC_PRIVATE_SCHEMA,
252
                'option' => AccessControlFunctionalityModuleResolver::OPTION_MODE,
253
                'callback' => function ($value) {
254
                    // It is stored as string "private" in DB, and must be passed as bool `true` to component
255
                    return $value == SchemaModes::PRIVATE_SCHEMA_MODE;
256
                },
257
            ],
258
            // Enable individual access control for the schema mode?
259
            [
260
                'class' => AccessControlComponentConfiguration::class,
261
                'envVariable' => AccessControlEnvironment::ENABLE_INDIVIDUAL_CONTROL_FOR_PUBLIC_PRIVATE_SCHEMA_MODE,
262
                'module' => AccessControlFunctionalityModuleResolver::PUBLIC_PRIVATE_SCHEMA,
263
                'option' => AccessControlFunctionalityModuleResolver::OPTION_ENABLE_GRANULAR,
264
                'callback' => function ($value) use ($moduleRegistry) {
265
                    // Also make sure that the module is enabled.
266
                    // Otherwise set the value in `false`, to override a potential `true` in the Settings
267
                    return
268
                        $moduleRegistry->isModuleEnabled(AccessControlFunctionalityModuleResolver::PUBLIC_PRIVATE_SCHEMA)
269
                        && $value;
270
                },
271
                'condition' => 'any',
272
            ],
273
            // Use namespacing?
274
            [
275
                'class' => ComponentModelComponentConfiguration::class,
276
                'envVariable' => ComponentModelEnvironment::NAMESPACE_TYPES_AND_INTERFACES,
277
                'module' => PioneeringFunctionalityModuleResolver::SCHEMA_NAMESPACING,
278
                'option' => PioneeringFunctionalityModuleResolver::OPTION_USE_NAMESPACING,
279
            ],
280
            // Cache-Control default max-age
281
            [
282
                'class' => CacheControlComponentConfiguration::class,
283
                'envVariable' => CacheControlEnvironment::DEFAULT_CACHE_CONTROL_MAX_AGE,
284
                'module' => FunctionalityModuleResolver::CACHE_CONTROL,
285
                'option' => FunctionalityModuleResolver::OPTION_MAX_AGE,
286
            ],
287
            // Custom Post default/max limits, Supported custom post types
288
            [
289
                'class' => GenericCustomPostsComponentConfiguration::class,
290
                'envVariable' => GenericCustomPostsEnvironment::GENERIC_CUSTOMPOST_LIST_DEFAULT_LIMIT,
291
                'module' => SchemaModuleResolver::SCHEMA_GENERIC_CUSTOMPOSTS,
292
                'optionModule' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
293
                'option' => SchemaModuleResolver::OPTION_LIST_DEFAULT_LIMIT,
294
            ],
295
            // [
296
            //     'class' => GenericCustomPostsComponentConfiguration::class,
297
            //     'envVariable' => GenericCustomPostsEnvironment::GENERIC_CUSTOMPOST_LIST_MAX_LIMIT,
298
            //     'module' => SchemaModuleResolver::SCHEMA_GENERIC_CUSTOMPOSTS,
299
            //     'optionModule' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
300
            //     'option' => SchemaModuleResolver::OPTION_LIST_MAX_LIMIT,
301
            // ],
302
            [
303
                'class' => GenericCustomPostsComponentConfiguration::class,
304
                'envVariable' => GenericCustomPostsEnvironment::GENERIC_CUSTOMPOST_TYPES,
305
                'module' => SchemaModuleResolver::SCHEMA_GENERIC_CUSTOMPOSTS,
306
                'option' => SchemaModuleResolver::OPTION_CUSTOMPOST_TYPES,
307
            ],
308
            // Post default/max limits, add to CustomPostUnion
309
            [
310
                'class' => PostsComponentConfiguration::class,
311
                'envVariable' => PostsEnvironment::POST_LIST_DEFAULT_LIMIT,
312
                'module' => SchemaModuleResolver::SCHEMA_POSTS,
313
                'optionModule' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
314
                'option' => SchemaModuleResolver::OPTION_LIST_DEFAULT_LIMIT,
315
            ],
316
            [
317
                'class' => PostsComponentConfiguration::class,
318
                'envVariable' => PostsEnvironment::POST_LIST_MAX_LIMIT,
319
                'module' => SchemaModuleResolver::SCHEMA_POSTS,
320
                'optionModule' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
321
                'option' => SchemaModuleResolver::OPTION_LIST_MAX_LIMIT,
322
            ],
323
            [
324
                'class' => PostsComponentConfiguration::class,
325
                'envVariable' => PostsEnvironment::ADD_POST_TYPE_TO_CUSTOMPOST_UNION_TYPES,
326
                'module' => SchemaModuleResolver::SCHEMA_POSTS,
327
                'option' => SchemaModuleResolver::OPTION_ADD_TYPE_TO_CUSTOMPOST_UNION_TYPE,
328
            ],
329
            // User default/max limits
330
            [
331
                'class' => UsersComponentConfiguration::class,
332
                'envVariable' => UsersEnvironment::USER_LIST_DEFAULT_LIMIT,
333
                'module' => SchemaModuleResolver::SCHEMA_USERS,
334
                'option' => SchemaModuleResolver::OPTION_LIST_DEFAULT_LIMIT,
335
            ],
336
            [
337
                'class' => UsersComponentConfiguration::class,
338
                'envVariable' => UsersEnvironment::USER_LIST_MAX_LIMIT,
339
                'module' => SchemaModuleResolver::SCHEMA_USERS,
340
                'option' => SchemaModuleResolver::OPTION_LIST_MAX_LIMIT,
341
            ],
342
            // Tag default/max limits
343
            [
344
                'class' => TagsComponentConfiguration::class,
345
                'envVariable' => TagsEnvironment::TAG_LIST_DEFAULT_LIMIT,
346
                'module' => SchemaModuleResolver::SCHEMA_TAGS,
347
                'option' => SchemaModuleResolver::OPTION_LIST_DEFAULT_LIMIT,
348
            ],
349
            [
350
                'class' => TagsComponentConfiguration::class,
351
                'envVariable' => TagsEnvironment::TAG_LIST_MAX_LIMIT,
352
                'module' => SchemaModuleResolver::SCHEMA_TAGS,
353
                'option' => SchemaModuleResolver::OPTION_LIST_MAX_LIMIT,
354
            ],
355
            // Page default/max limits, add to CustomPostUnion
356
            [
357
                'class' => PagesComponentConfiguration::class,
358
                'envVariable' => PagesEnvironment::PAGE_LIST_DEFAULT_LIMIT,
359
                'module' => SchemaModuleResolver::SCHEMA_PAGES,
360
                'optionModule' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
361
                'option' => SchemaModuleResolver::OPTION_LIST_DEFAULT_LIMIT,
362
            ],
363
            [
364
                'class' => PagesComponentConfiguration::class,
365
                'envVariable' => PagesEnvironment::PAGE_LIST_MAX_LIMIT,
366
                'module' => SchemaModuleResolver::SCHEMA_PAGES,
367
                'optionModule' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
368
                'option' => SchemaModuleResolver::OPTION_LIST_MAX_LIMIT,
369
            ],
370
            [
371
                'class' => PagesComponentConfiguration::class,
372
                'envVariable' => PagesEnvironment::ADD_PAGE_TYPE_TO_CUSTOMPOST_UNION_TYPES,
373
                'module' => SchemaModuleResolver::SCHEMA_PAGES,
374
                'option' => SchemaModuleResolver::OPTION_ADD_TYPE_TO_CUSTOMPOST_UNION_TYPE,
375
            ],
376
            // Custom post default/max limits
377
            [
378
                'class' => CustomPostsComponentConfiguration::class,
379
                'envVariable' => CustomPostsEnvironment::CUSTOMPOST_LIST_DEFAULT_LIMIT,
380
                'module' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
381
                'option' => SchemaModuleResolver::OPTION_LIST_DEFAULT_LIMIT,
382
            ],
383
            [
384
                'class' => CustomPostsComponentConfiguration::class,
385
                'envVariable' => CustomPostsEnvironment::CUSTOMPOST_LIST_MAX_LIMIT,
386
                'module' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
387
                'option' => SchemaModuleResolver::OPTION_LIST_MAX_LIMIT,
388
            ],
389
            // Custom post, if there is only one custom type, use it instead of the Union
390
            [
391
                'class' => CustomPostsComponentConfiguration::class,
392
                'envVariable' => CustomPostsEnvironment::USE_SINGLE_TYPE_INSTEAD_OF_CUSTOMPOST_UNION_TYPE,
393
                'module' => SchemaModuleResolver::SCHEMA_CUSTOMPOSTS,
394
                'option' => SchemaModuleResolver::OPTION_USE_SINGLE_TYPE_INSTEAD_OF_UNION_TYPE,
395
            ],
396
        ];
397
        // For each environment variable, see if its value has been saved in the settings
398
        $userSettingsManager = UserSettingsManagerFacade::getInstance();
399
        foreach ($mappings as $mapping) {
400
            $module = $mapping['module'];
401
            $condition = $mapping['condition'] ?? true;
402
            // Check if the hook must be executed always (condition => 'any') or with
403
            // stated enabled (true) or disabled (false). By default, it's enabled
404
            if ($condition !== 'any' && $condition !== $moduleRegistry->isModuleEnabled($module)) {
405
                continue;
406
            }
407
            // If the environment value has been defined, or the constant in wp-config.php,
408
            // then do nothing, since they have priority
409
            $envVariable = $mapping['envVariable'];
410
            if (isset($_ENV[$envVariable]) || PluginConfigurationHelpers::isWPConfigConstantDefined($envVariable)) {
411
                continue;
412
            }
413
            $hookName = ComponentConfigurationHelpers::getHookName(
414
                $mapping['class'],
415
                $envVariable
416
            );
417
            $option = $mapping['option'];
418
            $optionModule = $mapping['optionModule'] ?? $module;
419
            // Make explicit it can be null so that PHPStan level 3 doesn't fail
420
            $callback = $mapping['callback'] ?? null;
421
            \add_filter(
422
                $hookName,
423
                function () use ($userSettingsManager, $optionModule, $option, $callback) {
424
                    $value = $userSettingsManager->getSetting($optionModule, $option);
425
                    if (!is_null($callback)) {
426
                        return $callback($value);
427
                    }
428
                    return $value;
429
                }
430
            );
431
        }
432
    }
433
434
    /**
435
     * Map the environment variables from the components, to WordPress wp-config.php constants
436
     */
437
    protected static function mapEnvVariablesToWPConfigConstants(): void
438
    {
439
        // All the environment variables to override
440
        $mappings = [
441
            [
442
                'class' => ComponentConfiguration::class,
443
                'envVariable' => Environment::ADD_EXCERPT_AS_DESCRIPTION,
444
            ],
445
            [
446
                'class' => GraphQLEndpointForWPComponentConfiguration::class,
447
                'envVariable' => GraphQLEndpointForWPEnvironment::GRAPHQL_API_ENDPOINT,
448
            ],
449
            [
450
                'class' => GraphQLClientsForWPComponentConfiguration::class,
451
                'envVariable' => GraphQLClientsForWPEnvironment::GRAPHIQL_CLIENT_ENDPOINT,
452
            ],
453
            [
454
                'class' => GraphQLClientsForWPComponentConfiguration::class,
455
                'envVariable' => GraphQLClientsForWPEnvironment::VOYAGER_CLIENT_ENDPOINT,
456
            ],
457
            [
458
                'class' => AccessControlComponentConfiguration::class,
459
                'envVariable' => AccessControlEnvironment::USE_PRIVATE_SCHEMA_MODE,
460
            ],
461
            [
462
                'class' => AccessControlComponentConfiguration::class,
463
                'envVariable' => AccessControlEnvironment::ENABLE_INDIVIDUAL_CONTROL_FOR_PUBLIC_PRIVATE_SCHEMA_MODE,
464
            ],
465
            [
466
                'class' => ComponentModelComponentConfiguration::class,
467
                'envVariable' => ComponentModelEnvironment::NAMESPACE_TYPES_AND_INTERFACES,
468
            ],
469
            [
470
                'class' => CacheControlComponentConfiguration::class,
471
                'envVariable' => CacheControlEnvironment::DEFAULT_CACHE_CONTROL_MAX_AGE,
472
            ],
473
        ];
474
        // For each environment variable, see if it has been defined as a wp-config.php constant
475
        foreach ($mappings as $mapping) {
476
            $class = $mapping['class'];
477
            $envVariable = $mapping['envVariable'];
478
479
            // If the environment value has been defined, then do nothing, since it has priority
480
            if (isset($_ENV[$envVariable])) {
481
                continue;
482
            }
483
            $hookName = ComponentConfigurationHelpers::getHookName(
484
                $class,
485
                $envVariable
486
            );
487
488
            \add_filter(
489
                $hookName,
490
                /**
491
                 * Override the value of an environment variable if it has been definedas a constant
492
                 * in wp-config.php, with the environment name prepended with "GRAPHQL_API_"
493
                 */
494
                function ($value) use ($envVariable) {
495
                    if (PluginConfigurationHelpers::isWPConfigConstantDefined($envVariable)) {
496
                        return PluginConfigurationHelpers::getWPConfigConstantValue($envVariable);
497
                    }
498
                    return $value;
499
                }
500
            );
501
        }
502
    }
503
504
    /**
505
     * Provide the configuration for all components required in the plugin
506
     *
507
     * @return array
508
     */
509
    public static function getComponentClassConfiguration(): array
510
    {
511
        $componentClassConfiguration = [];
512
        self::addPredefinedComponentClassConfiguration($componentClassConfiguration);
513
        self::addBasedOnModuleEnabledStateComponentClassConfiguration($componentClassConfiguration);
514
        return $componentClassConfiguration;
515
    }
516
517
    /**
518
     * Add the fixed configuration for all components required in the plugin
519
     *
520
     * @return void
521
     */
522
    protected static function addPredefinedComponentClassConfiguration(array &$componentClassConfiguration): void
523
    {
524
        $componentClassConfiguration[\PoP\Engine\Component::class] = [
525
            \PoP\Engine\Environment::ADD_MANDATORY_CACHE_CONTROL_DIRECTIVE => false,
526
        ];
527
        $componentClassConfiguration[\GraphQLByPoP\GraphQLClientsForWP\Component::class] = [
528
            \GraphQLByPoP\GraphQLClientsForWP\Environment::GRAPHQL_CLIENTS_COMPONENT_URL => \GRAPHQL_API_URL . 'vendor/graphql-by-pop/graphql-clients-for-wp',
529
        ];
530
        // Disable the Native endpoint
531
        $componentClassConfiguration[\PoP\APIEndpointsForWP\Component::class] = [
532
            \PoP\APIEndpointsForWP\Environment::DISABLE_NATIVE_API_ENDPOINT => true,
533
        ];
534
        // Disable processing ?query=...
535
        $componentClassConfiguration[\GraphQLByPoP\GraphQLRequest\Component::class] = [
536
            \GraphQLByPoP\GraphQLRequest\Environment::DISABLE_GRAPHQL_API_FOR_POP => true,
537
        ];
538
        // Cache the container
539
        $moduleRegistry = ModuleRegistryFacade::getInstance();
540
        if ($moduleRegistry->isModuleEnabled(CacheFunctionalityModuleResolver::CONFIGURATION_CACHE)) {
541
            $cacheConfigurationManager = CacheConfigurationManagerFacade::getInstance();
542
            $componentClassConfiguration[\PoP\Root\Component::class] = [
543
                \PoP\Root\Environment::CACHE_CONTAINER_CONFIGURATION => true,
544
                \PoP\Root\Environment::CONTAINER_CONFIGURATION_CACHE_NAMESPACE => $cacheConfigurationManager->getNamespace(),
545
            ];
546
        }
547
        // Expose the "self" field when doing Low Level Query Editing
548
        if ($moduleRegistry->isModuleEnabled(AddonFunctionalityModuleResolver::LOW_LEVEL_QUERY_EDITING)) {
549
            $componentClassConfiguration[\GraphQLByPoP\GraphQLServer\Component::class] = [
550
                \GraphQLByPoP\GraphQLServer\Environment::ADD_SELF_FIELD_FOR_ROOT_TYPE_TO_SCHEMA => true,
551
            ];
552
        }
553
        // Enable Multiple Query Execution?
554
        $componentClassConfiguration[\GraphQLByPoP\GraphQLRequest\Component::class] = [
555
            \GraphQLByPoP\GraphQLRequest\Environment::ENABLE_MULTIPLE_QUERY_EXECUTION => $moduleRegistry->isModuleEnabled(PioneeringFunctionalityModuleResolver::MULTIPLE_QUERY_EXECUTION),
556
        ];
557
    }
558
559
    /**
560
     * Return the opposite value
561
     *
562
     * @param boolean $value
563
     * @return boolean
564
     */
565
    protected static function opposite(bool $value): bool
566
    {
567
        return !$value;
568
    }
569
570
    /**
571
     * Add configuration values if modules are enabled or disabled
572
     *
573
     * @return void
574
     */
575
    protected static function addBasedOnModuleEnabledStateComponentClassConfiguration(array &$componentClassConfiguration): void
576
    {
577
        $moduleRegistry = ModuleRegistryFacade::getInstance();
578
        $moduleToComponentClassConfigurationMappings = [
579
            [
580
                'module' => FunctionalityModuleResolver::SINGLE_ENDPOINT,
581
                'class' => \GraphQLByPoP\GraphQLEndpointForWP\Component::class,
582
                'envVariable' => \GraphQLByPoP\GraphQLEndpointForWP\Environment::DISABLE_GRAPHQL_API_ENDPOINT,
583
                'callback' => [self::class, 'opposite'],
584
            ],
585
            [
586
                'module' => ClientFunctionalityModuleResolver::GRAPHIQL_FOR_SINGLE_ENDPOINT,
587
                'class' => \GraphQLByPoP\GraphQLClientsForWP\Component::class,
588
                'envVariable' => \GraphQLByPoP\GraphQLClientsForWP\Environment::DISABLE_GRAPHIQL_CLIENT_ENDPOINT,
589
                'callback' => [self::class, 'opposite'],
590
            ],
591
            [
592
                'module' => ClientFunctionalityModuleResolver::INTERACTIVE_SCHEMA_FOR_SINGLE_ENDPOINT,
593
                'class' => \GraphQLByPoP\GraphQLClientsForWP\Component::class,
594
                'envVariable' => \GraphQLByPoP\GraphQLClientsForWP\Environment::DISABLE_VOYAGER_CLIENT_ENDPOINT,
595
                'callback' => [self::class, 'opposite'],
596
            ],
597
            // Cache the component model configuration
598
            [
599
                'module' => CacheFunctionalityModuleResolver::CONFIGURATION_CACHE,
600
                'class' => \PoP\ComponentModel\Component::class,
601
                'envVariable' => \PoP\ComponentModel\Environment::USE_COMPONENT_MODEL_CACHE,
602
            ],
603
            // Cache the schema
604
            [
605
                'module' => CacheFunctionalityModuleResolver::SCHEMA_CACHE,
606
                'class' => \PoP\API\Component::class,
607
                'envVariable' => \PoP\API\Environment::USE_SCHEMA_DEFINITION_CACHE,
608
            ],
609
        ];
610
        foreach ($moduleToComponentClassConfigurationMappings as $mapping) {
611
            // Copy the state (enabled/disabled) to the component
612
            $value = $moduleRegistry->isModuleEnabled($mapping['module']);
613
            // Make explicit it can be null so that PHPStan level 3 doesn't fail
614
            $callback = $mapping['callback'] ?? null;
615
            if (!is_null($callback)) {
616
                $value = $callback($value);
617
            }
618
            $componentClassConfiguration[$mapping['class']][$mapping['envVariable']] = $value;
619
        }
620
    }
621
622
    /**
623
     * Provide the classes of the components whose
624
     * schema initialization must be skipped
625
     *
626
     * @return array
627
     */
628
    public static function getSkippingSchemaComponentClasses(): array
629
    {
630
        $moduleRegistry = ModuleRegistryFacade::getInstance();
631
632
        // Component classes enabled/disabled by module
633
        $maybeSkipSchemaModuleComponentClasses = [
634
            SchemaModuleResolver::SCHEMA_CUSTOMPOSTS => [
635
                \PoPSchema\CustomPostMedia\Component::class,
636
            ],
637
            SchemaModuleResolver::SCHEMA_GENERIC_CUSTOMPOSTS => [
638
                \PoPSchema\GenericCustomPosts\Component::class,
639
            ],
640
            SchemaModuleResolver::SCHEMA_POSTS => [
641
                \PoPSchema\Posts\Component::class,
642
            ],
643
            SchemaModuleResolver::SCHEMA_COMMENTS => [
644
                \PoPSchema\Comments\Component::class,
645
            ],
646
            SchemaModuleResolver::SCHEMA_USERS => [
647
                \PoPSchema\Users\Component::class,
648
                \PoPSchema\UserState\Component::class,
649
            ],
650
            SchemaModuleResolver::SCHEMA_USER_ROLES => [
651
                \PoPSchema\UserRoles\Component::class,
652
            ],
653
            SchemaModuleResolver::SCHEMA_PAGES => [
654
                \PoPSchema\Pages\Component::class,
655
            ],
656
            SchemaModuleResolver::SCHEMA_MEDIA => [
657
                \PoPSchema\CustomPostMedia\Component::class,
658
                \PoPSchema\Media\Component::class,
659
            ],
660
            SchemaModuleResolver::SCHEMA_TAGS => [
661
                \PoPSchema\Tags\Component::class,
662
            ],
663
            SchemaModuleResolver::SCHEMA_POST_TAGS => [
664
                \PoPSchema\PostTags\Component::class,
665
            ],
666
        ];
667
        $skipSchemaModuleComponentClasses = array_filter(
668
            $maybeSkipSchemaModuleComponentClasses,
669
            function ($module) use ($moduleRegistry) {
670
                return !$moduleRegistry->isModuleEnabled($module);
671
            },
672
            ARRAY_FILTER_USE_KEY
673
        );
674
        return GeneralUtils::arrayFlatten(
675
            array_values(
676
                $skipSchemaModuleComponentClasses
677
            )
678
        );
679
    }
680
}
681