PluginProbe ʕ •ᴥ•ʔ
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF / 2.0.6
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF v2.0.6
2.0.7 2.0.6 2.0.5 trunk 1.3.7 1.4.0 1.4.1 1.4.2 1.4.6 1.5.0 1.5.3 1.5.6 1.5.8 1.6.5 1.6.6 1.6.9 1.7.0 1.7.4 1.8.1 1.8.2 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4
robin-image-optimizer / vendor / codeinwp / themeisle-sdk / src / Modules / Translations.php
robin-image-optimizer / vendor / codeinwp / themeisle-sdk / src / Modules Last commit date
About_us.php 1 month ago Abstract_Migration.php 4 months ago Announcements.php 4 months ago Compatibilities.php 10 months ago Crash_reporter.php 1 month ago Dashboard_widget.php 1 month ago Featured_plugins.php 1 month ago Float_widget.php 10 months ago Licenser.php 4 months ago Logger.php 1 month ago Migrator.php 1 month ago Notification.php 10 months ago Promotions.php 1 month ago Recommendation.php 10 months ago Review.php 10 months ago Rollback.php 10 months ago Script_loader.php 10 months ago Translate.php 10 months ago Translations.php 10 months ago Uninstall_feedback.php 1 month ago Welcome.php 10 months ago
Translations.php
248 lines
1 <?php
2 /**
3 * The translations model class for ThemeIsle SDK
4 *
5 * @package ThemeIsleSDK
6 * @subpackage Modules
7 * @copyright Copyright (c) 2024, Bogdan Preda
8 * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9 * @since 3.3.23
10 */
11
12 namespace ThemeisleSDK\Modules;
13
14 use ThemeisleSDK\Common\Abstract_Module;
15 use ThemeisleSDK\Product;
16
17 // Exit if accessed directly.
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22 /**
23 * Translations module for ThemeIsle SDK.
24 */
25 class Translations extends Abstract_Module {
26
27 const API_URL = 'https://translations.themeisle.com/wp-json/gpb-themeisle/';
28 const CACHE_KEY = 'ti_translations_data';
29
30 /**
31 * Check if we should load module for this.
32 *
33 * @param Product $product Product to check.
34 *
35 * @return bool Should load ?
36 */
37 public function can_load( $product ) {
38 if ( $this->is_from_partner( $product ) ) {
39 return false;
40 }
41
42 if ( $product->is_wordpress_available() ) {
43 return false;
44 }
45
46 return apply_filters( $product->get_slug() . '_sdk_enable_private_translations', false );
47 }
48
49 /**
50 * Load module logic.
51 *
52 * @param Product $product Product to load.
53 *
54 * @return Translations Module instance.
55 */
56 public function load( $product ) {
57
58 $this->product = $product;
59
60 if ( $this->product->is_plugin() ) {
61 add_filter( 'pre_set_site_transient_update_plugins', [ $this, 'add_plugin_translations' ], 11 );
62 } else {
63 add_filter( 'pre_set_site_transient_update_themes', [ $this, 'add_theme_translations' ], 11 );
64 }
65
66 add_filter( 'http_request_host_is_external', [ $this, 'allow_translations_api' ], 10, 3 );
67
68 return $this;
69 }
70
71 /**
72 * Allow external downloads for the translations API.
73 *
74 * @param bool $external Whether the host is external.
75 * @param string $host The host being checked.
76 * @param string $url The URL being checked.
77 *
78 * @return bool
79 */
80 public function allow_translations_api( $external, $host, $url ) {
81 return strpos( $url, self::API_URL ) === 0 ? true : $external;
82 }
83
84 /**
85 * Get translations from API.
86 *
87 * @return bool | array
88 */
89 private function get_api_translations() {
90 $translation_data = $this->get_translation_data();
91
92 return empty( $translation_data ) ? false : $translation_data;
93 }
94
95 /**
96 * Get translation data from API.
97 *
98 * @return array
99 */
100 private function get_translation_data() {
101 $cached = get_transient( self::CACHE_KEY );
102
103 if ( $cached ) {
104 return $cached;
105 }
106
107 $response = $this->safe_get(
108 self::API_URL . 'translations',
109 array(
110 'timeout' => 15, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout, Inherited by wp_remote_get only, for vip environment we use defaults.
111 'sslverify' => false,
112 )
113 );
114 if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
115 return [];
116 }
117
118 $data = json_decode( wp_remote_retrieve_body( $response ) );
119
120 if ( ! is_array( $data ) ) {
121 return [];
122 }
123
124 set_transient( self::CACHE_KEY, $data, 12 * HOUR_IN_SECONDS );
125
126 return $data;
127 }
128
129 /**
130 * Add translations to the transient data.
131 *
132 * @param array $_transient_data incoming transient data.
133 * @param string $type plugins or themes.
134 *
135 * @return array
136 */
137 public function add_translations( $_transient_data, $type = 'plugins' ) {
138 $translations = $this->get_api_translations();
139
140 if ( ! is_array( $translations ) ) {
141 return $_transient_data;
142 }
143
144 if ( ! isset( $_transient_data->translations ) ) {
145 return $_transient_data;
146 }
147
148 if ( ! in_array( $type, [ 'plugins', 'themes' ] ) ) {
149 return $_transient_data;
150 }
151
152 $installed_translations = wp_get_installed_translations( $type );
153
154 foreach ( $translations as $translation ) {
155 $translation = (array) $translation;
156
157
158 if ( ! $this->is_valid_translation( $translation, $type ) ) {
159 continue;
160 }
161
162 $latest_translation = strtotime( $translation['updated'] );
163
164 if ( ! is_int( $latest_translation ) ) {
165 continue;
166 }
167
168 $existing = (int) get_option( $this->get_translation_option_key( $translation ) );
169 $has_translation = isset( $installed_translations[ $translation['slug'] ][ $translation['language'] ] );
170
171 // If we already have the latest translation, skip.
172 if ( $existing >= $latest_translation && $has_translation ) {
173 continue;
174 }
175
176 $_transient_data->translations[] = $translation;
177
178 update_option( $this->get_translation_option_key( $translation ), $latest_translation );
179 }
180
181 return $_transient_data;
182 }
183
184 /**
185 * Add theme translations to the transient.
186 *
187 * @param array $_transient_data incoming transient data.
188 *
189 * @return array
190 */
191 public function add_theme_translations( $_transient_data ) {
192 return $this->add_translations( $_transient_data, 'themes' );
193 }
194
195
196 /**
197 * Add plugin translations to the transient.
198 *
199 * @param array $_transient_data The transient data.
200 *
201 * @return array
202 */
203 public function add_plugin_translations( $_transient_data ) {
204 return $this->add_translations( $_transient_data );
205 }
206
207 /**
208 * Get the option key for storing translations.
209 *
210 * @param array $translation the translation data from the API.
211 *
212 * @return string
213 */
214 private function get_translation_option_key( $translation ) {
215 return $translation['slug'] . '_translation_' . $translation['language'];
216 }
217
218 /**
219 * Check if a translation is valid and applies for the current site.
220 *
221 * @param array $translation The translation data.
222 *
223 * @return bool
224 */
225 private function is_valid_translation( $translation, $type = 'plugins' ) {
226 if ( ! isset( $translation['slug'] ) || $translation['slug'] !== $this->product->get_slug() ) {
227 return false;
228 }
229
230 $locales = apply_filters( $type . '_update_check_locales', array_values( get_available_languages() ) );
231
232 if ( ! is_array( $locales ) ) {
233 return false;
234 }
235 $locales = array_unique( $locales );
236
237 if ( ! isset( $translation['language'], $translation['updated'] ) ) {
238 return false;
239 }
240
241 if ( ! in_array( $translation['language'], $locales, true ) ) {
242 return false;
243 }
244
245 return true;
246 }
247 }
248