1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @link http://www.yiiframework.com/ |
4
|
|
|
* @copyright Copyright (c) 2008 Yii Software LLC |
5
|
|
|
* @license http://www.yiiframework.com/license/ |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace yii\helpers; |
9
|
|
|
|
10
|
|
|
use Yii; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* BaseInflector provides concrete implementation for [[Inflector]]. |
14
|
|
|
* |
15
|
|
|
* Do not use BaseInflector. Use [[Inflector]] instead. |
16
|
|
|
* |
17
|
|
|
* @author Antonio Ramirez <[email protected]> |
18
|
|
|
* @author Alexander Makarov <[email protected]> |
19
|
|
|
* @since 2.0 |
20
|
|
|
*/ |
21
|
|
|
class BaseInflector |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* @var array the rules for converting a word into its plural form. |
25
|
|
|
* The keys are the regular expressions and the values are the corresponding replacements. |
26
|
|
|
*/ |
27
|
|
|
public static $plurals = [ |
28
|
|
|
'/([nrlm]ese|deer|fish|sheep|measles|ois|pox|media)$/i' => '\1', |
29
|
|
|
'/^(sea[- ]bass)$/i' => '\1', |
30
|
|
|
'/(m)ove$/i' => '\1oves', |
31
|
|
|
'/(f)oot$/i' => '\1eet', |
32
|
|
|
'/(h)uman$/i' => '\1umans', |
33
|
|
|
'/(s)tatus$/i' => '\1tatuses', |
34
|
|
|
'/(s)taff$/i' => '\1taff', |
35
|
|
|
'/(t)ooth$/i' => '\1eeth', |
36
|
|
|
'/(quiz)$/i' => '\1zes', |
37
|
|
|
'/^(ox)$/i' => '\1\2en', |
38
|
|
|
'/([m|l])ouse$/i' => '\1ice', |
39
|
|
|
'/(matr|vert|ind)(ix|ex)$/i' => '\1ices', |
40
|
|
|
'/(x|ch|ss|sh)$/i' => '\1es', |
41
|
|
|
'/([^aeiouy]|qu)y$/i' => '\1ies', |
42
|
|
|
'/(hive)$/i' => '\1s', |
43
|
|
|
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', |
44
|
|
|
'/sis$/i' => 'ses', |
45
|
|
|
'/([ti])um$/i' => '\1a', |
46
|
|
|
'/(p)erson$/i' => '\1eople', |
47
|
|
|
'/(m)an$/i' => '\1en', |
48
|
|
|
'/(c)hild$/i' => '\1hildren', |
49
|
|
|
'/(buffal|tomat|potat|ech|her|vet)o$/i' => '\1oes', |
50
|
|
|
'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i', |
51
|
|
|
'/us$/i' => 'uses', |
52
|
|
|
'/(alias)$/i' => '\1es', |
53
|
|
|
'/(ax|cris|test)is$/i' => '\1es', |
54
|
|
|
'/(currenc)y$/' => '\1ies', |
55
|
|
|
'/s$/' => 's', |
56
|
|
|
'/^$/' => '', |
57
|
|
|
'/$/' => 's', |
58
|
|
|
]; |
59
|
|
|
/** |
60
|
|
|
* @var array the rules for converting a word into its singular form. |
61
|
|
|
* The keys are the regular expressions and the values are the corresponding replacements. |
62
|
|
|
*/ |
63
|
|
|
public static $singulars = [ |
64
|
|
|
'/([nrlm]ese|deer|fish|sheep|measles|ois|pox|media|ss)$/i' => '\1', |
65
|
|
|
'/^(sea[- ]bass)$/i' => '\1', |
66
|
|
|
'/(s)tatuses$/i' => '\1tatus', |
67
|
|
|
'/(f)eet$/i' => '\1oot', |
68
|
|
|
'/(t)eeth$/i' => '\1ooth', |
69
|
|
|
'/^(.*)(menu)s$/i' => '\1\2', |
70
|
|
|
'/(quiz)zes$/i' => '\\1', |
71
|
|
|
'/(matr)ices$/i' => '\1ix', |
72
|
|
|
'/(vert|ind)ices$/i' => '\1ex', |
73
|
|
|
'/^(ox)en/i' => '\1', |
74
|
|
|
'/(alias)(es)*$/i' => '\1', |
75
|
|
|
'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us', |
76
|
|
|
'/([ftw]ax)es/i' => '\1', |
77
|
|
|
'/(cris|ax|test)es$/i' => '\1is', |
78
|
|
|
'/(shoe|slave)s$/i' => '\1', |
79
|
|
|
'/(o)es$/i' => '\1', |
80
|
|
|
'/ouses$/' => 'ouse', |
81
|
|
|
'/([^a])uses$/' => '\1us', |
82
|
|
|
'/([m|l])ice$/i' => '\1ouse', |
83
|
|
|
'/(x|ch|ss|sh)es$/i' => '\1', |
84
|
|
|
'/(m)ovies$/i' => '\1\2ovie', |
85
|
|
|
'/(s)eries$/i' => '\1\2eries', |
86
|
|
|
'/([^aeiouy]|qu)ies$/i' => '\1y', |
87
|
|
|
'/([lr])ves$/i' => '\1f', |
88
|
|
|
'/(tive)s$/i' => '\1', |
89
|
|
|
'/(hive)s$/i' => '\1', |
90
|
|
|
'/(drive)s$/i' => '\1', |
91
|
|
|
'/([^fo])ves$/i' => '\1fe', |
92
|
|
|
'/(^analy)ses$/i' => '\1sis', |
93
|
|
|
'/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', |
94
|
|
|
'/([ti])a$/i' => '\1um', |
95
|
|
|
'/(p)eople$/i' => '\1\2erson', |
96
|
|
|
'/(m)en$/i' => '\1an', |
97
|
|
|
'/(c)hildren$/i' => '\1\2hild', |
98
|
|
|
'/(n)ews$/i' => '\1\2ews', |
99
|
|
|
'/(n)etherlands$/i' => '\1\2etherlands', |
100
|
|
|
'/eaus$/' => 'eau', |
101
|
|
|
'/(currenc)ies$/' => '\1y', |
102
|
|
|
'/^(.*us)$/' => '\\1', |
103
|
|
|
'/s$/i' => '', |
104
|
|
|
]; |
105
|
|
|
/** |
106
|
|
|
* @var array the special rules for converting a word between its plural form and singular form. |
107
|
|
|
* The keys are the special words in singular form, and the values are the corresponding plural form. |
108
|
|
|
*/ |
109
|
|
|
public static $specials = [ |
110
|
|
|
'atlas' => 'atlases', |
111
|
|
|
'beef' => 'beefs', |
112
|
|
|
'brother' => 'brothers', |
113
|
|
|
'cafe' => 'cafes', |
114
|
|
|
'child' => 'children', |
115
|
|
|
'cookie' => 'cookies', |
116
|
|
|
'corpus' => 'corpuses', |
117
|
|
|
'cow' => 'cows', |
118
|
|
|
'curve' => 'curves', |
119
|
|
|
'foe' => 'foes', |
120
|
|
|
'ganglion' => 'ganglions', |
121
|
|
|
'genie' => 'genies', |
122
|
|
|
'genus' => 'genera', |
123
|
|
|
'graffito' => 'graffiti', |
124
|
|
|
'hoof' => 'hoofs', |
125
|
|
|
'loaf' => 'loaves', |
126
|
|
|
'man' => 'men', |
127
|
|
|
'money' => 'monies', |
128
|
|
|
'mongoose' => 'mongooses', |
129
|
|
|
'move' => 'moves', |
130
|
|
|
'mythos' => 'mythoi', |
131
|
|
|
'niche' => 'niches', |
132
|
|
|
'numen' => 'numina', |
133
|
|
|
'occiput' => 'occiputs', |
134
|
|
|
'octopus' => 'octopuses', |
135
|
|
|
'opus' => 'opuses', |
136
|
|
|
'ox' => 'oxen', |
137
|
|
|
'pasta' => 'pasta', |
138
|
|
|
'penis' => 'penises', |
139
|
|
|
'sex' => 'sexes', |
140
|
|
|
'soliloquy' => 'soliloquies', |
141
|
|
|
'testis' => 'testes', |
142
|
|
|
'trilby' => 'trilbys', |
143
|
|
|
'turf' => 'turfs', |
144
|
|
|
'wave' => 'waves', |
145
|
|
|
'Amoyese' => 'Amoyese', |
146
|
|
|
'bison' => 'bison', |
147
|
|
|
'Borghese' => 'Borghese', |
148
|
|
|
'bream' => 'bream', |
149
|
|
|
'breeches' => 'breeches', |
150
|
|
|
'britches' => 'britches', |
151
|
|
|
'buffalo' => 'buffalo', |
152
|
|
|
'cantus' => 'cantus', |
153
|
|
|
'carp' => 'carp', |
154
|
|
|
'chassis' => 'chassis', |
155
|
|
|
'clippers' => 'clippers', |
156
|
|
|
'cod' => 'cod', |
157
|
|
|
'coitus' => 'coitus', |
158
|
|
|
'Congoese' => 'Congoese', |
159
|
|
|
'contretemps' => 'contretemps', |
160
|
|
|
'corps' => 'corps', |
161
|
|
|
'debris' => 'debris', |
162
|
|
|
'diabetes' => 'diabetes', |
163
|
|
|
'djinn' => 'djinn', |
164
|
|
|
'eland' => 'eland', |
165
|
|
|
'elk' => 'elk', |
166
|
|
|
'equipment' => 'equipment', |
167
|
|
|
'Faroese' => 'Faroese', |
168
|
|
|
'flounder' => 'flounder', |
169
|
|
|
'Foochowese' => 'Foochowese', |
170
|
|
|
'gallows' => 'gallows', |
171
|
|
|
'Genevese' => 'Genevese', |
172
|
|
|
'Genoese' => 'Genoese', |
173
|
|
|
'Gilbertese' => 'Gilbertese', |
174
|
|
|
'graffiti' => 'graffiti', |
175
|
|
|
'headquarters' => 'headquarters', |
176
|
|
|
'herpes' => 'herpes', |
177
|
|
|
'hijinks' => 'hijinks', |
178
|
|
|
'Hottentotese' => 'Hottentotese', |
179
|
|
|
'information' => 'information', |
180
|
|
|
'innings' => 'innings', |
181
|
|
|
'jackanapes' => 'jackanapes', |
182
|
|
|
'Kiplingese' => 'Kiplingese', |
183
|
|
|
'Kongoese' => 'Kongoese', |
184
|
|
|
'Lucchese' => 'Lucchese', |
185
|
|
|
'mackerel' => 'mackerel', |
186
|
|
|
'Maltese' => 'Maltese', |
187
|
|
|
'mews' => 'mews', |
188
|
|
|
'moose' => 'moose', |
189
|
|
|
'mumps' => 'mumps', |
190
|
|
|
'Nankingese' => 'Nankingese', |
191
|
|
|
'news' => 'news', |
192
|
|
|
'nexus' => 'nexus', |
193
|
|
|
'Niasese' => 'Niasese', |
194
|
|
|
'Pekingese' => 'Pekingese', |
195
|
|
|
'Piedmontese' => 'Piedmontese', |
196
|
|
|
'pincers' => 'pincers', |
197
|
|
|
'Pistoiese' => 'Pistoiese', |
198
|
|
|
'pliers' => 'pliers', |
199
|
|
|
'Portuguese' => 'Portuguese', |
200
|
|
|
'proceedings' => 'proceedings', |
201
|
|
|
'rabies' => 'rabies', |
202
|
|
|
'rice' => 'rice', |
203
|
|
|
'rhinoceros' => 'rhinoceros', |
204
|
|
|
'salmon' => 'salmon', |
205
|
|
|
'Sarawakese' => 'Sarawakese', |
206
|
|
|
'scissors' => 'scissors', |
207
|
|
|
'series' => 'series', |
208
|
|
|
'Shavese' => 'Shavese', |
209
|
|
|
'shears' => 'shears', |
210
|
|
|
'siemens' => 'siemens', |
211
|
|
|
'species' => 'species', |
212
|
|
|
'swine' => 'swine', |
213
|
|
|
'testes' => 'testes', |
214
|
|
|
'trousers' => 'trousers', |
215
|
|
|
'trout' => 'trout', |
216
|
|
|
'tuna' => 'tuna', |
217
|
|
|
'Vermontese' => 'Vermontese', |
218
|
|
|
'Wenchowese' => 'Wenchowese', |
219
|
|
|
'whiting' => 'whiting', |
220
|
|
|
'wildebeest' => 'wildebeest', |
221
|
|
|
'Yengeese' => 'Yengeese', |
222
|
|
|
'software' => 'software', |
223
|
|
|
'hardware' => 'hardware', |
224
|
|
|
]; |
225
|
|
|
/** |
226
|
|
|
* @var array fallback map for transliteration used by [[transliterate()]] when intl isn't available. |
227
|
|
|
*/ |
228
|
|
|
public static $transliteration = [ |
229
|
|
|
'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE', 'Ç' => 'C', |
230
|
|
|
'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', |
231
|
|
|
'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ő' => 'O', |
232
|
|
|
'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', 'Ý' => 'Y', 'Þ' => 'TH', |
233
|
|
|
'ß' => 'ss', |
234
|
|
|
'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', |
235
|
|
|
'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', |
236
|
|
|
'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', |
237
|
|
|
'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', |
238
|
|
|
'ÿ' => 'y', |
239
|
|
|
]; |
240
|
|
|
/** |
241
|
|
|
* Shortcut for `Any-Latin; NFKD` transliteration rule. |
242
|
|
|
* |
243
|
|
|
* The rule is strict, letters will be transliterated with |
244
|
|
|
* the closest sound-representation chars. The result may contain any UTF-8 chars. For example: |
245
|
|
|
* `获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?` will be transliterated to |
246
|
|
|
* `huò qǔ dào dochira Ukraí̈nsʹka: g̀,ê, Srpska: đ, n̂, d̂! ¿Español?`. |
247
|
|
|
* |
248
|
|
|
* Used in [[transliterate()]]. |
249
|
|
|
* For detailed information see [unicode normalization forms](http://unicode.org/reports/tr15/#Normalization_Forms_Table) |
250
|
|
|
* @see http://unicode.org/reports/tr15/#Normalization_Forms_Table |
251
|
|
|
* @see transliterate() |
252
|
|
|
* @since 2.0.7 |
253
|
|
|
*/ |
254
|
|
|
const TRANSLITERATE_STRICT = 'Any-Latin; NFKD'; |
255
|
|
|
/** |
256
|
|
|
* Shortcut for `Any-Latin; Latin-ASCII` transliteration rule. |
257
|
|
|
* |
258
|
|
|
* The rule is medium, letters will be |
259
|
|
|
* transliterated to characters of Latin-1 (ISO 8859-1) ASCII table. For example: |
260
|
|
|
* `获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?` will be transliterated to |
261
|
|
|
* `huo qu dao dochira Ukrainsʹka: g,e, Srpska: d, n, d! ¿Espanol?`. |
262
|
|
|
* |
263
|
|
|
* Used in [[transliterate()]]. |
264
|
|
|
* For detailed information see [unicode normalization forms](http://unicode.org/reports/tr15/#Normalization_Forms_Table) |
265
|
|
|
* @see http://unicode.org/reports/tr15/#Normalization_Forms_Table |
266
|
|
|
* @see transliterate() |
267
|
|
|
* @since 2.0.7 |
268
|
|
|
*/ |
269
|
|
|
const TRANSLITERATE_MEDIUM = 'Any-Latin; Latin-ASCII'; |
270
|
|
|
/** |
271
|
|
|
* Shortcut for `Any-Latin; Latin-ASCII; [\u0080-\uffff] remove` transliteration rule. |
272
|
|
|
* |
273
|
|
|
* The rule is loose, |
274
|
|
|
* letters will be transliterated with the characters of Basic Latin Unicode Block. |
275
|
|
|
* For example: |
276
|
|
|
* `获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?` will be transliterated to |
277
|
|
|
* `huo qu dao dochira Ukrainska: g,e, Srpska: d, n, d! Espanol?`. |
278
|
|
|
* |
279
|
|
|
* Used in [[transliterate()]]. |
280
|
|
|
* For detailed information see [unicode normalization forms](http://unicode.org/reports/tr15/#Normalization_Forms_Table) |
281
|
|
|
* @see http://unicode.org/reports/tr15/#Normalization_Forms_Table |
282
|
|
|
* @see transliterate() |
283
|
|
|
* @since 2.0.7 |
284
|
|
|
*/ |
285
|
|
|
const TRANSLITERATE_LOOSE = 'Any-Latin; Latin-ASCII; [\u0080-\uffff] remove'; |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* @var mixed Either a [[\Transliterator]], or a string from which a [[\Transliterator]] can be built |
289
|
|
|
* for transliteration. Used by [[transliterate()]] when intl is available. Defaults to [[TRANSLITERATE_LOOSE]] |
290
|
|
|
* @see https://www.php.net/manual/en/transliterator.transliterate.php |
291
|
|
|
*/ |
292
|
|
|
public static $transliterator = self::TRANSLITERATE_LOOSE; |
293
|
|
|
|
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Converts a word to its plural form. |
297
|
|
|
* Note that this is for English only! |
298
|
|
|
* For example, 'apple' will become 'apples', and 'child' will become 'children'. |
299
|
|
|
* @param string $word the word to be pluralized |
300
|
9 |
|
* @return string the pluralized word |
301
|
|
|
*/ |
302
|
9 |
|
public static function pluralize($word) |
303
|
1 |
|
{ |
304
|
|
|
if (empty($word)) { |
305
|
9 |
|
return (string) $word; |
306
|
9 |
|
} |
307
|
9 |
|
if (isset(static::$specials[$word])) { |
308
|
|
|
return static::$specials[$word]; |
309
|
|
|
} |
310
|
|
|
foreach (static::$plurals as $rule => $replacement) { |
311
|
|
|
if (preg_match($rule, $word)) { |
312
|
|
|
return preg_replace($rule, $replacement, $word); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
return $word; |
317
|
|
|
} |
318
|
|
|
|
319
|
2 |
|
/** |
320
|
|
|
* Returns the singular of the $word. |
321
|
2 |
|
* @param string $word the english word to singularize |
322
|
2 |
|
* @return string Singular noun. |
323
|
1 |
|
*/ |
324
|
|
|
public static function singularize($word) |
325
|
2 |
|
{ |
326
|
2 |
|
if (empty($word)) { |
327
|
2 |
|
return (string) $word; |
328
|
|
|
} |
329
|
|
|
$result = array_search($word, static::$specials, true); |
330
|
|
|
if ($result !== false) { |
331
|
1 |
|
return $result; |
332
|
|
|
} |
333
|
|
|
foreach (static::$singulars as $rule => $replacement) { |
334
|
|
|
if (preg_match($rule, $word)) { |
335
|
|
|
return preg_replace($rule, $replacement, $word); |
336
|
|
|
} |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
return $word; |
340
|
|
|
} |
341
|
1 |
|
|
342
|
|
|
/** |
343
|
1 |
|
* Converts an underscored or CamelCase word into a English |
344
|
|
|
* sentence. |
345
|
1 |
|
* @param string $words |
346
|
|
|
* @param bool $ucAll whether to set all words to uppercase |
347
|
|
|
* @return string |
348
|
|
|
*/ |
349
|
|
|
public static function titleize($words, $ucAll = false) |
350
|
|
|
{ |
351
|
|
|
if (empty($words)) { |
352
|
|
|
return (string) $words; |
353
|
|
|
} |
354
|
|
|
$words = static::humanize(static::underscore($words), $ucAll); |
355
|
|
|
|
356
|
|
|
return $ucAll ? StringHelper::mb_ucwords($words, self::encoding()) : StringHelper::mb_ucfirst($words, self::encoding()); |
357
|
|
|
} |
358
|
84 |
|
|
359
|
|
|
/** |
360
|
84 |
|
* Returns given word as CamelCased. |
361
|
|
|
* |
362
|
|
|
* Converts a word like "send_email" to "SendEmail". It |
363
|
|
|
* will remove non alphanumeric character from the word, so |
364
|
|
|
* "who's online" will be converted to "WhoSOnline". |
365
|
|
|
* @param string $word the word to CamelCase |
366
|
|
|
* @return string |
367
|
|
|
* @see variablize() |
368
|
|
|
*/ |
369
|
|
|
public static function camelize($word) |
370
|
141 |
|
{ |
371
|
|
|
if (empty($word)) { |
372
|
141 |
|
return (string) $word; |
373
|
141 |
|
} |
374
|
|
|
return str_replace(' ', '', StringHelper::mb_ucwords(preg_replace('/[^\pL\pN]+/u', ' ', $word), self::encoding())); |
375
|
|
|
} |
376
|
141 |
|
|
377
|
|
|
/** |
378
|
141 |
|
* Converts a CamelCase name into space-separated words. |
379
|
|
|
* For example, 'PostTag' will be converted to 'Post Tag'. |
380
|
|
|
* @param string $name the string to be converted |
381
|
|
|
* @param bool $ucwords whether to capitalize the first letter in each word |
382
|
|
|
* @return string the resulting words |
383
|
|
|
*/ |
384
|
|
|
public static function camel2words($name, $ucwords = true) |
385
|
|
|
{ |
386
|
|
|
if (empty($name)) { |
387
|
|
|
return (string) $name; |
388
|
|
|
} |
389
|
|
|
// Add a space before any uppercase letter preceded by a lowercase letter (xY => x Y) |
390
|
29 |
|
// and any uppercase letter preceded by an uppercase letter and followed by a lowercase letter (XYz => X Yz) |
391
|
|
|
$label = preg_replace('/(?<=\p{Ll})\p{Lu}|(?<=[\p{L}\d])\p{Lu}(?=\p{Ll})|(\d+)/u', ' \0', $name); |
392
|
29 |
|
|
393
|
29 |
|
$label = mb_strtolower(trim(str_replace(['-', '_', '.'], ' ', $label)), self::encoding()); |
394
|
22 |
|
|
395
|
|
|
return $ucwords ? StringHelper::mb_ucwords($label, self::encoding()) : $label; |
396
|
|
|
} |
397
|
8 |
|
|
398
|
|
|
/** |
399
|
|
|
* Converts a CamelCase name into an ID in lowercase. |
400
|
|
|
* Words in the ID may be concatenated using the specified character (defaults to '-'). |
401
|
|
|
* For example, 'PostTag' will be converted to 'post-tag'. |
402
|
|
|
* @param string $name the string to be converted |
403
|
|
|
* @param string $separator the character used to concatenate the words in the ID |
404
|
|
|
* @param bool|string $strict whether to insert a separator between two consecutive uppercase chars, defaults to false |
405
|
|
|
* @return string the resulting ID |
406
|
|
|
*/ |
407
|
|
|
public static function camel2id($name, $separator = '-', $strict = false) |
408
|
2 |
|
{ |
409
|
|
|
if (empty($name)) { |
410
|
2 |
|
return (string) $name; |
411
|
|
|
} |
412
|
|
|
$regex = $strict ? '/\p{Lu}/u' : '/(?<!\p{Lu})\p{Lu}/u'; |
413
|
|
|
if ($separator === '_') { |
414
|
|
|
return mb_strtolower(trim(preg_replace($regex, '_\0', $name), '_'), self::encoding()); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
return mb_strtolower(trim(str_replace('_', $separator, preg_replace($regex, $separator . '\0', $name)), $separator), self::encoding()); |
418
|
29 |
|
} |
419
|
|
|
|
420
|
29 |
|
/** |
421
|
|
|
* Converts an ID into a CamelCase name. |
422
|
|
|
* Words in the ID separated by `$separator` (defaults to '-') will be concatenated into a CamelCase name. |
423
|
|
|
* For example, 'post-tag' is converted to 'PostTag'. |
424
|
|
|
* @param string $id the ID to be converted |
425
|
|
|
* @param string $separator the character used to separate the words in the ID |
426
|
|
|
* @return string the resulting CamelCase name |
427
|
|
|
*/ |
428
|
|
|
public static function id2camel($id, $separator = '-') |
429
|
2 |
|
{ |
430
|
|
|
if (empty($id)) { |
431
|
2 |
|
return (string) $id; |
432
|
2 |
|
} |
433
|
|
|
return str_replace(' ', '', StringHelper::mb_ucwords(str_replace($separator, ' ', $id), self::encoding())); |
434
|
2 |
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Converts any "CamelCased" into an "underscored_word". |
438
|
|
|
* @param string $words the word(s) to underscore |
439
|
|
|
* @return string |
440
|
|
|
*/ |
441
|
|
|
public static function underscore($words) |
442
|
|
|
{ |
443
|
|
|
if (empty($words)) { |
444
|
|
|
return (string) $words; |
445
|
|
|
} |
446
|
1 |
|
return mb_strtolower(preg_replace('/(?<=\\pL)(\\p{Lu})/u', '_\\1', $words), self::encoding()); |
447
|
|
|
} |
448
|
1 |
|
|
449
|
|
|
/** |
450
|
1 |
|
* Returns a human-readable string from $word. |
451
|
|
|
* @param string $word the string to humanize |
452
|
|
|
* @param bool $ucAll whether to set all words to uppercase or not |
453
|
|
|
* @return string |
454
|
|
|
*/ |
455
|
|
|
public static function humanize($word, $ucAll = false) |
456
|
|
|
{ |
457
|
|
|
if (empty($word)) { |
458
|
|
|
return (string) $word; |
459
|
|
|
} |
460
|
1 |
|
$word = str_replace('_', ' ', preg_replace('/_id$/', '', $word)); |
461
|
|
|
$encoding = self::encoding(); |
462
|
1 |
|
|
463
|
|
|
return $ucAll ? StringHelper::mb_ucwords($word, $encoding) : StringHelper::mb_ucfirst($word, $encoding); |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* Same as camelize but first char is in lowercase. |
468
|
|
|
* |
469
|
|
|
* Converts a word like "send_email" to "sendEmail". It |
470
|
|
|
* will remove non alphanumeric character from the word, so |
471
|
|
|
* "who's online" will be converted to "whoSOnline". |
472
|
|
|
* @param string $word to lowerCamelCase |
473
|
|
|
* @return string |
474
|
|
|
*/ |
475
|
|
|
public static function variablize($word) |
476
|
|
|
{ |
477
|
|
|
if (empty($word)) { |
478
|
12 |
|
return (string) $word; |
479
|
|
|
} |
480
|
12 |
|
$word = static::camelize($word); |
481
|
12 |
|
|
482
|
|
|
return mb_strtolower(mb_substr($word, 0, 1, self::encoding())) . mb_substr($word, 1, null, self::encoding()); |
483
|
1 |
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
12 |
|
* Converts a class name to its table name (pluralized) naming conventions. |
487
|
12 |
|
* |
488
|
12 |
|
* For example, converts "Person" to "people". |
489
|
12 |
|
* @param string $className the class name for getting related table_name |
490
|
|
|
* @return string |
491
|
12 |
|
*/ |
492
|
12 |
|
public static function tableize($className) |
493
|
12 |
|
{ |
494
|
|
|
if (empty($className)) { |
495
|
|
|
return (string) $className; |
496
|
12 |
|
} |
497
|
|
|
return static::pluralize(static::underscore($className)); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* Returns a string with all spaces converted to given replacement, |
502
|
|
|
* non word characters removed and the rest of characters transliterated. |
503
|
|
|
* |
504
|
|
|
* If intl extension isn't available uses fallback that converts latin characters only |
505
|
|
|
* and removes the rest. You may customize characters map via $transliteration property |
506
|
|
|
* of the helper. |
507
|
|
|
* |
508
|
|
|
* @param string $string An arbitrary string to convert |
509
|
|
|
* @param string $replacement The replacement to use for spaces |
510
|
|
|
* @param bool $lowercase whether to return the string in lowercase or not. Defaults to `true`. |
511
|
|
|
* @return string The converted string. |
512
|
23 |
|
*/ |
513
|
|
|
public static function slug($string, $replacement = '-', $lowercase = true) |
514
|
23 |
|
{ |
515
|
22 |
|
if (empty($string)) { |
516
|
11 |
|
return (string) $string; |
517
|
|
|
} |
518
|
|
|
if ((string)$replacement !== '') { |
519
|
22 |
|
$parts = explode($replacement, static::transliterate($string)); |
520
|
|
|
} else { |
521
|
|
|
$parts = [static::transliterate($string)]; |
522
|
2 |
|
} |
523
|
|
|
|
524
|
|
|
$replaced = array_map(function ($element) use ($replacement) { |
525
|
|
|
$element = preg_replace('/[^a-zA-Z0-9=\s—–-]+/u', '', $element); |
526
|
|
|
return preg_replace('/[=\s—–-]+/u', $replacement, $element); |
527
|
|
|
}, $parts); |
528
|
22 |
|
|
529
|
|
|
$string = trim(implode($replacement, $replaced), $replacement); |
530
|
22 |
|
if ((string)$replacement !== '') { |
531
|
|
|
$string = preg_replace('#' . preg_quote($replacement) . '+#', $replacement, $string); |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
return $lowercase ? strtolower($string) : $string; |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
/** |
538
|
|
|
* Returns transliterated version of a string. |
539
|
|
|
* |
540
|
1 |
|
* If intl extension isn't available uses fallback that converts latin characters only |
541
|
|
|
* and removes the rest. You may customize characters map via $transliteration property |
542
|
1 |
|
* of the helper. |
543
|
|
|
* |
544
|
|
|
* @param string $string input string |
545
|
|
|
* @param string|\Transliterator|null $transliterator either a [[\Transliterator]] or a string |
546
|
|
|
* from which a [[\Transliterator]] can be built. |
547
|
|
|
* @return string |
548
|
|
|
* @since 2.0.7 this method is public. |
549
|
|
|
*/ |
550
|
1 |
|
public static function transliterate($string, $transliterator = null) |
551
|
|
|
{ |
552
|
1 |
|
if (empty($string)) { |
553
|
1 |
|
return (string) $string; |
554
|
|
|
} |
555
|
1 |
|
if (static::hasIntl()) { |
556
|
1 |
|
if ($transliterator === null) { |
557
|
1 |
|
$transliterator = static::$transliterator; |
558
|
1 |
|
} |
559
|
1 |
|
|
560
|
1 |
|
return transliterator_transliterate($transliterator, $string); |
561
|
1 |
|
} |
562
|
|
|
|
563
|
1 |
|
return strtr($string, static::$transliteration); |
564
|
|
|
} |
565
|
|
|
|
566
|
|
|
/** |
567
|
|
|
* @return bool if intl extension is loaded |
568
|
|
|
*/ |
569
|
|
|
protected static function hasIntl() |
570
|
|
|
{ |
571
|
|
|
return extension_loaded('intl'); |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Converts a table name to its class name. |
576
|
|
|
* |
577
|
|
|
* For example, converts "people" to "Person". |
578
|
|
|
* @param string $tableName |
579
|
|
|
* @return string |
580
|
|
|
*/ |
581
|
|
|
public static function classify($tableName) |
582
|
|
|
{ |
583
|
|
|
if (empty($tableName)) { |
584
|
|
|
return (string) $tableName; |
585
|
|
|
} |
586
|
|
|
return static::camelize(static::singularize($tableName)); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
/** |
590
|
|
|
* Converts number to its ordinal English form. For example, converts 13 to 13th, 2 to 2nd ... |
591
|
|
|
* @param int $number the number to get its ordinal value |
592
|
|
|
* @return string |
593
|
|
|
*/ |
594
|
|
|
public static function ordinalize($number) |
595
|
11 |
|
{ |
596
|
|
|
if (in_array($number % 100, range(11, 13))) { |
597
|
11 |
|
return $number . 'th'; |
598
|
11 |
|
} |
599
|
|
|
switch ($number % 10) { |
600
|
11 |
|
case 1: |
601
|
11 |
|
return $number . 'st'; |
602
|
|
|
case 2: |
603
|
11 |
|
return $number . 'nd'; |
604
|
11 |
|
case 3: |
605
|
1 |
|
return $number . 'rd'; |
606
|
11 |
|
default: |
607
|
1 |
|
return $number . 'th'; |
608
|
11 |
|
} |
609
|
11 |
|
} |
610
|
|
|
|
611
|
1 |
|
/** |
612
|
|
|
* Converts a list of words into a sentence. |
613
|
|
|
* |
614
|
|
|
* Special treatment is done for the last few words. For example, |
615
|
|
|
* |
616
|
|
|
* ```php |
617
|
|
|
* $words = ['Spain', 'France']; |
618
|
260 |
|
* echo Inflector::sentence($words); |
619
|
|
|
* // output: Spain and France |
620
|
260 |
|
* |
621
|
|
|
* $words = ['Spain', 'France', 'Italy']; |
622
|
|
|
* echo Inflector::sentence($words); |
623
|
|
|
* // output: Spain, France and Italy |
624
|
|
|
* |
625
|
|
|
* $words = ['Spain', 'France', 'Italy']; |
626
|
|
|
* echo Inflector::sentence($words, ' & '); |
627
|
|
|
* // output: Spain, France & Italy |
628
|
|
|
* ``` |
629
|
|
|
* |
630
|
|
|
* @param array $words the words to be converted into an string |
631
|
|
|
* @param string|null $twoWordsConnector the string connecting words when there are only two |
632
|
|
|
* @param string|null $lastWordConnector the string connecting the last two words. If this is null, it will |
633
|
|
|
* take the value of `$twoWordsConnector`. |
634
|
|
|
* @param string $connector the string connecting words other than those connected by |
635
|
|
|
* $lastWordConnector and $twoWordsConnector |
636
|
|
|
* @return string the generated sentence |
637
|
|
|
* @since 2.0.1 |
638
|
|
|
*/ |
639
|
|
|
public static function sentence(array $words, $twoWordsConnector = null, $lastWordConnector = null, $connector = ', ') |
640
|
|
|
{ |
641
|
|
|
if ($twoWordsConnector === null) { |
642
|
|
|
$twoWordsConnector = Yii::t('yii', ' and '); |
643
|
|
|
} |
644
|
|
|
if ($lastWordConnector === null) { |
645
|
|
|
$lastWordConnector = $twoWordsConnector; |
646
|
|
|
} |
647
|
|
|
switch (count($words)) { |
648
|
|
|
case 0: |
649
|
|
|
return ''; |
650
|
|
|
case 1: |
651
|
|
|
return reset($words); |
652
|
|
|
case 2: |
653
|
|
|
return implode($twoWordsConnector, $words); |
654
|
|
|
default: |
655
|
|
|
return implode($connector, array_slice($words, 0, -1)) . $lastWordConnector . end($words); |
656
|
|
|
} |
657
|
|
|
} |
658
|
|
|
|
659
|
|
|
/** |
660
|
|
|
* @return string |
661
|
|
|
*/ |
662
|
|
|
private static function encoding() |
663
|
|
|
{ |
664
|
|
|
return isset(Yii::$app) ? Yii::$app->charset : 'UTF-8'; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
} |
668
|
|
|
|