PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.3
WooCommerce v10.9.3
10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / lib / packages / GraphQL / Validator / DocumentValidator.php
woocommerce / lib / packages / GraphQL / Validator Last commit date
Rules 2 months ago DocumentValidator.php 2 months ago QueryValidationContext.php 2 months ago SDLValidationContext.php 2 months ago ValidationContext.php 2 months ago
DocumentValidator.php
331 lines
1 <?php declare(strict_types=1);
2
3 namespace Automattic\WooCommerce\Vendor\GraphQL\Validator;
4
5 use Automattic\WooCommerce\Vendor\GraphQL\Error\Error;
6 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\DocumentNode;
7 use Automattic\WooCommerce\Vendor\GraphQL\Language\Visitor;
8 use Automattic\WooCommerce\Vendor\GraphQL\Type\Schema;
9 use Automattic\WooCommerce\Vendor\GraphQL\Utils\TypeInfo;
10 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\DisableIntrospection;
11 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ExecutableDefinitions;
12 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\FieldsOnCorrectType;
13 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\FragmentsOnCompositeTypes;
14 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\KnownArgumentNames;
15 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\KnownArgumentNamesOnDirectives;
16 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\KnownDirectives;
17 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\KnownFragmentNames;
18 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\KnownTypeNames;
19 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\LoneAnonymousOperation;
20 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\LoneSchemaDefinition;
21 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\NoFragmentCycles;
22 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\NoUndefinedVariables;
23 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\NoUnusedFragments;
24 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\NoUnusedVariables;
25 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\OneOfInputObjectsRule;
26 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged;
27 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\PossibleFragmentSpreads;
28 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\PossibleTypeExtensions;
29 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ProvidedRequiredArguments;
30 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ProvidedRequiredArgumentsOnDirectives;
31 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\QueryComplexity;
32 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\QueryDepth;
33 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\QuerySecurityRule;
34 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ScalarLeafs;
35 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\SingleFieldSubscription;
36 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueArgumentDefinitionNames;
37 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueArgumentNames;
38 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueDirectiveNames;
39 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueDirectivesPerLocation;
40 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueEnumValueNames;
41 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueFieldDefinitionNames;
42 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueFragmentNames;
43 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueInputFieldNames;
44 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueOperationNames;
45 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueOperationTypes;
46 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueTypeNames;
47 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\UniqueVariableNames;
48 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ValidationRule;
49 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ValuesOfCorrectType;
50 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\VariablesAreInputTypes;
51 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\VariablesInAllowedPosition;
52
53 /**
54 * Implements the "Validation" section of the spec.
55 *
56 * Validation runs synchronously, returning an array of encountered errors, or
57 * an empty array if no errors were encountered and the document is valid.
58 *
59 * A list of specific validation rules may be provided. If not provided, the
60 * default list of rules defined by the Automattic\WooCommerce\Vendor\GraphQL specification will be used.
61 *
62 * Each validation rule is an instance of Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\ValidationRule
63 * which returns a visitor (see the [Automattic\WooCommerce\Vendor\GraphQL\Language\Visitor API](class-reference.md#graphqllanguagevisitor)).
64 *
65 * Visitor methods are expected to return an instance of [Automattic\WooCommerce\Vendor\GraphQL\Error\Error](class-reference.md#graphqlerrorerror),
66 * or array of such instances when invalid.
67 *
68 * Optionally a custom TypeInfo instance may be provided. If not provided, one
69 * will be created from the provided schema.
70 */
71 class DocumentValidator
72 {
73 /** @var array<string, ValidationRule> */
74 private static array $rules = [];
75
76 /** @var array<class-string<ValidationRule>, ValidationRule> */
77 private static array $defaultRules;
78
79 /** @var array<class-string<QuerySecurityRule>, QuerySecurityRule> */
80 private static array $securityRules;
81
82 /** @var array<class-string<ValidationRule>, ValidationRule> */
83 private static array $sdlRules;
84
85 private static bool $initRules = false;
86
87 /**
88 * Validate a Automattic\WooCommerce\Vendor\GraphQL query against a schema.
89 *
90 * @param array<ValidationRule>|null $rules Defaults to using all available rules
91 *
92 * @throws \Exception
93 *
94 * @return list<Error>
95 *
96 * @api
97 */
98 public static function validate(
99 Schema $schema,
100 DocumentNode $ast,
101 ?array $rules = null,
102 ?TypeInfo $typeInfo = null
103 ): array {
104 $rules ??= static::allRules();
105
106 if ($rules === []) {
107 return [];
108 }
109
110 $typeInfo ??= new TypeInfo($schema);
111
112 $context = new QueryValidationContext($schema, $ast, $typeInfo);
113
114 $visitors = [];
115 foreach ($rules as $rule) {
116 $visitors[] = $rule->getVisitor($context);
117 }
118
119 Visitor::visit(
120 $ast,
121 Visitor::visitWithTypeInfo(
122 $typeInfo,
123 Visitor::visitInParallel($visitors)
124 )
125 );
126
127 return $context->getErrors();
128 }
129
130 /**
131 * Returns all global validation rules.
132 *
133 * @throws \InvalidArgumentException
134 *
135 * @return array<string, ValidationRule>
136 *
137 * @api
138 */
139 public static function allRules(): array
140 {
141 if (! self::$initRules) {
142 self::$rules = array_merge(
143 static::defaultRules(),
144 self::securityRules(),
145 self::$rules
146 );
147 self::$initRules = true;
148 }
149
150 return self::$rules;
151 }
152
153 /** @return array<class-string<ValidationRule>, ValidationRule> */
154 public static function defaultRules(): array
155 {
156 return self::$defaultRules ??= [
157 ExecutableDefinitions::class => new ExecutableDefinitions(),
158 UniqueOperationNames::class => new UniqueOperationNames(),
159 LoneAnonymousOperation::class => new LoneAnonymousOperation(),
160 SingleFieldSubscription::class => new SingleFieldSubscription(),
161 KnownTypeNames::class => new KnownTypeNames(),
162 FragmentsOnCompositeTypes::class => new FragmentsOnCompositeTypes(),
163 VariablesAreInputTypes::class => new VariablesAreInputTypes(),
164 ScalarLeafs::class => new ScalarLeafs(),
165 FieldsOnCorrectType::class => new FieldsOnCorrectType(),
166 UniqueFragmentNames::class => new UniqueFragmentNames(),
167 KnownFragmentNames::class => new KnownFragmentNames(),
168 NoUnusedFragments::class => new NoUnusedFragments(),
169 PossibleFragmentSpreads::class => new PossibleFragmentSpreads(),
170 NoFragmentCycles::class => new NoFragmentCycles(),
171 UniqueVariableNames::class => new UniqueVariableNames(),
172 NoUndefinedVariables::class => new NoUndefinedVariables(),
173 NoUnusedVariables::class => new NoUnusedVariables(),
174 KnownDirectives::class => new KnownDirectives(),
175 UniqueDirectivesPerLocation::class => new UniqueDirectivesPerLocation(),
176 KnownArgumentNames::class => new KnownArgumentNames(),
177 UniqueArgumentNames::class => new UniqueArgumentNames(),
178 ValuesOfCorrectType::class => new ValuesOfCorrectType(),
179 ProvidedRequiredArguments::class => new ProvidedRequiredArguments(),
180 VariablesInAllowedPosition::class => new VariablesInAllowedPosition(),
181 OverlappingFieldsCanBeMerged::class => new OverlappingFieldsCanBeMerged(),
182 UniqueInputFieldNames::class => new UniqueInputFieldNames(),
183 OneOfInputObjectsRule::class => new OneOfInputObjectsRule(),
184 ];
185 }
186
187 /**
188 * @deprecated just add rules via @see DocumentValidator::addRule()
189 *
190 * @throws \InvalidArgumentException
191 *
192 * @return array<class-string<QuerySecurityRule>, QuerySecurityRule>
193 */
194 public static function securityRules(): array
195 {
196 return self::$securityRules ??= [
197 DisableIntrospection::class => new DisableIntrospection(DisableIntrospection::DISABLED),
198 QueryDepth::class => new QueryDepth(QueryDepth::DISABLED),
199 QueryComplexity::class => new QueryComplexity(QueryComplexity::DISABLED),
200 ];
201 }
202
203 /** @return array<class-string<ValidationRule>, ValidationRule> */
204 public static function sdlRules(): array
205 {
206 return self::$sdlRules ??= [
207 LoneSchemaDefinition::class => new LoneSchemaDefinition(),
208 UniqueOperationTypes::class => new UniqueOperationTypes(),
209 UniqueTypeNames::class => new UniqueTypeNames(),
210 UniqueEnumValueNames::class => new UniqueEnumValueNames(),
211 UniqueFieldDefinitionNames::class => new UniqueFieldDefinitionNames(),
212 UniqueArgumentDefinitionNames::class => new UniqueArgumentDefinitionNames(),
213 UniqueDirectiveNames::class => new UniqueDirectiveNames(),
214 KnownTypeNames::class => new KnownTypeNames(),
215 KnownDirectives::class => new KnownDirectives(),
216 UniqueDirectivesPerLocation::class => new UniqueDirectivesPerLocation(),
217 PossibleTypeExtensions::class => new PossibleTypeExtensions(),
218 KnownArgumentNamesOnDirectives::class => new KnownArgumentNamesOnDirectives(),
219 UniqueArgumentNames::class => new UniqueArgumentNames(),
220 UniqueInputFieldNames::class => new UniqueInputFieldNames(),
221 ProvidedRequiredArgumentsOnDirectives::class => new ProvidedRequiredArgumentsOnDirectives(),
222 ];
223 }
224
225 /**
226 * Returns global validation rule by name.
227 *
228 * Standard rules are named by class name, so example usage for such rules:
229 *
230 * @example DocumentValidator::getRule(Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\QueryComplexity::class);
231 *
232 * @api
233 *
234 * @throws \InvalidArgumentException
235 */
236 public static function getRule(string $name): ?ValidationRule
237 {
238 return static::allRules()[$name] ?? null;
239 }
240
241 /**
242 * Add rule to list of global validation rules.
243 *
244 * @api
245 */
246 public static function addRule(ValidationRule $rule): void
247 {
248 self::$rules[$rule->getName()] = $rule;
249 }
250
251 /**
252 * Remove rule from list of global validation rules.
253 *
254 * @api
255 */
256 public static function removeRule(ValidationRule $rule): void
257 {
258 unset(self::$rules[$rule->getName()]);
259 }
260
261 /**
262 * Validate a Automattic\WooCommerce\Vendor\GraphQL document defined through schema definition language.
263 *
264 * @param array<ValidationRule>|null $rules
265 *
266 * @throws \Exception
267 *
268 * @return list<Error>
269 */
270 public static function validateSDL(
271 DocumentNode $documentAST,
272 ?Schema $schemaToExtend = null,
273 ?array $rules = null
274 ): array {
275 $rules ??= self::sdlRules();
276
277 if ($rules === []) {
278 return [];
279 }
280
281 $context = new SDLValidationContext($documentAST, $schemaToExtend);
282
283 $visitors = [];
284 foreach ($rules as $rule) {
285 $visitors[] = $rule->getSDLVisitor($context);
286 }
287
288 Visitor::visit(
289 $documentAST,
290 Visitor::visitInParallel($visitors)
291 );
292
293 return $context->getErrors();
294 }
295
296 /**
297 * @throws \Exception
298 * @throws Error
299 */
300 public static function assertValidSDL(DocumentNode $documentAST): void
301 {
302 $errors = self::validateSDL($documentAST);
303 if ($errors !== []) {
304 throw new Error(self::combineErrorMessages($errors));
305 }
306 }
307
308 /**
309 * @throws \Exception
310 * @throws Error
311 */
312 public static function assertValidSDLExtension(DocumentNode $documentAST, Schema $schema): void
313 {
314 $errors = self::validateSDL($documentAST, $schema);
315 if ($errors !== []) {
316 throw new Error(self::combineErrorMessages($errors));
317 }
318 }
319
320 /** @param array<Error> $errors */
321 private static function combineErrorMessages(array $errors): string
322 {
323 $messages = [];
324 foreach ($errors as $error) {
325 $messages[] = $error->getMessage();
326 }
327
328 return implode("\n\n", $messages);
329 }
330 }
331