PluginProbe
Linguise – AI Automatic Multilingual Translation / trunk
Linguise – AI Automatic Multilingual Translation vtrunk
2.2.64 2.2.63 2.2.62 2.2.61 2.2.60 2.2.59 2.2.58 2.2.57 2.2.56 2.2.55 2.2.54 2.2.53 2.2.52 2.2.51 2.2.50 2.2.49 2.2.47 2.2.48 2.2.46 2.2.45 2.2.44 2.2.43 2.2.42 1.9.7 1.9.8 All 255 releases
linguise / src / Helper.php

Helper.php in Linguise – AI Automatic Multilingual Translation trunk, at src/Helper.php

464 lines 12.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Linguise\WordPress;
4
5 defined('ABSPATH') || die('');
6
7 /**
8 * Class Helper
9 */
10 class Helper
11 {
12 /**
13 * Languages information
14 *
15 * @var null | object
16 */
17 protected static $languages_information = null;
18
19 /**
20 * Check if a request is an admin one
21 * https://florianbrinkmann.com/en/wordpress-backend-request-3815/
22 *
23 * @return boolean
24 */
25 public static function isAdminRequest()
26 {
27 $admin_url = strtolower(admin_url());
28 $referrer = strtolower(wp_get_referer());
29 $current_url = home_url(add_query_arg(null, null));
30
31 if (strpos($current_url, $admin_url) === 0) {
32 if (0 === strpos($referrer, $admin_url)) {
33 return true;
34 } else {
35 if (function_exists('wp_doing_ajax')) {
36 return !wp_doing_ajax();
37 } else {
38 // @codeCoverageIgnoreStart
39 return !(defined('DOING_AJAX') && DOING_AJAX);
40 // @codeCoverageIgnoreEnd
41 }
42 }
43 } else {
44 return false;
45 }
46 }
47
48 /**
49 * Return the visitor language from Linguise request
50 *
51 * @return string|null
52 */
53 public static function getLanguage()
54 {
55 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- View request, no action
56 if (!empty($_SERVER['HTTP_LINGUISE_ORIGINAL_LANGUAGE']) && self::isTranslatableLanguage($_SERVER['HTTP_LINGUISE_ORIGINAL_LANGUAGE'])) {
57 return $_SERVER['HTTP_LINGUISE_ORIGINAL_LANGUAGE'];
58 } elseif (!empty($_GET['linguise_language']) && self::isTranslatableLanguage($_GET['linguise_language'])) {
59 return $_GET['linguise_language'];
60 }
61 // phpcs:enable
62
63 return null;
64 }
65
66 /**
67 * Retrieve the language from referer
68 *
69 * Will parse the referer as an URL and check if it matches a translatable language
70 * If not, return null
71 *
72 * @return string|null
73 */
74 public static function getLanguageFromReferer()
75 {
76 if (!empty(wp_get_referer())) {
77 // Parse as URL
78 $language = self::getLanguageFromUrl(wp_get_referer());
79 if ($language !== null) {
80 return $language;
81 }
82 }
83
84 return null;
85 }
86
87 /**
88 * Get the language from an URL
89 *
90 * @param string $url The URL to parse
91 *
92 * @return string|null The parsed language (or null if not found)
93 */
94 public static function getLanguageFromUrl($url)
95 {
96 $path = parse_url($url, PHP_URL_PATH);
97 if (empty($path)) {
98 // Fail to parse!
99 return null;
100 }
101
102 $site_path = parse_url(linguiseGetSite(), PHP_URL_PATH);
103 if (!empty($site_path) && strpos($path, $site_path) === 0) {
104 // Remove the site path from the URL
105 $path = substr($path, strlen($site_path));
106 }
107
108 $parts = explode('/', trim($path, '/'));
109 if (!count($parts) || $parts[0] === '') {
110 return null;
111 }
112
113 $language = $parts[0];
114 if (self::isTranslatableLanguage($language)) {
115 return $language;
116 }
117
118 return null;
119 }
120
121 /**
122 * Return all languages information
123 *
124 * @return object
125 */
126 public static function getLanguagesInfos()
127 {
128 if (self::$languages_information !== null) {
129 return self::$languages_information;
130 }
131
132 $languages = file_get_contents(dirname(__FILE__) . '../../assets/languages.json');
133 self::$languages_information = json_decode($languages);
134
135 return self::$languages_information;
136 }
137
138 /**
139 * Check if the passed language is RTL
140 *
141 * @param string $language_code Language code to check
142 *
143 * @return boolean
144 */
145 public static function getLanguageIsRtl($language_code)
146 {
147 $languages = self::getLanguagesInfos();
148
149 if (isset($languages->$language_code)) {
150 return $languages->$language_code->rtl ?? false;
151 }
152
153 return false;
154 }
155
156 /**
157 * Map Linguise language to WordPress locale
158 *
159 * @param string $language Linguise language
160 *
161 * @return string|null
162 */
163 public static function mapLanguageToWordPressLocale($language)
164 {
165 $languages = self::getLanguagesInfos();
166
167 if (isset($languages->$language)) {
168 // Check if wp_code exist
169 // If not set, we use the same as $language
170 // If set and NULL we should return null
171 if (!array_key_exists('wp_code', (array)$languages->$language)) {
172 return $language;
173 }
174 if (!empty($languages->$language->wp_code)) {
175 return $languages->$language->wp_code;
176 }
177
178 return null;
179 }
180
181 return null;
182 }
183
184 /**
185 * Check if the passed language is translatable
186 *
187 * @param string $language Language code to check
188 *
189 * @return boolean
190 */
191 public static function isTranslatableLanguage($language)
192 {
193 linguiseSwitchMainSite();
194 $linguise_options = get_option('linguise_options');
195 linguiseRestoreMultisite();
196
197 if (!$linguise_options) {
198 return false;
199 }
200
201 return $language !== $linguise_options['default_language'] && in_array($language, $linguise_options['enabled_languages']);
202 }
203
204 /**
205 * Get the Linguise locale from WordPress locale
206 *
207 * @param string $locale The WordPress locale to convert
208 *
209 * @return string|null The Linguise locale or null if not found
210 */
211 public static function getLinguiseCodeFromWPLocale($locale)
212 {
213 $languages = self::getLanguagesInfos();
214 foreach ($languages as $lang_key => $language) {
215 if (isset($language->wp_code) && $language->wp_code === $locale) {
216 return $lang_key;
217 }
218
219 if (self::localeCompare($lang_key, $locale)) {
220 return $lang_key;
221 }
222 }
223 return null;
224 }
225
226 /**
227 * Safe strpos function
228 *
229 * @param string $haystack The haystack string
230 * @param string $needle The needle string
231 *
232 * @return integer The position of the needle in the haystack or the length of the haystack if
233 * the needle is not found
234 */
235 public static function ensureStrpos($haystack, $needle)
236 {
237 $pos = strpos($haystack, $needle);
238 return $pos === false ? strlen($haystack) : $pos;
239 }
240
241 /**
242 * Locale compare check with country code ignore check supported.
243 *
244 * @param string $locale The current locale being checked
245 * @param string $test_locale The locale to test against
246 *
247 * @return boolean
248 */
249 public static function localeCompare($locale, $test_locale)
250 {
251 if (empty($locale) || empty($test_locale)) {
252 return false;
253 }
254
255 // Normalize underscore and dash to a dash
256 $locale = str_replace('_', '-', $locale);
257 $test_locale = str_replace('_', '-', $test_locale);
258 if (strcasecmp($locale, $test_locale) === 0) {
259 return true;
260 }
261
262 // trim until _ or -
263 $test_locale = substr($test_locale, 0, self::ensureStrpos($test_locale, '_'));
264 $test_locale = substr($test_locale, 0, self::ensureStrpos($test_locale, '-'));
265
266 if (strcasecmp($locale, $test_locale) === 0) {
267 return true;
268 }
269
270 // trim $locale until _ or -
271 $locale = substr($locale, 0, self::ensureStrpos($locale, '_'));
272 $locale = substr($locale, 0, self::ensureStrpos($locale, '-'));
273
274 return strcasecmp($locale, $test_locale) === 0;
275 }
276
277 /**
278 * Create a URL path to our script
279 *
280 * @param string $path Path to our script
281 *
282 * @return boolean
283 */
284 public static function getScriptUrl($path)
285 {
286 // Check if path starts with /
287 if (substr($path, 0, 1) === '/') {
288 // Strip / since we want some consistency
289 $path = substr($path, 1);
290 }
291
292 // Check if LINGUISE_PLUGIN_URL has / at the end
293 if (substr(LINGUISE_PLUGIN_URL, -1) === '/') {
294 // @codeCoverageIgnoreStart
295 return LINGUISE_PLUGIN_URL . $path;
296 // @codeCoverageIgnoreEnd
297 }
298
299 return LINGUISE_PLUGIN_URL . '/' . $path;
300 }
301
302 /**
303 * Check if the request is behind Cloudflare
304 *
305 * @return boolean true if the request is behind Cloudflare
306 */
307 public static function isBehindCloudflare()
308 {
309 if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER)) {
310 return true;
311 }
312
313 return false;
314 }
315
316 /**
317 * Parse a HEX color to RGB
318 *
319 * @param string $color The HEX color to parse
320 *
321 * @return array|null The parsed color as an array with 'r', 'g', and 'b' keys, or null if invalid
322 */
323 public static function parseHexColor($color)
324 {
325 $hex_color = ltrim($color, '#');
326
327 if (strlen($hex_color) === 3) {
328 $hex_color = $hex_color[0] . $hex_color[0] . $hex_color[1] . $hex_color[1] . $hex_color[2] . $hex_color[2];
329 } elseif (strlen($hex_color) !== 6) {
330 return null;
331 }
332
333 if (!ctype_xdigit($hex_color)) {
334 return null;
335 }
336
337 $r = hexdec(substr($hex_color, 0, 2));
338 $g = hexdec(substr($hex_color, 2, 2));
339 $b = hexdec(substr($hex_color, 4, 2));
340
341 return [
342 'r' => $r,
343 'g' => $g,
344 'b' => $b,
345 ];
346 }
347
348 /**
349 * Mix and blend $color HEX code with $alpha value
350 *
351 * This will create a RGBA color from a HEX color
352 * and a alpha value
353 *
354 * @param string $color The HEX color to parse
355 * @param float $alpha The alpha value to use (0.0 to 1.0)
356 *
357 * @return string The parsed color as an RGBA string, if fails returns the original color
358 */
359 public static function mixColorAlpha($color, $alpha = 1.0)
360 {
361 $color_p = self::parseHexColor($color);
362 if ($color_p === null) {
363 return $color;
364 }
365
366 return 'rgba(' . $color_p['r'] . ', ' . $color_p['g'] . ', ' . $color_p['b'] . ', ' . $alpha . ')';
367 }
368
369 /**
370 * Check if the array is an actual object or not.
371 *
372 * @param array|object $arrOrObject The array or object to be checked
373 *
374 * @return boolean - True if it's an actual object, false if it's an array
375 */
376 public static function isActualObject($arrOrObject)
377 {
378 if (is_object($arrOrObject)) {
379 return true;
380 }
381
382 if (!is_array($arrOrObject)) {
383 // preliminary check
384 return false;
385 }
386
387 // https://stackoverflow.com/a/72949244 (PHP 7 compatible)
388 if (function_exists('array_is_list')) {
389 return array_is_list($arrOrObject) === false; // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.array_is_listFound
390 }
391
392 // @codeCoverageIgnoreStart
393 $keys = array_keys($arrOrObject);
394 return implode('', $keys) !== implode(range(0, count($keys) - 1));
395 // @codeCoverageIgnoreEnd
396 }
397
398 /**
399 * Check if the string has space or not.
400 *
401 * @param string $str The string to be checked
402 *
403 * @return boolean - True if it has space, false if it doesn't
404 */
405 public static function hasSpace($str)
406 {
407 return preg_match('/\s/', $str) > 0;
408 }
409
410
411 /**
412 * Create a new URL based on the parsed_url output
413 *
414 * Code taken from Linguise Script Core Helper
415 *
416 * @param array $parsed_url The parsed URL
417 * @param boolean $encoded Should we encode the URL or not.
418 *
419 * @return string
420 */
421 public static function buildUrl($parsed_url, $encoded = \false)
422 {
423 $final_url = '';
424 if (empty($parsed_url['scheme'])) {
425 $final_url .= '//';
426 } else {
427 $final_url .= $parsed_url['scheme'] . '://';
428 }
429
430 if (!empty($parsed_url['user'])) {
431 $final_url .= $parsed_url['user'];
432 if (!empty($parsed_url['pass'])) {
433 $final_url .= ':' . $parsed_url['pass'];
434 }
435 $final_url .= '@';
436 }
437
438 $final_url .= empty($parsed_url['host']) ? '' : $parsed_url['host'];
439
440 if (!empty($parsed_url['port'])) {
441 $final_url .= ':' . $parsed_url['port'];
442 }
443
444 if (!empty($parsed_url['path'])) {
445 if ($encoded) {
446 $explode_path = array_map('rawurlencode', explode('/', $parsed_url['path']));
447 $final_url .= implode('/', $explode_path);
448 } else {
449 $final_url .= $parsed_url['path'];
450 }
451 }
452
453 if (!empty($parsed_url['query'])) {
454 $final_url .= '?' . $parsed_url['query'];
455 }
456
457 if (!empty($parsed_url['fragment'])) {
458 $final_url .= '#' . $parsed_url['fragment'];
459 }
460
461 return $final_url;
462 }
463 }
464