-
Notifications
You must be signed in to change notification settings - Fork 52
/
JsonSchemaExtractor.php
185 lines (154 loc) · 4.76 KB
/
JsonSchemaExtractor.php
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<?php
namespace WP_CLI\I18n;
use Gettext\Extractors\Extractor;
use Gettext\Translations;
use WP_CLI;
use WP_CLI\Utils;
class JsonSchemaExtractor extends Extractor {
use IterableCodeExtractor;
/**
* Source URL from which to download the latest theme-i18n.json file.
*
* @var string
*/
const THEME_JSON_SOURCE = 'https://develop.svn.wordpress.org/trunk/src/wp-includes/theme-i18n.json';
/**
* Fallback theme-18n.json file path.
*
* @var string
*/
const THEME_JSON_FALLBACK = __DIR__ . '/../assets/theme-i18n.json';
/**
* Source URL from which to download the latest block-i18n.json file.
*
* @var string
*/
const BLOCK_JSON_SOURCE = 'https://develop.svn.wordpress.org/trunk/src/wp-includes/block-i18n.json';
/**
* Fallback block-18n.json file path.
*
* @var string
*/
const BLOCK_JSON_FALLBACK = __DIR__ . '/../assets/block-i18n.json';
/**
* Static cache for the remote schema files.
*
* @var array<string, string>
*/
protected static $schema_cache = [];
/**
* Load the i18n from a remote URL or fall back to a local schema in case of an error.
* @param string $schema i18n schema URL.
* @param string $fallback Fallback i18n schema JSON file.
* @return array|mixed
*/
protected static function load_schema( $schema, $fallback ) {
if ( ! empty( self::$schema_cache[ $schema ] ) ) {
return self::$schema_cache[ $schema ];
}
$json = self::remote_get( $schema );
if ( empty( $json ) ) {
WP_CLI::debug( 'Remote file could not be accessed, will use local file as fallback', 'make-pot' );
$json = file_get_contents( $fallback );
}
$file_structure = json_decode( $json, false );
if ( JSON_ERROR_NONE !== json_last_error() ) {
WP_CLI::debug( 'Error when decoding theme-i18n.json file', 'make-pot' );
return [];
}
if ( ! is_object( $file_structure ) ) {
return [];
}
self::$schema_cache[ $schema ] = $file_structure;
return $file_structure;
}
/**
* @inheritdoc
*/
public static function fromString( $text, Translations $translations, array $options = [] ) {
$file = $options['file'];
WP_CLI::debug( "Parsing file {$file}", 'make-pot' );
$schema = self::load_schema( $options['schema'], $options['schemaFallback'] );
$json = json_decode( $text, true );
if ( null === $json ) {
WP_CLI::debug(
sprintf(
'Could not parse file %1$s: error code %2$s',
$file,
json_last_error()
),
'make-pot'
);
return;
}
self::extract_strings_using_i18n_schema(
$translations,
$options['addReferences'] ? $file : null,
$schema,
$json
);
}
/**
* Extract strings from a JSON file using its i18n schema.
*
* @param Translations $translations The translations instance to append the new translations.
* @param string|null $file JSON file name or null if no reference should be added.
* @param string|string[]|array[]|object $i18n_schema I18n schema for the setting.
* @param string|string[]|array[] $settings Value for the settings.
*
* @return void
*/
private static function extract_strings_using_i18n_schema( Translations $translations, $file, $i18n_schema, $settings ) {
if ( empty( $i18n_schema ) || empty( $settings ) ) {
return;
}
if ( is_string( $i18n_schema ) && is_string( $settings ) ) {
$translation = $translations->insert( $i18n_schema, $settings );
if ( $file ) {
$translation->addReference( $file );
}
return;
}
if ( is_array( $i18n_schema ) && is_array( $settings ) ) {
foreach ( $settings as $value ) {
self::extract_strings_using_i18n_schema( $translations, $file, $i18n_schema[0], $value );
}
}
if ( is_object( $i18n_schema ) && is_array( $settings ) ) {
$group_key = '*';
foreach ( $settings as $key => $value ) {
if ( isset( $i18n_schema->$key ) ) {
self::extract_strings_using_i18n_schema( $translations, $file, $i18n_schema->$key, $value );
} elseif ( isset( $i18n_schema->$group_key ) ) {
self::extract_strings_using_i18n_schema( $translations, $file, $i18n_schema->$group_key, $value );
}
}
}
}
/**
* Given a remote URL, fetches it remotely and returns its content.
*
* Returns an empty string in case of error.
*
* @param string $url URL of the file to fetch.
*
* @return string Contents of the file.
*/
private static function remote_get( $url ) {
if ( ! $url ) {
return '';
}
$headers = [ 'Content-type: application/json' ];
$options = [ 'halt_on_error' => false ];
$response = Utils\http_request( 'GET', $url, null, $headers, $options );
if (
! $response->success
|| 200 > (int) $response->status_code
|| 300 <= (int) $response->status_code
) {
WP_CLI::debug( "Failed to download from URL {$url}", 'make-pot' );
return '';
}
return trim( $response->body );
}
}