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
|
|
|
]; |
223
|
|
|
/** |
224
|
|
|
* @var array fallback map for transliteration used by [[transliterate()]] when intl isn't available. |
225
|
|
|
*/ |
226
|
|
|
public static $transliteration = [ |
227
|
|
|
'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE', 'Ç' => 'C', |
228
|
|
|
'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', |
229
|
|
|
'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ő' => 'O', |
230
|
|
|
'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', 'Ý' => 'Y', 'Þ' => 'TH', |
231
|
|
|
'ß' => 'ss', |
232
|
|
|
'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', |
233
|
|
|
'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', |
234
|
|
|
'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', |
235
|
|
|
'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', |
236
|
|
|
'ÿ' => 'y', |
237
|
|
|
]; |
238
|
|
|
/** |
239
|
|
|
* Shortcut for `Any-Latin; NFKD` transliteration rule. |
240
|
|
|
* |
241
|
|
|
* The rule is strict, letters will be transliterated with |
242
|
|
|
* the closest sound-representation chars. The result may contain any UTF-8 chars. For example: |
243
|
|
|
* `获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?` will be transliterated to |
244
|
|
|
* `huò qǔ dào dochira Ukraí̈nsʹka: g̀,ê, Srpska: đ, n̂, d̂! ¿Español?`. |
245
|
|
|
* |
246
|
|
|
* Used in [[transliterate()]]. |
247
|
|
|
* For detailed information see [unicode normalization forms](http://unicode.org/reports/tr15/#Normalization_Forms_Table) |
248
|
|
|
* @see http://unicode.org/reports/tr15/#Normalization_Forms_Table |
249
|
|
|
* @see transliterate() |
250
|
|
|
* @since 2.0.7 |
251
|
|
|
*/ |
252
|
|
|
const TRANSLITERATE_STRICT = 'Any-Latin; NFKD'; |
253
|
|
|
/** |
254
|
|
|
* Shortcut for `Any-Latin; Latin-ASCII` transliteration rule. |
255
|
|
|
* |
256
|
|
|
* The rule is medium, letters will be |
257
|
|
|
* transliterated to characters of Latin-1 (ISO 8859-1) ASCII table. For example: |
258
|
|
|
* `获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?` will be transliterated to |
259
|
|
|
* `huo qu dao dochira Ukrainsʹka: g,e, Srpska: d, n, d! ¿Espanol?`. |
260
|
|
|
* |
261
|
|
|
* Used in [[transliterate()]]. |
262
|
|
|
* For detailed information see [unicode normalization forms](http://unicode.org/reports/tr15/#Normalization_Forms_Table) |
263
|
|
|
* @see http://unicode.org/reports/tr15/#Normalization_Forms_Table |
264
|
|
|
* @see transliterate() |
265
|
|
|
* @since 2.0.7 |
266
|
|
|
*/ |
267
|
|
|
const TRANSLITERATE_MEDIUM = 'Any-Latin; Latin-ASCII'; |
268
|
|
|
/** |
269
|
|
|
* Shortcut for `Any-Latin; Latin-ASCII; [\u0080-\uffff] remove` transliteration rule. |
270
|
|
|
* |
271
|
|
|
* The rule is loose, |
272
|
|
|
* letters will be transliterated with the characters of Basic Latin Unicode Block. |
273
|
|
|
* For example: |
274
|
|
|
* `获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?` will be transliterated to |
275
|
|
|
* `huo qu dao dochira Ukrainska: g,e, Srpska: d, n, d! Espanol?`. |
276
|
|
|
* |
277
|
|
|
* Used in [[transliterate()]]. |
278
|
|
|
* For detailed information see [unicode normalization forms](http://unicode.org/reports/tr15/#Normalization_Forms_Table) |
279
|
|
|
* @see http://unicode.org/reports/tr15/#Normalization_Forms_Table |
280
|
|
|
* @see transliterate() |
281
|
|
|
* @since 2.0.7 |
282
|
|
|
*/ |
283
|
|
|
const TRANSLITERATE_LOOSE = 'Any-Latin; Latin-ASCII; [\u0080-\uffff] remove'; |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* @var mixed Either a [[\Transliterator]], or a string from which a [[\Transliterator]] can be built |
287
|
|
|
* for transliteration. Used by [[transliterate()]] when intl is available. Defaults to [[TRANSLITERATE_LOOSE]] |
288
|
|
|
* @see http://php.net/manual/en/transliterator.transliterate.php |
289
|
|
|
*/ |
290
|
|
|
public static $transliterator = self::TRANSLITERATE_LOOSE; |
291
|
|
|
|
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* Converts a word to its plural form. |
295
|
|
|
* Note that this is for English only! |
296
|
|
|
* For example, 'apple' will become 'apples', and 'child' will become 'children'. |
297
|
|
|
* @param string $word the word to be pluralized |
298
|
|
|
* @return string the pluralized word |
299
|
|
|
*/ |
300
|
9 |
|
public static function pluralize($word) |
301
|
|
|
{ |
302
|
9 |
|
if (isset(static::$specials[$word])) { |
303
|
1 |
|
return static::$specials[$word]; |
304
|
|
|
} |
305
|
9 |
|
foreach (static::$plurals as $rule => $replacement) { |
306
|
9 |
|
if (preg_match($rule, $word)) { |
307
|
9 |
|
return preg_replace($rule, $replacement, $word); |
308
|
|
|
} |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
return $word; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Returns the singular of the $word. |
316
|
|
|
* @param string $word the english word to singularize |
317
|
|
|
* @return string Singular noun. |
318
|
|
|
*/ |
319
|
2 |
|
public static function singularize($word) |
320
|
|
|
{ |
321
|
2 |
|
$result = array_search($word, static::$specials, true); |
322
|
2 |
|
if ($result !== false) { |
323
|
1 |
|
return $result; |
324
|
|
|
} |
325
|
2 |
|
foreach (static::$singulars as $rule => $replacement) { |
326
|
2 |
|
if (preg_match($rule, $word)) { |
327
|
2 |
|
return preg_replace($rule, $replacement, $word); |
328
|
|
|
} |
329
|
|
|
} |
330
|
|
|
|
331
|
1 |
|
return $word; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Converts an underscored or CamelCase word into a English |
336
|
|
|
* sentence. |
337
|
|
|
* @param string $words |
338
|
|
|
* @param bool $ucAll whether to set all words to uppercase |
339
|
|
|
* @return string |
340
|
|
|
*/ |
341
|
1 |
|
public static function titleize($words, $ucAll = false) |
342
|
|
|
{ |
343
|
1 |
|
$words = static::humanize(static::underscore($words), $ucAll); |
344
|
|
|
|
345
|
1 |
|
return $ucAll ? mb_convert_case($words, MB_CASE_TITLE, self::encoding()) : self::mb_ucfirst($words, self::encoding()); |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
/** |
349
|
|
|
* Returns given word as CamelCased. |
350
|
|
|
* |
351
|
|
|
* Converts a word like "send_email" to "SendEmail". It |
352
|
|
|
* will remove non alphanumeric character from the word, so |
353
|
|
|
* "who's online" will be converted to "WhoSOnline". |
354
|
|
|
* @see variablize() |
355
|
|
|
* @param string $word the word to CamelCase |
356
|
|
|
* @return string |
357
|
|
|
*/ |
358
|
3 |
|
public static function camelize($word) |
359
|
|
|
{ |
360
|
3 |
|
return str_replace(' ', '', mb_convert_case(preg_replace('/[^\pL\pN]+/u', ' ', $word), MB_CASE_TITLE, self::encoding())); |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
/** |
364
|
|
|
* Converts a CamelCase name into space-separated words. |
365
|
|
|
* For example, 'PostTag' will be converted to 'Post Tag'. |
366
|
|
|
* @param string $name the string to be converted |
367
|
|
|
* @param bool $ucwords whether to capitalize the first letter in each word |
368
|
|
|
* @return string the resulting words |
369
|
|
|
*/ |
370
|
96 |
|
public static function camel2words($name, $ucwords = true) |
371
|
|
|
{ |
372
|
96 |
|
$label = mb_strtolower(trim(str_replace([ |
373
|
96 |
|
'-', |
374
|
|
|
'_', |
375
|
|
|
'.', |
376
|
96 |
|
], ' ', preg_replace('/(\p{Lu})/u', ' \0', $name))), self::encoding()); |
377
|
|
|
|
378
|
96 |
|
return $ucwords ? mb_convert_case($label, MB_CASE_TITLE, self::encoding()) : $label; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Converts a CamelCase name into an ID in lowercase. |
383
|
|
|
* Words in the ID may be concatenated using the specified character (defaults to '-'). |
384
|
|
|
* For example, 'PostTag' will be converted to 'post-tag'. |
385
|
|
|
* @param string $name the string to be converted |
386
|
|
|
* @param string $separator the character used to concatenate the words in the ID |
387
|
|
|
* @param bool|string $strict whether to insert a separator between two consecutive uppercase chars, defaults to false |
388
|
|
|
* @return string the resulting ID |
389
|
|
|
*/ |
390
|
37 |
|
public static function camel2id($name, $separator = '-', $strict = false) |
391
|
|
|
{ |
392
|
37 |
|
$regex = $strict ? '/\p{Lu}/u' : '/(?<!\p{Lu})\p{Lu}/u'; |
393
|
37 |
|
if ($separator === '_') { |
394
|
16 |
|
return mb_strtolower(trim(preg_replace($regex, '_\0', $name), '_'), self::encoding()); |
395
|
|
|
} |
396
|
|
|
|
397
|
22 |
|
return mb_strtolower(trim(str_replace('_', $separator, preg_replace($regex, $separator . '\0', $name)), $separator), self::encoding()); |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
/** |
401
|
|
|
* Converts an ID into a CamelCase name. |
402
|
|
|
* Words in the ID separated by `$separator` (defaults to '-') will be concatenated into a CamelCase name. |
403
|
|
|
* For example, 'post-tag' is converted to 'PostTag'. |
404
|
|
|
* @param string $id the ID to be converted |
405
|
|
|
* @param string $separator the character used to separate the words in the ID |
406
|
|
|
* @return string the resulting CamelCase name |
407
|
|
|
*/ |
408
|
2 |
|
public static function id2camel($id, $separator = '-') |
409
|
|
|
{ |
410
|
2 |
|
return str_replace(' ', '', mb_convert_case(str_replace($separator, ' ', $id), MB_CASE_TITLE, self::encoding())); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
|
|
* Converts any "CamelCased" into an "underscored_word". |
415
|
|
|
* @param string $words the word(s) to underscore |
416
|
|
|
* @return string |
417
|
|
|
*/ |
418
|
3 |
|
public static function underscore($words) |
419
|
|
|
{ |
420
|
3 |
|
return mb_strtolower(preg_replace('/(?<=\\pL)(\\p{Lu})/u', '_\\1', $words), self::encoding()); |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Returns a human-readable string from $word. |
425
|
|
|
* @param string $word the string to humanize |
426
|
|
|
* @param bool $ucAll whether to set all words to uppercase or not |
427
|
|
|
* @return string |
428
|
|
|
*/ |
429
|
2 |
|
public static function humanize($word, $ucAll = false) |
430
|
|
|
{ |
431
|
2 |
|
$word = str_replace('_', ' ', preg_replace('/_id$/', '', $word)); |
432
|
2 |
|
$encoding = self::encoding(); |
433
|
|
|
|
434
|
2 |
|
return $ucAll ? mb_convert_case($word, MB_CASE_TITLE, $encoding) : self::mb_ucfirst($word, $encoding); |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* Same as camelize but first char is in lowercase. |
439
|
|
|
* |
440
|
|
|
* Converts a word like "send_email" to "sendEmail". It |
441
|
|
|
* will remove non alphanumeric character from the word, so |
442
|
|
|
* "who's online" will be converted to "whoSOnline". |
443
|
|
|
* @param string $word to lowerCamelCase |
444
|
|
|
* @return string |
445
|
|
|
*/ |
446
|
1 |
|
public static function variablize($word) |
447
|
|
|
{ |
448
|
1 |
|
$word = static::camelize($word); |
449
|
|
|
|
450
|
1 |
|
return mb_strtolower(mb_substr($word, 0, 1, self::encoding())) . mb_substr($word, 1, null, self::encoding()); |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* Converts a class name to its table name (pluralized) naming conventions. |
455
|
|
|
* |
456
|
|
|
* For example, converts "Person" to "people". |
457
|
|
|
* @param string $className the class name for getting related table_name |
458
|
|
|
* @return string |
459
|
|
|
*/ |
460
|
1 |
|
public static function tableize($className) |
461
|
|
|
{ |
462
|
1 |
|
return static::pluralize(static::underscore($className)); |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
/** |
466
|
|
|
* Returns a string with all spaces converted to given replacement, |
467
|
|
|
* non word characters removed and the rest of characters transliterated. |
468
|
|
|
* |
469
|
|
|
* If intl extension isn't available uses fallback that converts latin characters only |
470
|
|
|
* and removes the rest. You may customize characters map via $transliteration property |
471
|
|
|
* of the helper. |
472
|
|
|
* |
473
|
|
|
* @param string $string An arbitrary string to convert |
474
|
|
|
* @param string $replacement The replacement to use for spaces |
475
|
|
|
* @param bool $lowercase whether to return the string in lowercase or not. Defaults to `true`. |
476
|
|
|
* @return string The converted string. |
477
|
|
|
*/ |
478
|
11 |
|
public static function slug($string, $replacement = '-', $lowercase = true) |
479
|
|
|
{ |
480
|
11 |
|
$string = static::transliterate($string); |
481
|
11 |
|
$string = preg_replace('/[^a-zA-Z0-9=\s—–-]+/u', '', $string); |
482
|
11 |
|
$string = preg_replace('/[=\s—–-]+/u', $replacement, $string); |
483
|
11 |
|
$string = trim($string, $replacement); |
484
|
|
|
|
485
|
11 |
|
return $lowercase ? strtolower($string) : $string; |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* Returns transliterated version of a string. |
490
|
|
|
* |
491
|
|
|
* If intl extension isn't available uses fallback that converts latin characters only |
492
|
|
|
* and removes the rest. You may customize characters map via $transliteration property |
493
|
|
|
* of the helper. |
494
|
|
|
* |
495
|
|
|
* @param string $string input string |
496
|
|
|
* @param string|\Transliterator $transliterator either a [[\Transliterator]] or a string |
497
|
|
|
* from which a [[\Transliterator]] can be built. |
498
|
|
|
* @return string |
499
|
|
|
* @since 2.0.7 this method is public. |
500
|
|
|
*/ |
501
|
18 |
|
public static function transliterate($string, $transliterator = null) |
502
|
|
|
{ |
503
|
18 |
|
if (static::hasIntl()) { |
504
|
17 |
|
if ($transliterator === null) { |
505
|
10 |
|
$transliterator = static::$transliterator; |
506
|
|
|
} |
507
|
|
|
|
508
|
17 |
|
return transliterator_transliterate($transliterator, $string); |
509
|
|
|
} |
510
|
|
|
|
511
|
2 |
|
return strtr($string, static::$transliteration); |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* @return bool if intl extension is loaded |
516
|
|
|
*/ |
517
|
17 |
|
protected static function hasIntl() |
518
|
|
|
{ |
519
|
17 |
|
return extension_loaded('intl'); |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
/** |
523
|
|
|
* Converts a table name to its class name. |
524
|
|
|
* |
525
|
|
|
* For example, converts "people" to "Person". |
526
|
|
|
* @param string $tableName |
527
|
|
|
* @return string |
528
|
|
|
*/ |
529
|
1 |
|
public static function classify($tableName) |
530
|
|
|
{ |
531
|
1 |
|
return static::camelize(static::singularize($tableName)); |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
/** |
535
|
|
|
* Converts number to its ordinal English form. For example, converts 13 to 13th, 2 to 2nd ... |
536
|
|
|
* @param int $number the number to get its ordinal value |
537
|
|
|
* @return string |
538
|
|
|
*/ |
539
|
1 |
|
public static function ordinalize($number) |
540
|
|
|
{ |
541
|
1 |
|
if (in_array($number % 100, range(11, 13))) { |
542
|
1 |
|
return $number . 'th'; |
543
|
|
|
} |
544
|
1 |
|
switch ($number % 10) { |
545
|
1 |
|
case 1: |
546
|
1 |
|
return $number . 'st'; |
547
|
1 |
|
case 2: |
548
|
1 |
|
return $number . 'nd'; |
549
|
1 |
|
case 3: |
550
|
1 |
|
return $number . 'rd'; |
551
|
|
|
default: |
552
|
1 |
|
return $number . 'th'; |
553
|
|
|
} |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
/** |
557
|
|
|
* Converts a list of words into a sentence. |
558
|
|
|
* |
559
|
|
|
* Special treatment is done for the last few words. For example, |
560
|
|
|
* |
561
|
|
|
* ```php |
562
|
|
|
* $words = ['Spain', 'France']; |
563
|
|
|
* echo Inflector::sentence($words); |
564
|
|
|
* // output: Spain and France |
565
|
|
|
* |
566
|
|
|
* $words = ['Spain', 'France', 'Italy']; |
567
|
|
|
* echo Inflector::sentence($words); |
568
|
|
|
* // output: Spain, France and Italy |
569
|
|
|
* |
570
|
|
|
* $words = ['Spain', 'France', 'Italy']; |
571
|
|
|
* echo Inflector::sentence($words, ' & '); |
572
|
|
|
* // output: Spain, France & Italy |
573
|
|
|
* ``` |
574
|
|
|
* |
575
|
|
|
* @param array $words the words to be converted into an string |
576
|
|
|
* @param string $twoWordsConnector the string connecting words when there are only two |
577
|
|
|
* @param string $lastWordConnector the string connecting the last two words. If this is null, it will |
578
|
|
|
* take the value of `$twoWordsConnector`. |
579
|
|
|
* @param string $connector the string connecting words other than those connected by |
580
|
|
|
* $lastWordConnector and $twoWordsConnector |
581
|
|
|
* @return string the generated sentence |
582
|
|
|
* @since 2.0.1 |
583
|
|
|
*/ |
584
|
7 |
|
public static function sentence(array $words, $twoWordsConnector = null, $lastWordConnector = null, $connector = ', ') |
585
|
|
|
{ |
586
|
7 |
|
if ($twoWordsConnector === null) { |
587
|
7 |
|
$twoWordsConnector = Yii::t('yii', ' and '); |
588
|
|
|
} |
589
|
7 |
|
if ($lastWordConnector === null) { |
590
|
7 |
|
$lastWordConnector = $twoWordsConnector; |
591
|
|
|
} |
592
|
7 |
|
switch (count($words)) { |
593
|
7 |
|
case 0: |
594
|
1 |
|
return ''; |
595
|
7 |
|
case 1: |
596
|
1 |
|
return reset($words); |
597
|
7 |
|
case 2: |
598
|
7 |
|
return implode($twoWordsConnector, $words); |
599
|
|
|
default: |
600
|
1 |
|
return implode($connector, array_slice($words, 0, -1)) . $lastWordConnector . end($words); |
601
|
|
|
} |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
/** |
605
|
|
|
* @return string |
606
|
|
|
*/ |
607
|
142 |
|
private static function encoding() |
608
|
|
|
{ |
609
|
142 |
|
return isset(Yii::$app) ? Yii::$app->charset : 'UTF-8'; |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* The same as built-in `ucfirst`, but unicode-safe |
614
|
|
|
* |
615
|
|
|
* @param $string |
616
|
|
|
* @param $encoding |
617
|
|
|
* @return string |
618
|
|
|
*/ |
619
|
2 |
|
private static function mb_ucfirst($string, $encoding) |
620
|
|
|
{ |
621
|
2 |
|
$firstChar = mb_substr($string, 0, 1, $encoding); |
622
|
2 |
|
$rest = mb_substr($string, 1, null, $encoding); |
623
|
|
|
|
624
|
2 |
|
return mb_strtoupper($firstChar, $encoding) . $rest; |
625
|
|
|
} |
626
|
|
|
} |
627
|
|
|
|