PluginProbe
FluentSMTP – WP Mail SMTP Plugin with Amazon SES, SendGrid, Mailgun, Postmark, Cloudflare, toSend, Gmail and Any SMTP / trunk
FluentSMTP – WP Mail SMTP Plugin with Amazon SES, SendGrid, Mailgun, Postmark, Cloudflare, toSend, Gmail and Any SMTP vtrunk
2.4.0 trunk 1.0.1 1.1.0 1.1.1 1.2.0 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.71 2.2.72 2.2.73 2.2.80 2.2.81 All 32 releases
fluent-smtp / includes / Support / Str.php

Str.php in FluentSMTP – WP Mail SMTP Plugin with Amazon SES, SendGrid, Mailgun, Postmark, Cloudflare, toSend, Gmail and Any SMTP trunk, at includes/Support/Str.php

582 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentMail\Includes\Support;
4
5 use FluentMail\Includes\Support\MacroableTrait;
6
7 class Str {
8
9 use MacroableTrait;
10
11 /**
12 * The cache of snake-cased words.
13 *
14 * @var array
15 */
16 protected static $snakeCache = [];
17
18 /**
19 * The cache of camel-cased words.
20 *
21 * @var array
22 */
23 protected static $camelCache = [];
24
25 /**
26 * The cache of studly-cased words.
27 *
28 * @var array
29 */
30 protected static $studlyCache = [];
31
32 /**
33 * Transliterate a UTF-8 value to ASCII.
34 *
35 * @param string $value
36 * @return string
37 */
38 public static function ascii($value)
39 {
40 foreach (static::charsArray() as $key => $val) {
41 $value = str_replace($val, $key, $value);
42 }
43
44 return preg_replace('/[^\x20-\x7E]/u', '', $value);
45 }
46
47 /**
48 * Convert a value to camel case.
49 *
50 * @param string $value
51 * @return string
52 */
53 public static function camel($value)
54 {
55 if (isset(static::$camelCache[$value])) {
56 return static::$camelCache[$value];
57 }
58
59 return static::$camelCache[$value] = lcfirst(static::studly($value));
60 }
61
62 /**
63 * Determine if a given string contains a given substring.
64 *
65 * @param string $haystack
66 * @param string|array $needles
67 * @return bool
68 */
69 public static function contains($haystack, $needles)
70 {
71 foreach ((array) $needles as $needle) {
72 if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
73 return true;
74 }
75 }
76
77 return false;
78 }
79
80 /**
81 * Determine if a given string ends with a given substring.
82 *
83 * @param string $haystack
84 * @param string|array $needles
85 * @return bool
86 */
87 public static function endsWith($haystack, $needles)
88 {
89 foreach ((array) $needles as $needle) {
90 if (substr($haystack, -strlen($needle)) === (string) $needle) {
91 return true;
92 }
93 }
94
95 return false;
96 }
97
98 /**
99 * Cap a string with a single instance of a given value.
100 *
101 * @param string $value
102 * @param string $cap
103 * @return string
104 */
105 public static function finish($value, $cap)
106 {
107 $quoted = preg_quote($cap, '/');
108
109 return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
110 }
111
112 /**
113 * Determine if a given string matches a given pattern.
114 *
115 * @param string $pattern
116 * @param string $value
117 * @return bool
118 */
119 public static function is($pattern, $value)
120 {
121 if ($pattern == $value) {
122 return true;
123 }
124
125 $pattern = preg_quote($pattern, '#');
126
127 // Asterisks are translated into zero-or-more regular expression wildcards
128 // to make it convenient to check if the strings starts with the given
129 // pattern such as "library/*", making any string check convenient.
130 $pattern = str_replace('\*', '.*', $pattern);
131
132 return (bool) preg_match('#^'.$pattern.'\z#u', $value);
133 }
134
135 /**
136 * Return the length of the given string.
137 *
138 * @param string $value
139 * @return int
140 */
141 public static function length($value)
142 {
143 return mb_strlen($value);
144 }
145
146 /**
147 * Limit the number of characters in a string.
148 *
149 * @param string $value
150 * @param int $limit
151 * @param string $end
152 * @return string
153 */
154 public static function limit($value, $limit = 100, $end = '...')
155 {
156 if (mb_strwidth($value, 'UTF-8') <= $limit) {
157 return $value;
158 }
159
160 return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end;
161 }
162
163 /**
164 * Convert the given string to lower-case.
165 *
166 * @param string $value
167 * @return string
168 */
169 public static function lower($value)
170 {
171 return mb_strtolower($value, 'UTF-8');
172 }
173
174 /**
175 * Limit the number of words in a string.
176 *
177 * @param string $value
178 * @param int $words
179 * @param string $end
180 * @return string
181 */
182 public static function words($value, $words = 100, $end = '...')
183 {
184 preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
185
186 if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) {
187 return $value;
188 }
189
190 return rtrim($matches[0]).$end;
191 }
192
193 /**
194 * Parse a Class@method style callback into class and method.
195 *
196 * @param string $callback
197 * @param string $default
198 * @return array
199 */
200 public static function parseCallback($callback, $default)
201 {
202 return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
203 }
204
205 /**
206 * Generate a more truly "random" alpha-numeric string.
207 *
208 * @param int $length
209 * @return string
210 */
211 public static function random($length = 16)
212 {
213 $string = '';
214
215 while (($len = strlen($string)) < $length) {
216 $size = $length - $len;
217
218 $bytes = random_bytes($size);
219
220 $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
221 }
222
223 return $string;
224 }
225
226 /**
227 * Generate a "random" alpha-numeric string.
228 *
229 * Should not be considered sufficient for cryptography, etc.
230 *
231 * @deprecated since version 5.3. Use the "random" method directly.
232 *
233 * @param int $length
234 * @return string
235 */
236 public static function quickRandom($length = 16)
237 {
238 if (PHP_MAJOR_VERSION > 5) {
239 return static::random($length);
240 }
241
242 $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
243
244 return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
245 }
246
247 /**
248 * Replace a given value in the string sequentially with an array.
249 *
250 * @param string $search
251 * @param array $replace
252 * @param string $subject
253 * @return string
254 */
255 public static function replaceArray($search, array $replace, $subject)
256 {
257 foreach ($replace as $value) {
258 $subject = static::replaceFirst($search, $value, $subject);
259 }
260
261 return $subject;
262 }
263
264 /**
265 * Replace the first occurrence of a given value in the string.
266 *
267 * @param string $search
268 * @param string $replace
269 * @param string $subject
270 * @return string
271 */
272 public static function replaceFirst($search, $replace, $subject)
273 {
274 $position = strpos($subject, $search);
275
276 if ($position !== false) {
277 return substr_replace($subject, $replace, $position, strlen($search));
278 }
279
280 return $subject;
281 }
282
283 /**
284 * Replace the last occurrence of a given value in the string.
285 *
286 * @param string $search
287 * @param string $replace
288 * @param string $subject
289 * @return string
290 */
291 public static function replaceLast($search, $replace, $subject)
292 {
293 $position = strrpos($subject, $search);
294
295 if ($position !== false) {
296 return substr_replace($subject, $replace, $position, strlen($search));
297 }
298
299 return $subject;
300 }
301
302 /**
303 * Convert the given string to upper-case.
304 *
305 * @param string $value
306 * @return string
307 */
308 public static function upper($value)
309 {
310 return mb_strtoupper($value, 'UTF-8');
311 }
312
313 /**
314 * Convert the given string to title case.
315 *
316 * @param string $value
317 * @return string
318 */
319 public static function title($value)
320 {
321 return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
322 }
323
324 /**
325 * Generate a URL friendly "slug" from a given string.
326 *
327 * @param string $title
328 * @param string $separator
329 * @return string
330 */
331 public static function slug($title, $separator = '-')
332 {
333 $title = static::ascii($title);
334
335 // Convert all dashes/underscores into separator
336 $flip = $separator == '-' ? '_' : '-';
337
338 $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);
339
340 // Remove all characters that are not the separator, letters, numbers, or whitespace.
341 $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title));
342
343 // Replace all separator characters and whitespace by a single separator
344 $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
345
346 return trim($title, $separator);
347 }
348
349 /**
350 * Convert a string to snake case.
351 *
352 * @param string $value
353 * @param string $delimiter
354 * @return string
355 */
356 public static function snake($value, $delimiter = '_')
357 {
358 $key = $value;
359
360 if (isset(static::$snakeCache[$key][$delimiter])) {
361 return static::$snakeCache[$key][$delimiter];
362 }
363
364 if (! ctype_lower($value)) {
365 $value = preg_replace('/\s+/u', '', $value);
366
367 $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
368 }
369
370 return static::$snakeCache[$key][$delimiter] = $value;
371 }
372
373 /**
374 * Determine if a given string starts with a given substring.
375 *
376 * @param string $haystack
377 * @param string|array $needles
378 * @return bool
379 */
380 public static function startsWith($haystack, $needles)
381 {
382 foreach ((array) $needles as $needle) {
383 if ($needle != '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
384 return true;
385 }
386 }
387
388 return false;
389 }
390
391 /**
392 * Convert a value to studly caps case.
393 *
394 * @param string $value
395 * @return string
396 */
397 public static function studly($value)
398 {
399 $key = $value;
400
401 if (isset(static::$studlyCache[$key])) {
402 return static::$studlyCache[$key];
403 }
404
405 $value = ucwords(str_replace(['-', '_'], ' ', $value));
406
407 return static::$studlyCache[$key] = str_replace(' ', '', $value);
408 }
409
410 /**
411 * Returns the portion of string specified by the start and length parameters.
412 *
413 * @param string $string
414 * @param int $start
415 * @param int|null $length
416 * @return string
417 */
418 public static function substr($string, $start, $length = null)
419 {
420 return mb_substr($string, $start, $length, 'UTF-8');
421 }
422
423 /**
424 * Make a string's first character uppercase.
425 *
426 * @param string $string
427 * @return string
428 */
429 public static function ucfirst($string)
430 {
431 return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
432 }
433
434 /**
435 * Returns the replacements for the ascii method.
436 *
437 * Note: Adapted from Stringy\Stringy.
438 *
439 * @see https://github.com/danielstjules/Stringy/blob/2.3.1/LICENSE.txt
440 *
441 * @return array
442 */
443 protected static function charsArray()
444 {
445 static $charsArray;
446
447 if (isset($charsArray)) {
448 return $charsArray;
449 }
450
451 return $charsArray = [
452 '0' => ['°', '', '۰'],
453 '1' => ['¹', '', '۱'],
454 '2' => ['²', '', '۲'],
455 '3' => ['³', '', '۳'],
456 '4' => ['', '', '۴', '٤'],
457 '5' => ['⁵', '�
458 ', '۵', '٥'],
459 '6' => ['', '', '۶', '٦'],
460 '7' => ['', '', '۷'],
461 '8' => ['', '', '۸'],
462 '9' => ['', '', '۹'],
463 'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', '�
464 ', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', '�
465 ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', '�
466 ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', '�
467 ', 'ا'],
468 'b' => ['б', 'β', 'Ъ', 'Ь', 'ب', '', ''],
469 'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
470 'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', '', '', '', 'д', 'δ', 'د', 'ض', '', '', ''],
471 'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', '�
472 ', '', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', '', '', '', '', '', '', '', 'έ', 'е', 'ё', 'э', 'є', 'ə', '', '', '', '', '', 'إ', 'ئ'],
473 'f' => ['ф', 'φ', 'ف', 'ƒ', ''],
474 'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', '', '', 'گ'],
475 'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', '', '', ''],
476 'i' => ['í', 'ì', '', 'ĩ', '', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', '', '', '', '', '', '', '', '', '', 'ί', '', '', '', 'ΐ', '', '', 'і', 'ї', 'и', '', '', '', 'ည်', 'ǐ', '', ''],
477 'j' => ['ĵ', 'ј', 'Ј', '', 'ج'],
478 'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', '', '', 'ک'],
479 'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', '', ''],
480 'm' => ['м', 'μ', '�
481 ', '', ''],
482 'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', '', ''],
483 'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', '�
484 ', '', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', '', ''],
485 'p' => ['п', 'π', '', '', 'پ'],
486 'q' => [''],
487 'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', ''],
488 's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', '�
489 ', 'ſ', ''],
490 't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', '', '', 'ŧ', '', ''],
491 'u' => ['ú', 'ù', '', 'ũ', '', 'ư', '', '', '', '', '', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', '', '', '', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', '', ''],
492 'v' => ['в', '', 'ϐ'],
493 'w' => ['ŵ', 'ω', 'ώ', '', ''],
494 'x' => ['χ', 'ξ'],
495 'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', '�
496 ', 'ϋ', 'ύ', 'ΰ', 'ي', ''],
497 'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', '', ''],
498 'aa' => ['ع', '', 'آ'],
499 'ae' => ['ä', 'æ', 'ǽ'],
500 'ai' => [''],
501 'at' => ['@'],
502 'ch' => ['ч', '', '', 'چ'],
503 'dj' => ['ђ', 'đ'],
504 'dz' => ['џ', ''],
505 'ei' => [''],
506 'gh' => ['غ', ''],
507 'ii' => [''],
508 'ij' => ['ij'],
509 'kh' => ['�
510 ', 'خ', ''],
511 'lj' => ['љ'],
512 'nj' => ['њ'],
513 'oe' => ['ö', 'œ', 'ؤ'],
514 'oi' => [''],
515 'oii' => [''],
516 'ps' => ['ψ'],
517 'sh' => ['ш', '', 'ش'],
518 'shch' => ['щ'],
519 'ss' => ['ß'],
520 'sx' => ['ŝ'],
521 'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
522 'ts' => ['ц', '', ''],
523 'ue' => ['ü'],
524 'uu' => [''],
525 'ya' => ['я'],
526 'yu' => ['ю'],
527 'zh' => ['ж', '', 'ژ'],
528 '(c)' => ['©'],
529 'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', '�
530 ', 'Ā', 'Ą', 'Α', 'Ά', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'Ά', '', 'А', 'Ǻ', 'Ǎ'],
531 'B' => ['Б', 'Β', ''],
532 'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
533 'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', '�
534 ', '', 'Д', 'Δ'],
535 'E' => ['É', 'È', '', '', '', 'Ê', '', '', '', '', '', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', '', '', '', '', '', '', 'Έ', '', 'Е', 'Ё', 'Э', 'Є', 'Ə'],
536 'F' => ['Ф', 'Φ'],
537 'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
538 'H' => ['Η', 'Ή', 'Ħ'],
539 'I' => ['Í', 'Ì', '', 'Ĩ', '', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', '', '', '', '', '', '', 'Ἷ', '', '', '', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ'],
540 'K' => ['К', 'Κ'],
541 'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', ''],
542 'M' => ['М', 'Μ'],
543 'N' => ['Ń', 'Ñ', 'Ň', '�
544 ', 'Ŋ', 'Н', 'Ν'],
545 'O' => ['Ó', 'Ò', '', 'Õ', '', 'Ô', '', '', '', '', '', 'Ơ', '', '', '', '', '', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', '', '', '', '', '', '', '', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ'],
546 'P' => ['П', 'Π'],
547 'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
548 'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
549 'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
550 'U' => ['Ú', 'Ù', '', 'Ũ', '', 'Ư', '', '', '', '', '', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ'],
551 'V' => ['В'],
552 'W' => ['Ω', 'Ώ', 'Ŵ'],
553 'X' => ['Χ', 'Ξ'],
554 'Y' => ['Ý', '', '', '', '', 'Ÿ', '', '', '', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
555 'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
556 'AE' => ['Ä', 'Æ', 'Ǽ'],
557 'CH' => ['Ч'],
558 'DJ' => ['Ђ'],
559 'DZ' => ['Џ'],
560 'GX' => ['Ĝ'],
561 'HX' => ['Ĥ'],
562 'IJ' => ['IJ'],
563 'JX' => ['Ĵ'],
564 'KH' => ['Х'],
565 'LJ' => ['Љ'],
566 'NJ' => ['Њ'],
567 'OE' => ['Ö', 'Œ'],
568 'PS' => ['Ψ'],
569 'SH' => ['Ш'],
570 'SHCH' => ['Щ'],
571 'SS' => [''],
572 'TH' => ['Þ'],
573 'TS' => ['Ц'],
574 'UE' => ['Ü'],
575 'YA' => ['Я'],
576 'YU' => ['Ю'],
577 'ZH' => ['Ж'],
578 ' ' => ["\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"],
579 ];
580 }
581 }
582