PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor-prefixed / symfony / string / AbstractUnicodeString.php
mailpoet / vendor-prefixed / symfony / string Last commit date
Exception 2 years ago Inflector 8 months ago Resources 8 months ago Slugger 2 years ago AbstractString.php 2 years ago AbstractUnicodeString.php 8 months ago ByteString.php 2 years ago CodePointString.php 2 years ago LazyString.php 2 years ago UnicodeString.php 2 years ago index.php 2 years ago
AbstractUnicodeString.php
472 lines
1 <?php
2 namespace MailPoetVendor\Symfony\Component\String;
3 if (!defined('ABSPATH')) exit;
4 use MailPoetVendor\Symfony\Component\String\Exception\ExceptionInterface;
5 use MailPoetVendor\Symfony\Component\String\Exception\InvalidArgumentException;
6 use MailPoetVendor\Symfony\Component\String\Exception\RuntimeException;
7 abstract class AbstractUnicodeString extends AbstractString
8 {
9 public const NFC = \Normalizer::NFC;
10 public const NFD = \Normalizer::NFD;
11 public const NFKC = \Normalizer::NFKC;
12 public const NFKD = \Normalizer::NFKD;
13 // all ASCII letters sorted by typical frequency of occurrence
14 private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
15 // the subset of folded case mappings that is not in lower case mappings
16 private const FOLD_FROM = ['İ', 'µ', 'ſ', "�
17 ", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "ι", 'ß', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', '�
18 ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', '�
19 ', '', '', '', '', '', ''];
20 private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', '�
21 ι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', '�
22 ι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', '', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', '', 'ῆι', 'ηι', '', '', '', '', '', '', '', 'ὼι', 'ωι', 'ώι', '', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ'];
23 // the subset of upper case mappings that map one code point to many code points
24 private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', '�
25 ', '', 'և', '', '', '', '', '', 'ʼn', 'ΐ', 'ΰ', 'ǰ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
26 private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ԵՒ', 'ՄՆ', 'ՄԵ', 'ՄԻ', 'ՎՆ', 'ՄԽ', 'ʼN', 'Ϊ́', 'Ϋ́', '', '', '', '', '', '', 'Υ̓', 'Υ̓̀', 'Υ̓́', 'Υ̓͂', 'Α͂', 'Η͂', 'Ϊ̀', 'Ϊ́', 'Ι͂', 'Ϊ͂', 'Ϋ̀', 'Ϋ́', 'Ρ̓', 'Υ͂', 'Ϋ͂', 'Ω͂'];
27 // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD
28 private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ʼn', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'DŽ', '�
29 ', 'dž', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', '�
30 ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', '�
31 ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '�
32 �', '�
33 �', '�
34 �', '�
35 �', '�
36 �', '�
37 �', '�
38 �', '�
39 �', '�
40 �', '�
41 �', '�
42 �', '�
43 �', '�
44 �', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '�
45 ', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '⦅', '⦆', '。', '、', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '�
46 ', ''];
47 private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))'];
48 private static $transliterators = [];
49 private static $tableZero;
50 private static $tableWide;
51 public static function fromCodePoints(int ...$codes) : self
52 {
53 $string = '';
54 foreach ($codes as $code) {
55 if (0x80 > ($code %= 0x200000)) {
56 $string .= \chr($code);
57 } elseif (0x800 > $code) {
58 $string .= \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
59 } elseif (0x10000 > $code) {
60 $string .= \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
61 } else {
62 $string .= \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
63 }
64 }
65 return new static($string);
66 }
67 public function ascii(array $rules = []) : self
68 {
69 $str = clone $this;
70 $s = $str->string;
71 $str->string = '';
72 \array_unshift($rules, 'nfd');
73 $rules[] = 'latin-ascii';
74 if (\function_exists('transliterator_transliterate')) {
75 $rules[] = 'any-latin/bgn';
76 }
77 $rules[] = 'nfkd';
78 $rules[] = '[:nonspacing mark:] remove';
79 while (\strlen($s) - 1 > ($i = \strspn($s, self::ASCII))) {
80 if (0 < --$i) {
81 $str->string .= \substr($s, 0, $i);
82 $s = \substr($s, $i);
83 }
84 if (!($rule = \array_shift($rules))) {
85 $rules = [];
86 // An empty rule interrupts the next ones
87 }
88 if ($rule instanceof \Transliterator) {
89 $s = $rule->transliterate($s);
90 } elseif ($rule instanceof \Closure) {
91 $s = $rule($s);
92 } elseif ($rule) {
93 if ('nfd' === ($rule = \strtolower($rule))) {
94 \normalizer_is_normalized($s, self::NFD) ?: ($s = \normalizer_normalize($s, self::NFD));
95 } elseif ('nfkd' === $rule) {
96 \normalizer_is_normalized($s, self::NFKD) ?: ($s = \normalizer_normalize($s, self::NFKD));
97 } elseif ('[:nonspacing mark:] remove' === $rule) {
98 $s = \preg_replace('/\\p{Mn}++/u', '', $s);
99 } elseif ('latin-ascii' === $rule) {
100 $s = \str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s);
101 } elseif ('de-ascii' === $rule) {
102 $s = \preg_replace("/([AUO])̈(?=\\p{Ll})/u", '$1e', $s);
103 $s = \str_replace(["", "", "", "", "", ""], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s);
104 } elseif (\function_exists('transliterator_transliterate')) {
105 if (null === ($transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule)))) {
106 if ('any-latin/bgn' === $rule) {
107 $rule = 'any-latin';
108 $transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule));
109 }
110 if (null === $transliterator) {
111 throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule));
112 }
113 self::$transliterators['any-latin/bgn'] = $transliterator;
114 }
115 $s = $transliterator->transliterate($s);
116 }
117 } elseif (!\function_exists('iconv')) {
118 $s = \preg_replace('/[^\\x00-\\x7F]/u', '?', $s);
119 } else {
120 $s = @\preg_replace_callback('/[^\\x00-\\x7F]/u', static function ($c) {
121 $c = (string) \iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);
122 if ('' === $c && '' === \iconv('UTF-8', 'ASCII//TRANSLIT', '²')) {
123 throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
124 }
125 return 1 < \strlen($c) ? \ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
126 }, $s);
127 }
128 }
129 $str->string .= $s;
130 return $str;
131 }
132 public function camel() : parent
133 {
134 $str = clone $this;
135 $str->string = \str_replace(' ', '', \preg_replace_callback('/\\b.(?!\\p{Lu})/u', static function ($m) use(&$i) {
136 return 1 === ++$i ? 'İ' === $m[0] ? '' : \mb_strtolower($m[0], 'UTF-8') : \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
137 }, \preg_replace('/[^\\pL0-9]++/u', ' ', $this->string)));
138 return $str;
139 }
140 public function codePointsAt(int $offset) : array
141 {
142 $str = $this->slice($offset, 1);
143 if ('' === $str->string) {
144 return [];
145 }
146 $codePoints = [];
147 foreach (\preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
148 $codePoints[] = \mb_ord($c, 'UTF-8');
149 }
150 return $codePoints;
151 }
152 public function folded(bool $compat = \true) : parent
153 {
154 $str = clone $this;
155 if (!$compat || \PHP_VERSION_ID < 70300 || !\defined('Normalizer::NFKC_CF')) {
156 $str->string = \normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC);
157 $str->string = \mb_strtolower(\str_replace(self::FOLD_FROM, self::FOLD_TO, $str->string), 'UTF-8');
158 } else {
159 $str->string = \normalizer_normalize($str->string, \Normalizer::NFKC_CF);
160 }
161 return $str;
162 }
163 public function join(array $strings, ?string $lastGlue = null) : parent
164 {
165 $str = clone $this;
166 $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : '';
167 $str->string = \implode($this->string, $strings) . $tail;
168 if (!\preg_match('//u', $str->string)) {
169 throw new InvalidArgumentException('Invalid UTF-8 string.');
170 }
171 return $str;
172 }
173 public function lower() : parent
174 {
175 $str = clone $this;
176 $str->string = \mb_strtolower(\str_replace('İ', '', $str->string), 'UTF-8');
177 return $str;
178 }
179 public function match(string $regexp, int $flags = 0, int $offset = 0) : array
180 {
181 $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
182 if ($this->ignoreCase) {
183 $regexp .= 'i';
184 }
185 \set_error_handler(static function ($t, $m) {
186 throw new InvalidArgumentException($m);
187 });
188 try {
189 if (\false === $match($regexp . 'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
190 $lastError = \preg_last_error();
191 foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
192 if ($lastError === $v && '_ERROR' === \substr($k, -6)) {
193 throw new RuntimeException('Matching failed with ' . $k . '.');
194 }
195 }
196 throw new RuntimeException('Matching failed with unknown error code.');
197 }
198 } finally {
199 \restore_error_handler();
200 }
201 return $matches;
202 }
203 public function normalize(int $form = self::NFC) : self
204 {
205 if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) {
206 throw new InvalidArgumentException('Unsupported normalization form.');
207 }
208 $str = clone $this;
209 \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form));
210 return $str;
211 }
212 public function padBoth(int $length, string $padStr = ' ') : parent
213 {
214 if ('' === $padStr || !\preg_match('//u', $padStr)) {
215 throw new InvalidArgumentException('Invalid UTF-8 string.');
216 }
217 $pad = clone $this;
218 $pad->string = $padStr;
219 return $this->pad($length, $pad, \STR_PAD_BOTH);
220 }
221 public function padEnd(int $length, string $padStr = ' ') : parent
222 {
223 if ('' === $padStr || !\preg_match('//u', $padStr)) {
224 throw new InvalidArgumentException('Invalid UTF-8 string.');
225 }
226 $pad = clone $this;
227 $pad->string = $padStr;
228 return $this->pad($length, $pad, \STR_PAD_RIGHT);
229 }
230 public function padStart(int $length, string $padStr = ' ') : parent
231 {
232 if ('' === $padStr || !\preg_match('//u', $padStr)) {
233 throw new InvalidArgumentException('Invalid UTF-8 string.');
234 }
235 $pad = clone $this;
236 $pad->string = $padStr;
237 return $this->pad($length, $pad, \STR_PAD_LEFT);
238 }
239 public function replaceMatches(string $fromRegexp, $to) : parent
240 {
241 if ($this->ignoreCase) {
242 $fromRegexp .= 'i';
243 }
244 if (\is_array($to) || $to instanceof \Closure) {
245 if (!\is_callable($to)) {
246 throw new \TypeError(\sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class));
247 }
248 $replace = 'preg_replace_callback';
249 $to = static function (array $m) use($to) : string {
250 $to = $to($m);
251 if ('' !== $to && (!\is_string($to) || !\preg_match('//u', $to))) {
252 throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.');
253 }
254 return $to;
255 };
256 } elseif ('' !== $to && !\preg_match('//u', $to)) {
257 throw new InvalidArgumentException('Invalid UTF-8 string.');
258 } else {
259 $replace = 'preg_replace';
260 }
261 \set_error_handler(static function ($t, $m) {
262 throw new InvalidArgumentException($m);
263 });
264 try {
265 if (null === ($string = $replace($fromRegexp . 'u', $to, $this->string))) {
266 $lastError = \preg_last_error();
267 foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
268 if ($lastError === $v && '_ERROR' === \substr($k, -6)) {
269 throw new RuntimeException('Matching failed with ' . $k . '.');
270 }
271 }
272 throw new RuntimeException('Matching failed with unknown error code.');
273 }
274 } finally {
275 \restore_error_handler();
276 }
277 $str = clone $this;
278 $str->string = $string;
279 return $str;
280 }
281 public function reverse() : parent
282 {
283 $str = clone $this;
284 $str->string = \implode('', \array_reverse(\preg_split('/(\\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY)));
285 return $str;
286 }
287 public function snake() : parent
288 {
289 $str = $this->camel();
290 $str->string = \mb_strtolower(\preg_replace(['/(\\p{Lu}+)(\\p{Lu}\\p{Ll})/u', '/([\\p{Ll}0-9])(\\p{Lu})/u'], 'MailPoetVendor\\1_\\2', $str->string), 'UTF-8');
291 return $str;
292 }
293 public function title(bool $allWords = \false) : parent
294 {
295 $str = clone $this;
296 $limit = $allWords ? -1 : 1;
297 $str->string = \preg_replace_callback('/\\b./u', static function (array $m) : string {
298 return \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
299 }, $str->string, $limit);
300 return $str;
301 }
302 public function trim(string $chars = " \t\n\r\x00\v\f ") : parent
303 {
304 if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) {
305 throw new InvalidArgumentException('Invalid UTF-8 chars.');
306 }
307 $chars = \preg_quote($chars);
308 $str = clone $this;
309 $str->string = \preg_replace("{^[{$chars}]++|[{$chars}]++\$}uD", '', $str->string);
310 return $str;
311 }
312 public function trimEnd(string $chars = " \t\n\r\x00\v\f ") : parent
313 {
314 if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) {
315 throw new InvalidArgumentException('Invalid UTF-8 chars.');
316 }
317 $chars = \preg_quote($chars);
318 $str = clone $this;
319 $str->string = \preg_replace("{[{$chars}]++\$}uD", '', $str->string);
320 return $str;
321 }
322 public function trimPrefix($prefix) : parent
323 {
324 if (!$this->ignoreCase) {
325 return parent::trimPrefix($prefix);
326 }
327 $str = clone $this;
328 if ($prefix instanceof \Traversable) {
329 $prefix = \iterator_to_array($prefix, \false);
330 } elseif ($prefix instanceof parent) {
331 $prefix = $prefix->string;
332 }
333 $prefix = \implode('|', \array_map('preg_quote', (array) $prefix));
334 $str->string = \preg_replace("{^(?:{$prefix})}iuD", '', $this->string);
335 return $str;
336 }
337 public function trimStart(string $chars = " \t\n\r\x00\v\f ") : parent
338 {
339 if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) {
340 throw new InvalidArgumentException('Invalid UTF-8 chars.');
341 }
342 $chars = \preg_quote($chars);
343 $str = clone $this;
344 $str->string = \preg_replace("{^[{$chars}]++}uD", '', $str->string);
345 return $str;
346 }
347 public function trimSuffix($suffix) : parent
348 {
349 if (!$this->ignoreCase) {
350 return parent::trimSuffix($suffix);
351 }
352 $str = clone $this;
353 if ($suffix instanceof \Traversable) {
354 $suffix = \iterator_to_array($suffix, \false);
355 } elseif ($suffix instanceof parent) {
356 $suffix = $suffix->string;
357 }
358 $suffix = \implode('|', \array_map('preg_quote', (array) $suffix));
359 $str->string = \preg_replace("{(?:{$suffix})\$}iuD", '', $this->string);
360 return $str;
361 }
362 public function upper() : parent
363 {
364 $str = clone $this;
365 $str->string = \mb_strtoupper($str->string, 'UTF-8');
366 if (\PHP_VERSION_ID < 70300) {
367 $str->string = \str_replace(self::UPPER_FROM, self::UPPER_TO, $str->string);
368 }
369 return $str;
370 }
371 public function width(bool $ignoreAnsiDecoration = \true) : int
372 {
373 $width = 0;
374 $s = \str_replace(["\x00", "\x05", "\x07"], '', $this->string);
375 if (\false !== \strpos($s, "\r")) {
376 $s = \str_replace(["\r\n", "\r"], "\n", $s);
377 }
378 if (!$ignoreAnsiDecoration) {
379 $s = \preg_replace('/[\\p{Cc}\\x7F]++/u', '', $s);
380 }
381 foreach (\explode("\n", $s) as $s) {
382 if ($ignoreAnsiDecoration) {
383 $s = \preg_replace('/(?:\\x1B(?:
384 \\[ [\\x30-\\x3F]*+ [\\x20-\\x2F]*+ [\\x40-\\x7E]
385 | [P\\]X^_] .*? \\x1B\\\\
386 | [\\x41-\\x7E]
387 )|[\\p{Cc}\\x7F]++)/xu', '', $s);
388 }
389 $lineWidth = $this->wcswidth($s);
390 if ($lineWidth > $width) {
391 $width = $lineWidth;
392 }
393 }
394 return $width;
395 }
396 private function pad(int $len, self $pad, int $type) : parent
397 {
398 $sLen = $this->length();
399 if ($len <= $sLen) {
400 return clone $this;
401 }
402 $padLen = $pad->length();
403 $freeLen = $len - $sLen;
404 $len = $freeLen % $padLen;
405 switch ($type) {
406 case \STR_PAD_RIGHT:
407 return $this->append(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
408 case \STR_PAD_LEFT:
409 return $this->prepend(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
410 case \STR_PAD_BOTH:
411 $freeLen /= 2;
412 $rightLen = \ceil($freeLen);
413 $len = $rightLen % $padLen;
414 $str = $this->append(\str_repeat($pad->string, \intdiv($rightLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
415 $leftLen = \floor($freeLen);
416 $len = $leftLen % $padLen;
417 return $str->prepend(\str_repeat($pad->string, \intdiv($leftLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
418 default:
419 throw new InvalidArgumentException('Invalid padding type.');
420 }
421 }
422 private function wcswidth(string $string) : int
423 {
424 $width = 0;
425 foreach (\preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
426 $codePoint = \mb_ord($c, 'UTF-8');
427 if (0 === $codePoint || 0x34f === $codePoint || 0x200b <= $codePoint && 0x200f >= $codePoint || 0x2028 === $codePoint || 0x2029 === $codePoint || 0x202a <= $codePoint && 0x202e >= $codePoint || 0x2060 <= $codePoint && 0x2063 >= $codePoint) {
428 continue;
429 }
430 // Non printable characters
431 if (32 > $codePoint || 0x7f <= $codePoint && 0xa0 > $codePoint) {
432 return -1;
433 }
434 if (null === self::$tableZero) {
435 self::$tableZero = (require __DIR__ . '/Resources/data/wcswidth_table_zero.php');
436 }
437 if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) {
438 $lbound = 0;
439 while ($ubound >= $lbound) {
440 $mid = \floor(($lbound + $ubound) / 2);
441 if ($codePoint > self::$tableZero[$mid][1]) {
442 $lbound = $mid + 1;
443 } elseif ($codePoint < self::$tableZero[$mid][0]) {
444 $ubound = $mid - 1;
445 } else {
446 continue 2;
447 }
448 }
449 }
450 if (null === self::$tableWide) {
451 self::$tableWide = (require __DIR__ . '/Resources/data/wcswidth_table_wide.php');
452 }
453 if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) {
454 $lbound = 0;
455 while ($ubound >= $lbound) {
456 $mid = \floor(($lbound + $ubound) / 2);
457 if ($codePoint > self::$tableWide[$mid][1]) {
458 $lbound = $mid + 1;
459 } elseif ($codePoint < self::$tableWide[$mid][0]) {
460 $ubound = $mid - 1;
461 } else {
462 $width += 2;
463 continue 2;
464 }
465 }
466 }
467 ++$width;
468 }
469 return $width;
470 }
471 }
472