*/ 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( $string, 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( $string, 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 ); } }