1 | <?php namespace Tamtamchik\NameCase; |
||
6 | class Formatter |
||
7 | { |
||
8 | // Irish exceptions. |
||
9 | private const EXCEPTIONS = [ |
||
10 | '\bMacEdo' => 'Macedo', |
||
11 | '\bMacEvicius' => 'Macevicius', |
||
12 | '\bMacHado' => 'Machado', |
||
13 | '\bMacHar' => 'Machar', |
||
14 | '\bMacHin' => 'Machin', |
||
15 | '\bMacHlin' => 'Machlin', |
||
16 | '\bMacIas' => 'Macias', |
||
17 | '\bMacIulis' => 'Maciulis', |
||
18 | '\bMacKie' => 'Mackie', |
||
19 | '\bMacKle' => 'Mackle', |
||
20 | '\bMacKlin' => 'Macklin', |
||
21 | '\bMacKmin' => 'Mackmin', |
||
22 | '\bMacQuarie' => 'Macquarie', |
||
23 | '\bMacOmber' => 'Macomber', |
||
24 | '\bMacIn' => 'Macin', |
||
25 | '\bMacKintosh' => 'Mackintosh', |
||
26 | '\bMacKen' => 'Macken', |
||
27 | '\bMacHen' => 'Machen', |
||
28 | '\bMacisaac' => 'MacIsaac', |
||
29 | '\bMacHiel' => 'Machiel', |
||
30 | '\bMacIol' => 'Maciol', |
||
31 | '\bMacKell' => 'Mackell', |
||
32 | '\bMacKlem' => 'Macklem', |
||
33 | '\bMacKrell' => 'Mackrell', |
||
34 | '\bMacLin' => 'Maclin', |
||
35 | '\bMacKey' => 'Mackey', |
||
36 | '\bMacKley' => 'Mackley', |
||
37 | '\bMacHell' => 'Machell', |
||
38 | '\bMacHon' => 'Machon', |
||
39 | ]; |
||
40 | |||
41 | // General replacements. |
||
42 | private const REPLACEMENTS = [ |
||
43 | '\bAl(?=\s+\w)' => 'al', // al Arabic or forename Al. |
||
44 | '\bAp\b' => 'ap', // ap Welsh. |
||
45 | '\b(Bin|Binti|Binte)\b' => 'bin', // bin, binti, binte Arabic. |
||
46 | '\bDell([ae])\b' => 'dell\1', // della and delle Italian. |
||
47 | '\bD([aeiou])\b' => 'd\1', // da, de, di Italian; du French; do Brasil. |
||
48 | '\bD([ao]s)\b' => 'd\1', // das, dos Brasileiros. |
||
49 | '\bDe([lrn])\b' => 'de\1', // del Italian; der/den Dutch/Flemish. |
||
50 | '\bL([eo])\b' => 'l\1', // lo Italian; le French. |
||
51 | '\bTe([rn])' => 'te\1', // ten, ter Dutch/Flemish. |
||
52 | '\bVan(?=\s+\w)' => 'van', // van German or forename Van. |
||
53 | '\bVon\b' => 'von', // von Dutch/Flemish. |
||
54 | ]; |
||
55 | |||
56 | private const SPANISH = [ |
||
57 | '\bEl\b' => 'el', // el Greek or El Spanish. |
||
58 | '\bLa\b' => 'la', // la French or La Spanish. |
||
59 | ]; |
||
60 | |||
61 | private const HEBREW = [ |
||
62 | '\bBen(?=\s+\w)' => 'ben', // ben Hebrew or forename Ben. |
||
63 | '\bBat(?=\s+\w)' => 'bat', // bat Hebrew or forename Bat. |
||
64 | ]; |
||
65 | |||
66 | // Spanish conjunctions. |
||
67 | private const CONJUNCTIONS = ["Y", "E", "I"]; |
||
68 | |||
69 | // Roman letters regexp. |
||
70 | private const ROMAN_REGEX = '\b((?:[Xx]{1,3}|[Xx][Ll]|[Ll][Xx]{0,3})?(?:[Ii]{1,3}|[Ii][VvXx]|[Vv][Ii]{0,3})?)\b'; |
||
71 | |||
72 | // Post nominal values. |
||
73 | private const POST_NOMINALS = [ |
||
74 | 'ACILEx', 'ACSM', 'ADC', 'AEPC', 'AFC', 'AFM', 'AICSM', 'AKC', 'AM', 'ARBRIBA', 'ARCS', 'ARRC', 'ARSM', 'AUH', 'AUS', |
||
75 | 'BA', 'BArch', 'BCh', 'BChir', 'BCL', 'BDS', 'BEd', 'BEM', 'BEng', 'BM', 'BS', 'BSc', 'BSW', 'BVM&S', 'BVScBVetMed', |
||
76 | 'CB', 'CBE', 'CEng', 'CertHE', 'CGC', 'CGM', 'CH', 'CIE', 'CMarEngCMarSci', 'CMarTech', 'CMG', 'CMILT', 'CML', 'CPhT', 'CPLCTP', 'CPM', 'CQSW', 'CSciTeach', 'CSI', 'CTL', 'CVO', |
||
77 | 'DBE', 'DBEnv', 'DC', 'DCB', 'DCM', 'DCMG', 'DConstMgt', 'DCVO', 'DD', 'DEM', 'DFC', 'DFM', 'DIC', 'Dip', 'DipHE', 'DipLP', 'DipSW', 'DL', 'DLitt', 'DLP', 'DPhil', 'DProf', 'DPT', 'DREst', 'DSC', 'DSM', 'DSO', 'DSocSci', |
||
78 | 'ED', 'EdD', 'EJLog', 'EMLog', 'EN', 'EngD', 'EngTech', 'ERD', 'ESLog', |
||
79 | 'FADO', 'FAWM', 'FBDOFCOptom', 'FCEM', 'FCILEx', 'FCILT', 'FCSP.', 'FdAFdSc', 'FdEng', 'FFHOM', 'FFPM', 'FRCAFFPMRCA', 'FRCGP', 'FRCOG', 'FRCP', 'FRCPsych', 'FRCS', 'FRCVS', 'FSCR.', |
||
80 | 'GBE', 'GC', 'GCB', 'GCIE', 'GCILEx', 'GCMG', 'GCSI', 'GCVO', 'GM', |
||
81 | 'HNC', 'HNCert', 'HND', 'HNDip', |
||
82 | 'ICTTech', 'IDSM', 'IEng', 'IMarEng', 'IOMCPM', 'ISO', |
||
83 | 'J', 'JP', 'JrLog', |
||
84 | 'KBE', 'KC', 'KCB', 'KCIE', 'KCMG', 'KCSI', 'KCVO', 'KG', 'KP', 'KT', |
||
85 | 'LFHOM', 'LG', 'LJ', 'LLB', 'LLD', 'LLM', 'Log', 'LPE', 'LT', 'LVO', |
||
86 | 'MA', 'MAcc', 'MAnth', 'MArch', 'MarEngTech', 'MB', 'MBA', 'MBChB', 'MBE', 'MBEIOM', 'MBiochem', 'MC', 'MCEM', 'MCGI', 'MCh.', 'MChem', 'MChiro', 'MClinRes', 'MComp', 'MCOptom', 'MCSM', 'MCSP', 'MD', 'MEarthSc', 'MEng', 'MEnt', 'MEP', 'MFHOM', 'MFin', 'MFPM', 'MGeol', 'MILT', 'MJur', 'MLA', 'MLitt', 'MM', 'MMath', 'MMathStat', 'MMORSE', 'MMus', 'MOst', 'MP', 'MPAMEd', 'MPharm', 'MPhil', 'MPhys', 'MRCGP', 'MRCOG', 'MRCP', 'MRCPath', 'MRCPCHFRCPCH', 'MRCPsych', 'MRCS', 'MRCVS', 'MRes', 'MS', 'MSc', 'MScChiro', 'MSci', 'MSCR', 'MSM', 'MSocSc', 'MSP', 'MSt', 'MSW', 'MSYP', 'MVO', |
||
87 | 'NPQH', |
||
88 | 'OBE', 'OBI', 'OM', 'OND', |
||
89 | 'PgC', 'PGCAP', 'PGCE', 'PgCert', 'PGCHE', 'PgCLTHE', 'PgD', 'PGDE', 'PgDip', 'PhD', 'PLog', 'PLS', |
||
90 | 'QAM', 'QC', 'QFSM', 'QGM', 'QHC', 'QHDS', 'QHNS', 'QHP', 'QHS', 'QPM', 'QS', 'QTSCSci', |
||
91 | 'RD', 'RFHN', 'RGN', 'RHV', 'RIAI', 'RIAS', 'RM', 'RMN', 'RN', 'RN1RNA', 'RN2', 'RN3', 'RN4', 'RN5', 'RN6', 'RN7', 'RN8', 'RN9', 'RNC', 'RNLD', 'RNMH', 'ROH', 'RRC', 'RSAW', 'RSci', 'RSciTech', 'RSCN', 'RSN', 'RVM', 'RVN', |
||
92 | 'SCHM', 'SCJ', 'SCLD', 'SEN', 'SGM', 'SL', 'SPANSPMH', 'SPCC', 'SPCN', 'SPDN', 'SPHP', 'SPLD', 'SrLog', 'SRN', 'SROT', |
||
93 | 'TD', |
||
94 | 'UD', |
||
95 | 'V100', 'V200', 'V300', 'VC', 'VD', 'VetMB', 'VN', 'VRD' |
||
96 | ]; |
||
97 | |||
98 | // Excluded post-nominals |
||
99 | private static $postNominalsExcluded = []; |
||
100 | |||
101 | // Default options. |
||
102 | private static $options = [ |
||
103 | 'lazy' => true, |
||
104 | 'irish' => true, |
||
105 | 'spanish' => false, |
||
106 | 'roman' => true, |
||
107 | 'hebrew' => true, |
||
108 | 'postnominal' => true, |
||
109 | ]; |
||
110 | |||
111 | /** |
||
112 | * Formatter constructor. |
||
113 | 4 | * |
|
114 | * @param array $options |
||
115 | 4 | */ |
|
116 | 4 | public function __construct($options = []) |
|
117 | { |
||
118 | $this->setOptions($options); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Global options setter. |
||
123 | 18 | * |
|
124 | * @param array $options |
||
125 | 18 | */ |
|
126 | 18 | public static function setOptions($options) |
|
127 | { |
||
128 | self::$options = array_merge(self::$options, $options); |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Global post-nominals exclusions setter. |
||
133 | * |
||
134 | * @param array|string $values |
||
135 | * @return boolean |
||
136 | 20 | */ |
|
137 | public static function excludePostNominals($values) |
||
138 | 20 | { |
|
139 | if (is_string($values)) $values = [$values]; |
||
140 | 18 | if (!is_array($values)) return false; |
|
141 | |||
142 | self::$postNominalsExcluded = array_merge(self::$postNominalsExcluded, $values); |
||
143 | 18 | } |
|
144 | |||
145 | /** |
||
146 | 16 | * Main function for NameCase. |
|
147 | * |
||
148 | 16 | * @param string $name |
|
149 | 16 | * @param array $options |
|
150 | * |
||
151 | * @return string |
||
152 | 16 | */ |
|
153 | public static function nameCase($name = '', array $options = []): string |
||
154 | { |
||
155 | 16 | if ($name == '') return $name; |
|
156 | |||
157 | 16 | self::setOptions($options); |
|
158 | 16 | ||
159 | // Do not do anything if string is mixed and lazy option is true. |
||
160 | if (self::$options['lazy'] && self::skipMixed($name)) return $name; |
||
161 | 16 | ||
162 | 2 | // Capitalize |
|
163 | $name = self::capitalize($name); |
||
164 | |||
165 | 16 | foreach (self::getReplacements() as $pattern => $replacement) { |
|
166 | 16 | $name = mb_ereg_replace($pattern, $replacement, $name); |
|
167 | } |
||
168 | |||
169 | 16 | return self::processOptions($name); |
|
170 | } |
||
171 | |||
172 | private static function processOptions(string $name): string |
||
188 | |||
189 | 4 | /** |
|
190 | 16 | * Capitalize first letters. |
|
191 | * |
||
192 | 16 | * @param string $name |
|
193 | * |
||
194 | 16 | * @return string |
|
195 | */ |
||
196 | private static function capitalize(string $name): string |
||
213 | |||
214 | 16 | /** |
|
215 | * Define required replacements. |
||
216 | * |
||
217 | * @return array |
||
218 | */ |
||
219 | private static function getReplacements(): array |
||
233 | |||
234 | /** |
||
235 | * Skip if string is mixed case. |
||
236 | * |
||
237 | * @param string $name |
||
238 | * |
||
239 | 16 | * @return bool |
|
240 | */ |
||
241 | 16 | private static function skipMixed(string $name): bool |
|
248 | |||
249 | /** |
||
250 | 16 | * Update for Irish names. |
|
251 | * |
||
252 | * @param string $name |
||
253 | * |
||
254 | * @return string |
||
255 | */ |
||
256 | private static function updateIrish(string $name): string |
||
269 | |||
270 | /** |
||
271 | * Fix roman numeral names. |
||
272 | * |
||
273 | * @param string $name |
||
274 | 6 | * |
|
275 | * @return string |
||
276 | */ |
||
277 | 6 | private static function updateRoman(string $name): string |
|
283 | |||
284 | /** |
||
285 | 6 | * Updates irish Mac & Mc. |
|
286 | * |
||
287 | * @param string $name |
||
288 | * |
||
289 | * @return string |
||
290 | */ |
||
291 | private static function updateMac(string $name): string |
||
304 | |||
305 | /** |
||
306 | * Fix Spanish conjunctions. |
||
307 | * |
||
308 | * @param string $name |
||
309 | 16 | * |
|
310 | * @return string |
||
311 | 16 | */ |
|
312 | 16 | private static function fixConjunction(string $name): string |
|
319 | |||
320 | /** |
||
321 | * Fix post-nominal letter cases. |
||
322 | * |
||
323 | * @param string $name |
||
324 | * @return string |
||
325 | */ |
||
326 | private static function fixPostNominal(string $name): string |
||
334 | } |
||
335 |