Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 18 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
JsonSchemaReferenceResolver | |
0.00% |
0 / 18 |
|
0.00% |
0 / 4 |
56 | |
0.00% |
0 / 1 |
normalizeRef | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
unpackRef | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
getDefinitionName | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
resolveRef | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Settings\Source; |
4 | |
5 | use Error; |
6 | use InvalidArgumentException; |
7 | |
8 | /** |
9 | * Utility for resolving references ($ref) in JSON-schemas |
10 | * and building a collection of the referenced definitions. |
11 | * |
12 | * @since 1.42 |
13 | * @unstable |
14 | */ |
15 | class JsonSchemaReferenceResolver { |
16 | /** |
17 | * Returns a URI relative to a JSON-schema document |
18 | * for a given definition name |
19 | * |
20 | * @param array $schema A $ref sub-schema |
21 | * @return string Definition relative URI |
22 | */ |
23 | public static function normalizeRef( array $schema ): string { |
24 | return '#/$defs/' . self::getDefinitionName( $schema ); |
25 | } |
26 | |
27 | /** |
28 | * Destructures and validates a JSON-schema "$ref" definition of the |
29 | * form [ "class" => SomePHPClass:class, "field" => "someExistingPublicConsInTheClass" ] |
30 | * |
31 | * @param array $schema A $ref sub-schema |
32 | * @return array An array with the class name as the first element, and the field name as the second. |
33 | */ |
34 | private static function unpackRef( array $schema ): array { |
35 | $className = $schema['class']; |
36 | $field = $schema['field']; |
37 | if ( !$className || !$field ) { |
38 | throw new InvalidArgumentException( 'The schema $ref must have "class" and "field" defined.' ); |
39 | } |
40 | return [ |
41 | $className, |
42 | $field |
43 | ]; |
44 | } |
45 | |
46 | /** |
47 | * Builds a definition name based on the specified "$ref" definition |
48 | * |
49 | * @param array $schema A $ref sub-schema |
50 | * @return string A definition name using both the name of the class and the field |
51 | */ |
52 | public static function getDefinitionName( array $schema ): string { |
53 | [ $className, $field ] = self::unpackRef( $schema ); |
54 | // Avoid using "\" or "/" in the definition name as they are interpreted as fragment |
55 | // separators in the URI and make consumers of the schema unable to resolve a document |
56 | // relative schema. Use "." as the word separator for the namespace, resulting in |
57 | // eg: SomeExtension.Namespace.MyClass::MyConstant |
58 | return str_replace( "\\", '.', $className ) . '::' . $field; |
59 | } |
60 | |
61 | /** |
62 | * Returns the value of a given reference "$ref". |
63 | * |
64 | * @param array $schema A $ref sub-schema |
65 | * @return array The value of the class field referenced by the definition |
66 | */ |
67 | public static function resolveRef( array $schema, string $rootClass ): array { |
68 | [ $className, $fieldName ] = self::unpackRef( $schema ); |
69 | try { |
70 | $value = constant( "$className::$fieldName" ); |
71 | } catch ( Error $e ) { |
72 | throw new RefNotFoundException( |
73 | "Failed resolving reference $fieldName in $className. Root schema location: $rootClass" |
74 | ); |
75 | } |
76 | return $value; |
77 | } |
78 | |
79 | } |