PluginProbe
PostNL for WooCommerce / 4.4.0
PostNL for WooCommerce v4.4.0
5.9.12 5.9.11 5.9.10 5.9.9 5.9.8 5.9.7 5.9.6 trunk 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 3.1.4 3.1.5 3.1.6 3.1.7 4.0.0 4.0.1 4.0.2 4.3.2 4.3.3 4.4.0 4.4.1 All 72 releases
woo-postnl / vendor / myparcelnl / sdk / src / Support / Str.php

Str.php in PostNL for WooCommerce 4.4.0, at vendor/myparcelnl/sdk/src/Support/Str.php

726 lines 22.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php declare(strict_types=1); /** @noinspection PhpComposerExtensionStubsInspection */
2
3 namespace MyParcelNL\Sdk\src\Support;
4
5 use Exception;
6
7 class Str
8 {
9 /**
10 * The cache of snake-cased words.
11 *
12 * @var array
13 */
14 protected static $snakeCache = [];
15
16 /**
17 * The cache of camel-cased words.
18 *
19 * @var array
20 */
21 protected static $camelCache = [];
22
23 /**
24 * The cache of studly-cased words.
25 *
26 * @var array
27 */
28 protected static $studlyCache = [];
29
30 /**
31 * Return the remainder of a string after a given value.
32 *
33 * @param string $subject
34 * @param string $search
35 * @return string
36 */
37 public static function after($subject, $search)
38 {
39 return $search === '' ? $subject : array_reverse(explode($search, $subject, 2))[0];
40 }
41
42 /**
43 * Transliterate a UTF-8 value to ASCII.
44 *
45 * @param string $value
46 * @param string $language
47 * @return string
48 */
49 public static function ascii($value, $language = 'en')
50 {
51 $languageSpecific = static::languageSpecificCharsArray($language);
52
53 if (! is_null($languageSpecific)) {
54 $value = str_replace($languageSpecific[0], $languageSpecific[1], $value);
55 }
56
57 foreach (static::charsArray() as $key => $val) {
58 $value = str_replace($val, $key, $value);
59 }
60
61 return preg_replace('/[^\x20-\x7E]/u', '', $value);
62 }
63
64 /**
65 * Get the portion of a string before a given value.
66 *
67 * @param string $subject
68 * @param string $search
69 * @return string
70 */
71 public static function before($subject, $search)
72 {
73 return $search === '' ? $subject : explode($search, $subject)[0];
74 }
75
76 /**
77 * Convert a value to camel case.
78 *
79 * @param string $value
80 * @return string
81 */
82 public static function camel($value)
83 {
84 if (isset(static::$camelCache[$value])) {
85 return static::$camelCache[$value];
86 }
87
88 return static::$camelCache[$value] = lcfirst(static::studly($value));
89 }
90
91 /**
92 * Determine if a given string contains a given substring.
93 *
94 * @param string $haystack
95 * @param string|array $needles
96 * @return bool
97 */
98 public static function contains($haystack, $needles)
99 {
100 foreach ((array) $needles as $needle) {
101 if ($needle !== '' && mb_strpos($haystack, $needle) !== false) {
102 return true;
103 }
104 }
105
106 return false;
107 }
108
109 /**
110 * Determine if a given string ends with a given substring.
111 *
112 * @param string $haystack
113 * @param string|array $needles
114 * @return bool
115 */
116 public static function endsWith($haystack, $needles)
117 {
118 foreach ((array) $needles as $needle) {
119 if (substr($haystack, -strlen($needle)) === (string) $needle) {
120 return true;
121 }
122 }
123
124 return false;
125 }
126
127 /**
128 * Cap a string with a single instance of a given value.
129 *
130 * @param string $value
131 * @param string $cap
132 * @return string
133 */
134 public static function finish($value, $cap)
135 {
136 $quoted = preg_quote($cap, '/');
137
138 return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
139 }
140
141 /**
142 * Determine if a given string matches a given pattern.
143 *
144 * @param string|array $pattern
145 * @param string $value
146 * @return bool
147 */
148 public static function is($pattern, $value)
149 {
150 $patterns = Arr::wrap($pattern);
151
152 if (empty($patterns)) {
153 return false;
154 }
155
156 foreach ($patterns as $pattern) {
157 // If the given value is an exact match we can of course return true right
158 // from the beginning. Otherwise, we will translate asterisks and do an
159 // actual pattern match against the two strings to see if they match.
160 if ($pattern == $value) {
161 return true;
162 }
163
164 $pattern = preg_quote($pattern, '#');
165
166 // Asterisks are translated into zero-or-more regular expression wildcards
167 // to make it convenient to check if the strings starts with the given
168 // pattern such as "library/*", making any string check convenient.
169 $pattern = str_replace('\*', '.*', $pattern);
170
171 if (preg_match('#^'.$pattern.'\z#u', $value) === 1) {
172 return true;
173 }
174 }
175
176 return false;
177 }
178
179 /**
180 * Convert a string to kebab case.
181 *
182 * @param string $value
183 * @return string
184 */
185 public static function kebab($value)
186 {
187 return static::snake($value, '-');
188 }
189
190 /**
191 * Return the length of the given string.
192 *
193 * @param string $value
194 * @param string $encoding
195 * @return int
196 */
197 public static function length($value, $encoding = null)
198 {
199 if ($encoding) {
200 return mb_strlen($value, $encoding);
201 }
202
203 return mb_strlen($value);
204 }
205
206 /**
207 * Limit the number of characters in a string.
208 *
209 * @param string $value
210 * @param int $limit
211 * @param string $end
212 * @return string
213 */
214 public static function limit($value, $limit = 100, $end = '...')
215 {
216 if (mb_strwidth($value, 'UTF-8') <= $limit) {
217 return $value;
218 }
219
220 return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end;
221 }
222
223 /**
224 * Convert the given string to lower-case.
225 *
226 * @param string $value
227 * @return string
228 */
229 public static function lower($value)
230 {
231 return mb_strtolower($value, 'UTF-8');
232 }
233
234 /**
235 * Limit the number of words in a string.
236 *
237 * @param string $value
238 * @param int $words
239 * @param string $end
240 * @return string
241 */
242 public static function words($value, $words = 100, $end = '...')
243 {
244 preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
245
246 if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) {
247 return $value;
248 }
249
250 return rtrim($matches[0]).$end;
251 }
252
253 /**
254 * Parse a [email protected] style callback into class and method.
255 *
256 * @param string $callback
257 * @param string|null $default
258 * @return array
259 */
260 public static function parseCallback($callback, $default = null)
261 {
262 return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
263 }
264
265 /**
266 * Get the plural form of an English word.
267 *
268 * @deprecated Not implemented
269 * @return string
270 * @throws Exception
271 */
272 public static function plural()
273 {
274 throw new Exception('Not implemented');
275 }
276
277 /**
278 * Generate a more truly "random" alpha-numeric string.
279 *
280 * @param int $length
281 * @return string
282 * @throws Exception
283 */
284 public static function random($length = 16)
285 {
286 $string = '';
287
288 while (($len = strlen($string)) < $length) {
289 $size = $length - $len;
290
291 $bytes = random_bytes($size);
292
293 $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
294 }
295
296 return $string;
297 }
298
299 /**
300 * Replace a given value in the string sequentially with an array.
301 *
302 * @param string $search
303 * @param array $replace
304 * @param string $subject
305 * @return string
306 */
307 public static function replaceArray($search, array $replace, $subject)
308 {
309 foreach ($replace as $value) {
310 $subject = static::replaceFirst($search, $value, $subject);
311 }
312
313 return $subject;
314 }
315
316 /**
317 * Replace the first occurrence of a given value in the string.
318 *
319 * @param string $search
320 * @param string $replace
321 * @param string $subject
322 * @return string
323 */
324 public static function replaceFirst($search, $replace, $subject)
325 {
326 if ($search == '') {
327 return $subject;
328 }
329
330 $position = strpos($subject, $search);
331
332 if ($position !== false) {
333 return substr_replace($subject, $replace, $position, strlen($search));
334 }
335
336 return $subject;
337 }
338
339 /**
340 * Replace the last occurrence of a given value in the string.
341 *
342 * @param string $search
343 * @param string $replace
344 * @param string $subject
345 * @return string
346 */
347 public static function replaceLast($search, $replace, $subject)
348 {
349 $position = strrpos($subject, $search);
350
351 if ($position !== false) {
352 return substr_replace($subject, $replace, $position, strlen($search));
353 }
354
355 return $subject;
356 }
357
358 /**
359 * Begin a string with a single instance of a given value.
360 *
361 * @param string $value
362 * @param string $prefix
363 * @return string
364 */
365 public static function start($value, $prefix)
366 {
367 $quoted = preg_quote($prefix, '/');
368
369 return $prefix.preg_replace('/^(?:'.$quoted.')+/u', '', $value);
370 }
371
372 /**
373 * Convert the given string to upper-case.
374 *
375 * @param string $value
376 * @return string
377 */
378 public static function upper($value)
379 {
380 return mb_strtoupper($value, 'UTF-8');
381 }
382
383 /**
384 * Convert the given string to title case.
385 *
386 * @param string $value
387 * @return string
388 */
389 public static function title($value)
390 {
391 return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
392 }
393
394 /**
395 * Get the singular form of an English word.
396 *
397 * @deprecated Not implemented
398 * @return string
399 * @throws Exception
400 */
401 public static function singular()
402 {
403 throw new Exception('Not implemented');
404 }
405
406 /**
407 * Generate a URL friendly "slug" from a given string.
408 *
409 * @param string $title
410 * @param string $separator
411 * @param string $language
412 * @return string
413 */
414 public static function slug($title, $separator = '-', $language = 'en')
415 {
416 $title = static::ascii($title, $language);
417
418 // Convert all dashes/underscores into separator
419 $flip = $separator == '-' ? '_' : '-';
420
421 $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);
422
423 // Replace @ with the word 'at'
424 $title = str_replace('@', $separator.'at'.$separator, $title);
425
426 // Remove all characters that are not the separator, letters, numbers, or whitespace.
427 $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title));
428
429 // Replace all separator characters and whitespace by a single separator
430 $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
431
432 return trim($title, $separator);
433 }
434
435 /**
436 * Convert a string to snake case.
437 *
438 * @param string $value
439 * @param string $delimiter
440 * @return string
441 */
442 public static function snake($value, $delimiter = '_')
443 {
444 $key = $value;
445
446 if (isset(static::$snakeCache[$key][$delimiter])) {
447 return static::$snakeCache[$key][$delimiter];
448 }
449
450 if (! ctype_lower($value)) {
451 $value = preg_replace('/\s+/u', '', ucwords($value));
452
453 $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
454 }
455
456 return static::$snakeCache[$key][$delimiter] = $value;
457 }
458
459 /**
460 * Determine if a given string starts with a given substring.
461 *
462 * @param string $haystack
463 * @param string|array $needles
464 * @return bool
465 */
466 public static function startsWith($haystack, $needles)
467 {
468 foreach ((array) $needles as $needle) {
469 if ($needle !== '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
470 return true;
471 }
472 }
473
474 return false;
475 }
476
477 /**
478 * Convert a value to studly caps case.
479 *
480 * @param string $value
481 * @return string
482 */
483 public static function studly($value)
484 {
485 $key = $value;
486
487 if (isset(static::$studlyCache[$key])) {
488 return static::$studlyCache[$key];
489 }
490
491 $value = ucwords(str_replace(['-', '_'], ' ', $value));
492
493 return static::$studlyCache[$key] = str_replace(' ', '', $value);
494 }
495
496 /**
497 * Returns the portion of string specified by the start and length parameters.
498 *
499 * @param string $string
500 * @param int $start
501 * @param int|null $length
502 * @return string
503 */
504 public static function substr($string, $start, $length = null)
505 {
506 return mb_substr($string, $start, $length, 'UTF-8');
507 }
508
509 /**
510 * Make a string's first character uppercase.
511 *
512 * @param string $string
513 * @return string
514 */
515 public static function ucfirst($string)
516 {
517 return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
518 }
519
520 /**
521 * Generate a UUID (version 4).
522 *
523 * @deprecated Not implemented
524 * @throws Exception
525 */
526 public static function uuid()
527 {
528 throw new Exception('Not implemented');
529 }
530
531 /**
532 * Generate a time-ordered UUID (version 4).
533 *
534 * @deprecated Not implemented
535 * @throws Exception
536 */
537 public static function orderedUuid()
538 {
539 throw new Exception('Not implemented');
540 }
541
542 /**
543 * Returns the replacements for the ascii method.
544 *
545 * Note: Adapted from Stringy\Stringy.
546 *
547 * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt
548 *
549 * @return array
550 */
551 protected static function charsArray()
552 {
553 static $charsArray;
554
555 if (isset($charsArray)) {
556 return $charsArray;
557 }
558
559 return $charsArray = [
560 '0' => ['°', '₀', '۰', '0'],
561 '1' => ['¹', '₁', '۱', '1'],
562 '2' => ['²', '₂', '۲', '2'],
563 '3' => ['³', '₃', '۳', '3'],
564 '4' => ['⁴', '₄', '۴', '٤', '4'],
565 '5' => ['⁵', '�
566 ', '۵', '٥', '5'],
567 '6' => ['⁶', '₆', '۶', '٦', '6'],
568 '7' => ['⁷', '₇', '۷', '7'],
569 '8' => ['⁸', '₈', '۸', '8'],
570 '9' => ['⁹', '₉', '۹', '9'],
571 'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', '�
572 ', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', '�
573 ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', '�
574 ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', '�
575 ', 'ا', 'a', 'ä'],
576 'b' => ['б', 'β', 'ب', 'ဗ', 'ბ', 'b'],
577 'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ', 'c'],
578 'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ', 'd'],
579 'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', '�
580 ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ', '�
581 '],
582 'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ', 'f'],
583 'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ', 'g'],
584 'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ', 'h'],
585 'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ', 'ی', 'i'],
586 'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج', 'j'],
587 'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک', 'k'],
588 'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ', 'l'],
589 'm' => ['м', 'μ', '�
590 ', 'မ', 'მ', 'm'],
591 'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ', 'n'],
592 'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', '�
593 ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ', 'o', 'ö'],
594 'p' => ['п', 'π', 'ပ', 'პ', 'پ', 'p'],
595 'q' => ['ყ', 'q'],
596 'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ', 'r'],
597 's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', '�
598 ', 'ſ', 'ს', 's'],
599 't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ', 't'],
600 'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ', 'u', 'ў', 'ü'],
601 'v' => ['в', 'ვ', 'ϐ', 'v'],
602 'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ', 'w'],
603 'x' => ['χ', 'ξ', 'x'],
604 'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', '�
605 ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ', 'y'],
606 'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ', 'z'],
607 'aa' => ['ع', 'आ', 'آ'],
608 'ae' => ['æ', 'ǽ'],
609 'ai' => ['ऐ'],
610 'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
611 'dj' => ['ђ', 'đ'],
612 'dz' => ['џ', 'ძ'],
613 'ei' => ['ऍ'],
614 'gh' => ['غ', 'ღ'],
615 'ii' => ['ई'],
616 'ij' => ['ij'],
617 'kh' => ['�
618 ', 'خ', 'ხ'],
619 'lj' => ['љ'],
620 'nj' => ['њ'],
621 'oe' => ['ö', 'œ', 'ؤ'],
622 'oi' => ['ऑ'],
623 'oii' => ['ऒ'],
624 'ps' => ['ψ'],
625 'sh' => ['ш', 'შ', 'ش'],
626 'shch' => ['щ'],
627 'ss' => ['ß'],
628 'sx' => ['ŝ'],
629 'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
630 'ts' => ['ц', 'ც', 'წ'],
631 'ue' => ['ü'],
632 'uu' => ['ऊ'],
633 'ya' => ['я'],
634 'yu' => ['ю'],
635 'zh' => ['ж', 'ჟ', 'ژ'],
636 '(c)' => ['©'],
637 'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', '�
638 ', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ', 'A', 'Ä'],
639 'B' => ['Б', 'Β', 'ब', 'B'],
640 'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ', 'C'],
641 'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', '�
642 ', 'ᴆ', 'Д', 'Δ', 'D'],
643 'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə', 'E'],
644 'F' => ['Ф', 'Φ', 'F'],
645 'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ', 'G'],
646 'H' => ['Η', 'Ή', 'Ħ', 'H'],
647 'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ', 'I'],
648 'J' => ['J'],
649 'K' => ['К', 'Κ', 'K'],
650 'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल', 'L'],
651 'M' => ['М', 'Μ', 'M'],
652 'N' => ['Ń', 'Ñ', 'Ň', '�
653 ', 'Ŋ', 'Н', 'Ν', 'N'],
654 'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ', 'O', 'Ö'],
655 'P' => ['П', 'Π', 'P'],
656 'Q' => ['Q'],
657 'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ', 'R'],
658 'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ', 'S'],
659 'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ', 'T'],
660 'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ', 'U', 'Ў', 'Ü'],
661 'V' => ['В', 'V'],
662 'W' => ['Ω', 'Ώ', 'Ŵ', 'W'],
663 'X' => ['Χ', 'Ξ', 'X'],
664 'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ', 'Y'],
665 'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ', 'Z'],
666 'AE' => ['Æ', 'Ǽ'],
667 'Ch' => ['Ч'],
668 'Dj' => ['Ђ'],
669 'Dz' => ['Џ'],
670 'Gx' => ['Ĝ'],
671 'Hx' => ['Ĥ'],
672 'Ij' => ['IJ'],
673 'Jx' => ['Ĵ'],
674 'Kh' => ['Х'],
675 'Lj' => ['Љ'],
676 'Nj' => ['Њ'],
677 'Oe' => ['Œ'],
678 'Ps' => ['Ψ'],
679 'Sh' => ['Ш'],
680 'Shch' => ['Щ'],
681 'Ss' => ['ẞ'],
682 'Th' => ['Þ'],
683 'Ts' => ['Ц'],
684 'Ya' => ['Я'],
685 'Yu' => ['Ю'],
686 'Zh' => ['Ж'],
687 ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80", "\xEF\xBE\xA0"],
688 ];
689 }
690
691 /**
692 * Returns the language specific replacements for the ascii method.
693 *
694 * Note: Adapted from Stringy\Stringy.
695 *
696 * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt
697 *
698 * @param string $language
699 * @return array|null
700 */
701 protected static function languageSpecificCharsArray($language)
702 {
703 static $languageSpecific;
704
705 if (! isset($languageSpecific)) {
706 $languageSpecific = [
707 'bg' => [
708 ['�
709 ', 'Х', 'щ', 'Щ', 'ъ', 'Ъ', 'ь', 'Ь'],
710 ['h', 'H', 'sht', 'SHT', 'a', 'А', 'y', 'Y'],
711 ],
712 'de' => [
713 ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'],
714 ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'],
715 ],
716 ];
717 }
718
719 if (isset($languageSpecific[$language])) {
720 return $languageSpecific[$language];
721 }
722
723 return null;
724 }
725 }
726