-
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathPatternLibraryJSONParserTrait.php
More file actions
126 lines (118 loc) · 4.31 KB
/
Copy pathPatternLibraryJSONParserTrait.php
File metadata and controls
126 lines (118 loc) · 4.31 KB
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
<?php
namespace Drupal\patternkit;
use Drupal\Component\Serialization\SerializationInterface;
use Drupal\patternkit\Entity\PatternInterface;
/**
* Provides methods for parsing JSON schema.
*/
trait PatternLibraryJSONParserTrait {
/**
* Serializes and de-serializes data.
*
* @var \Drupal\Component\Serialization\SerializationInterface
*/
protected SerializationInterface $serializer;
/**
* Fetches a JSON Schema from a file URI.
*
* @param string $file_uri
* URI of the JSON file to decode.
*
* @return mixed
* Truthy mixed data if the contents are successfully decoded.
*/
public function fetchJsonSchemaAsset(string $file_uri) {
return $this->serializer::decode(file_get_contents($file_uri));
}
/**
* Parses schema properties for $ref and updates their location.
*
* @param array|object $properties
* The properties to parse.
* @param \Drupal\patternkit\Entity\PatternInterface $pattern
* Pattern for retrieving schema data and pathing.
*
* @return array|object
* The updated schema properties.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
*
* @example JSON Schema technically allows the following valid refs:
* - URI "example.json" "../../example.json" "./example.json"
* - URL "https://json-schema.org/person.schema.json"
* - JSON Pointer "#/definitions/example" "example.json#/example"
* Additionally we support Twig namespaces:
* - Twig NS "@mylibrary/example" "@mylibrary/category/example.json"
* - ... and a combination of some of the above.
* - "@mylibrary/category/example.json#/definitions/example"
* - "./../../../test.json"
*/
public static function schemaDereference($properties, PatternInterface $pattern) {
$ext = '.json';
$ext_len = strlen($ext);
$namespace_resolver = \Drupal::service('patternkit.library.namespace_resolver');
foreach ($properties as $property => $value) {
if (!is_scalar($value)) {
$new_value = static::schemaDereference($value, $pattern);
if (is_object($properties)) {
$properties->{$property} = $new_value;
}
if (is_array($properties)) {
$properties[$property] = $new_value;
}
continue;
}
if ($property !== '$ref') {
continue;
}
if (strpos($value, '#/') === 0) {
continue;
}
/** @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_manager */
$stream_manager = \Drupal::service('stream_wrapper_manager');
if ($stream_manager->isValidScheme($stream_manager->getViaUri($value))) {
continue;
}
$path = $value;
if (strpos($value, '@') === 0) {
$library_namespace = strstr($value, '/', TRUE);
$path = substr($value, strlen("$library_namespace/"));
}
$ref = '';
if (strpos($path, '#/') !== FALSE) {
$ref = explode('#/', $path);
$path = reset($ref);
$ref = !empty($ref[1]) ? '#/' . $ref[1] : '';
}
$library_name = $pattern->getLibrary();
// Since schema paths can be relative, we loop through each possible
// pattern library path to locate the schema, with overrides allowed.
if (strpos($path, './') !== FALSE) {
$pattern_library = $namespace_resolver->getLibraryFromNamespace("@$library_name");
$library_path = $pattern_library['extensionPath'];
$realpath = $path;
foreach ($pattern_library['patterns'] as $info) {
if (!isset($info['data'])) {
continue;
}
$library_path = $info['data'] ?? $library_path;
$realpath = realpath($library_path . '/' . $path) ?? $realpath;
}
$path = substr(str_replace('\\', '/', $realpath), strlen(\Drupal::root() . '/' . $library_path . '/'));
}
$path_no_ext = strripos($path, $ext) === strlen($path) - $ext_len ? substr($path, 0, -$ext_len) : $path;
$path_encoded = [];
foreach (explode('/', $path_no_ext) as $path_parts) {
$path_encoded[] = urlencode($path_parts);
}
$path_encoded = implode('/', $path_encoded);
$properties[$property] = '/api/patternkit/'
. urlencode(ltrim($library_namespace ?? $library_name, '@'))
. '/'
. $path_encoded
. '?asset=schema'
. $ref;
}
return $properties;
}
}