Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
16591 anikendra 1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://cakephp.org CakePHP(tm) Project
12
 * @package       Cake.Utility
13
 * @since         CakePHP(tm) v 0.2.9
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16
 
17
/**
18
 * Pluralize and singularize English words.
19
 *
20
 * Inflector pluralizes and singularizes English nouns.
21
 * Used by CakePHP's naming conventions throughout the framework.
22
 *
23
 * @package       Cake.Utility
24
 * @link          http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html
25
 */
26
class Inflector {
27
 
28
/**
29
 * Plural inflector rules
30
 *
31
 * @var array
32
 */
33
	protected static $_plural = array(
34
		'rules' => array(
35
			'/(s)tatus$/i' => '\1tatuses',
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|([lre])f)$/i' => '\1\2ves',
44
			'/sis$/i' => 'ses',
45
			'/([ti])um$/i' => '\1a',
46
			'/(p)erson$/i' => '\1eople',
47
			'/(?<!u)(m)an$/i' => '\1en',
48
			'/(c)hild$/i' => '\1hildren',
49
			'/(buffal|tomat)o$/i' => '\1\2oes',
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
			'/s$/' => 's',
55
			'/^$/' => '',
56
			'/$/' => 's',
57
		),
58
		'uninflected' => array(
59
			'.*[nrlm]ese',
60
			'.*data',
61
			'.*deer',
62
			'.*fish',
63
			'.*measles',
64
			'.*ois',
65
			'.*pox',
66
			'.*sheep',
67
			'people',
68
			'feedback',
69
			'stadia'
70
		),
71
		'irregular' => array(
72
			'atlas' => 'atlases',
73
			'beef' => 'beefs',
74
			'brief' => 'briefs',
75
			'brother' => 'brothers',
76
			'cafe' => 'cafes',
77
			'child' => 'children',
78
			'cookie' => 'cookies',
79
			'corpus' => 'corpuses',
80
			'cow' => 'cows',
81
			'criterion' => 'criteria',
82
			'ganglion' => 'ganglions',
83
			'genie' => 'genies',
84
			'genus' => 'genera',
85
			'graffito' => 'graffiti',
86
			'hoof' => 'hoofs',
87
			'loaf' => 'loaves',
88
			'man' => 'men',
89
			'money' => 'monies',
90
			'mongoose' => 'mongooses',
91
			'move' => 'moves',
92
			'mythos' => 'mythoi',
93
			'niche' => 'niches',
94
			'numen' => 'numina',
95
			'occiput' => 'occiputs',
96
			'octopus' => 'octopuses',
97
			'opus' => 'opuses',
98
			'ox' => 'oxen',
99
			'penis' => 'penises',
100
			'person' => 'people',
101
			'sex' => 'sexes',
102
			'soliloquy' => 'soliloquies',
103
			'testis' => 'testes',
104
			'trilby' => 'trilbys',
105
			'turf' => 'turfs',
106
			'potato' => 'potatoes',
107
			'hero' => 'heroes',
108
			'tooth' => 'teeth',
109
			'goose' => 'geese',
110
			'foot' => 'feet',
111
			'sieve' => 'sieves'
112
		)
113
	);
114
 
115
/**
116
 * Singular inflector rules
117
 *
118
 * @var array
119
 */
120
	protected static $_singular = array(
121
		'rules' => array(
122
			'/(s)tatuses$/i' => '\1\2tatus',
123
			'/^(.*)(menu)s$/i' => '\1\2',
124
			'/(quiz)zes$/i' => '\\1',
125
			'/(matr)ices$/i' => '\1ix',
126
			'/(vert|ind)ices$/i' => '\1ex',
127
			'/^(ox)en/i' => '\1',
128
			'/(alias)(es)*$/i' => '\1',
129
			'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us',
130
			'/([ftw]ax)es/i' => '\1',
131
			'/(cris|ax|test)es$/i' => '\1is',
132
			'/(shoe)s$/i' => '\1',
133
			'/(o)es$/i' => '\1',
134
			'/ouses$/' => 'ouse',
135
			'/([^a])uses$/' => '\1us',
136
			'/([m|l])ice$/i' => '\1ouse',
137
			'/(x|ch|ss|sh)es$/i' => '\1',
138
			'/(m)ovies$/i' => '\1\2ovie',
139
			'/(s)eries$/i' => '\1\2eries',
140
			'/([^aeiouy]|qu)ies$/i' => '\1y',
141
			'/(tive)s$/i' => '\1',
142
			'/(hive)s$/i' => '\1',
143
			'/(drive)s$/i' => '\1',
144
			'/([le])ves$/i' => '\1f',
145
			'/([^rfoa])ves$/i' => '\1fe',
146
			'/(^analy)ses$/i' => '\1sis',
147
			'/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
148
			'/([ti])a$/i' => '\1um',
149
			'/(p)eople$/i' => '\1\2erson',
150
			'/(m)en$/i' => '\1an',
151
			'/(c)hildren$/i' => '\1\2hild',
152
			'/(n)ews$/i' => '\1\2ews',
153
			'/eaus$/' => 'eau',
154
			'/^(.*us)$/' => '\\1',
155
			'/s$/i' => ''
156
		),
157
		'uninflected' => array(
158
			'.*data',
159
			'.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', '.*ss', 'feedback'
160
		),
161
		'irregular' => array(
162
			'foes' => 'foe',
163
		)
164
	);
165
 
166
/**
167
 * Words that should not be inflected
168
 *
169
 * @var array
170
 */
171
	protected static $_uninflected = array(
172
		'Amoyese', 'bison', 'Borghese', 'bream', 'breeches', 'britches', 'buffalo', 'cantus',
173
		'carp', 'chassis', 'clippers', 'cod', 'coitus', 'Congoese', 'contretemps', 'corps',
174
		'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder',
175
		'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti',
176
		'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings',
177
		'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', '.*?media',
178
		'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese',
179
		'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese',
180
		'proceedings', 'rabies', 'research', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
181
		'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes',
182
		'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest',
183
		'Yengeese'
184
	);
185
 
186
/**
187
 * Default map of accented and special characters to ASCII characters
188
 *
189
 * @var array
190
 */
191
	protected static $_transliteration = array(
192
		'/À|Á|Â|Ã|Å|Ǻ|Ā|Ă|Ą|Ǎ/' => 'A',
193
		'/Æ|Ǽ/' => 'AE',
194
		'/Ä/' => 'Ae',
195
		'/Ç|Ć|Ĉ|Ċ|Č/' => 'C',
196
		'/Ð|Ď|Đ/' => 'D',
197
		'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě/' => 'E',
198
		'/Ĝ|Ğ|Ġ|Ģ|Ґ/' => 'G',
199
		'/Ĥ|Ħ/' => 'H',
200
		'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|І/' => 'I',
201
		'/IJ/' => 'IJ',
202
		'/Ĵ/' => 'J',
203
		'/Ķ/' => 'K',
204
		'/Ĺ|Ļ|Ľ|Ŀ|Ł/' => 'L',
205
		'/Ñ|Ń|Ņ|Ň/' => 'N',
206
		'/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ/' => 'O',
207
		'/Œ/' => 'OE',
208
		'/Ö/' => 'Oe',
209
		'/Ŕ|Ŗ|Ř/' => 'R',
210
		'/Ś|Ŝ|Ş|Ș|Š/' => 'S',
211
		'/ẞ/' => 'SS',
212
		'/Ţ|Ț|Ť|Ŧ/' => 'T',
213
		'/Þ/' => 'TH',
214
		'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ/' => 'U',
215
		'/Ü/' => 'Ue',
216
		'/Ŵ/' => 'W',
217
		'/Ý|Ÿ|Ŷ/' => 'Y',
218
		'/Є/' => 'Ye',
219
		'/Ї/' => 'Yi',
220
		'/Ź|Ż|Ž/' => 'Z',
221
		'/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª/' => 'a',
222
		'/ä|æ|ǽ/' => 'ae',
223
		'/ç|ć|ĉ|ċ|č/' => 'c',
224
		'/ð|ď|đ/' => 'd',
225
		'/è|é|ê|ë|ē|ĕ|ė|ę|ě/' => 'e',
226
		'/ƒ/' => 'f',
227
		'/ĝ|ğ|ġ|ģ|ґ/' => 'g',
228
		'/ĥ|ħ/' => 'h',
229
		'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|і/' => 'i',
230
		'/ij/' => 'ij',
231
		'/ĵ/' => 'j',
232
		'/ķ/' => 'k',
233
		'/ĺ|ļ|ľ|ŀ|ł/' => 'l',
234
		'/ñ|ń|ņ|ň|ʼn/' => 'n',
235
		'/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º/' => 'o',
236
		'/ö|œ/' => 'oe',
237
		'/ŕ|ŗ|ř/' => 'r',
238
		'/ś|ŝ|ş|ș|š|ſ/' => 's',
239
		'/ß/' => 'ss',
240
		'/ţ|ț|ť|ŧ/' => 't',
241
		'/þ/' => 'th',
242
		'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ/' => 'u',
243
		'/ü/' => 'ue',
244
		'/ŵ/' => 'w',
245
		'/ý|ÿ|ŷ/' => 'y',
246
		'/є/' => 'ye',
247
		'/ї/' => 'yi',
248
		'/ź|ż|ž/' => 'z',
249
	);
250
 
251
/**
252
 * Method cache array.
253
 *
254
 * @var array
255
 */
256
	protected static $_cache = array();
257
 
258
/**
259
 * The initial state of Inflector so reset() works.
260
 *
261
 * @var array
262
 */
263
	protected static $_initialState = array();
264
 
265
/**
266
 * Cache inflected values, and return if already available
267
 *
268
 * @param string $type Inflection type
269
 * @param string $key Original value
270
 * @param string $value Inflected value
271
 * @return string Inflected value, from cache
272
 */
273
	protected static function _cache($type, $key, $value = false) {
274
		$key = '_' . $key;
275
		$type = '_' . $type;
276
		if ($value !== false) {
277
			static::$_cache[$type][$key] = $value;
278
			return $value;
279
		}
280
		if (!isset(static::$_cache[$type][$key])) {
281
			return false;
282
		}
283
		return static::$_cache[$type][$key];
284
	}
285
 
286
/**
287
 * Clears Inflectors inflected value caches. And resets the inflection
288
 * rules to the initial values.
289
 *
290
 * @return void
291
 */
292
	public static function reset() {
293
		if (empty(static::$_initialState)) {
294
			static::$_initialState = get_class_vars('Inflector');
295
			return;
296
		}
297
		foreach (static::$_initialState as $key => $val) {
298
			if ($key !== '_initialState') {
299
				static::${$key} = $val;
300
			}
301
		}
302
	}
303
 
304
/**
305
 * Adds custom inflection $rules, of either 'plural', 'singular' or 'transliteration' $type.
306
 *
307
 * ### Usage:
308
 *
309
 * ```
310
 * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
311
 * Inflector::rules('plural', array(
312
 *     'rules' => array('/^(inflect)ors$/i' => '\1ables'),
313
 *     'uninflected' => array('dontinflectme'),
314
 *     'irregular' => array('red' => 'redlings')
315
 * ));
316
 * Inflector::rules('transliteration', array('/å/' => 'aa'));
317
 * ```
318
 *
319
 * @param string $type The type of inflection, either 'plural', 'singular' or 'transliteration'
320
 * @param array $rules Array of rules to be added.
321
 * @param bool $reset If true, will unset default inflections for all
322
 *        new rules that are being defined in $rules.
323
 * @return void
324
 */
325
	public static function rules($type, $rules, $reset = false) {
326
		$var = '_' . $type;
327
 
328
		switch ($type) {
329
			case 'transliteration':
330
				if ($reset) {
331
					static::$_transliteration = $rules;
332
				} else {
333
					static::$_transliteration = $rules + static::$_transliteration;
334
				}
335
				break;
336
 
337
			default:
338
				foreach ($rules as $rule => $pattern) {
339
					if (is_array($pattern)) {
340
						if ($reset) {
341
							static::${$var}[$rule] = $pattern;
342
						} else {
343
							if ($rule === 'uninflected') {
344
								static::${$var}[$rule] = array_merge($pattern, static::${$var}[$rule]);
345
							} else {
346
								static::${$var}[$rule] = $pattern + static::${$var}[$rule];
347
							}
348
						}
349
						unset($rules[$rule], static::${$var}['cache' . ucfirst($rule)]);
350
						if (isset(static::${$var}['merged'][$rule])) {
351
							unset(static::${$var}['merged'][$rule]);
352
						}
353
						if ($type === 'plural') {
354
							static::$_cache['pluralize'] = static::$_cache['tableize'] = array();
355
						} elseif ($type === 'singular') {
356
							static::$_cache['singularize'] = array();
357
						}
358
					}
359
				}
360
				static::${$var}['rules'] = $rules + static::${$var}['rules'];
361
		}
362
	}
363
 
364
/**
365
 * Return $word in plural form.
366
 *
367
 * @param string $word Word in singular
368
 * @return string Word in plural
369
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::pluralize
370
 */
371
	public static function pluralize($word) {
372
		if (isset(static::$_cache['pluralize'][$word])) {
373
			return static::$_cache['pluralize'][$word];
374
		}
375
 
376
		if (!isset(static::$_plural['merged']['irregular'])) {
377
			static::$_plural['merged']['irregular'] = static::$_plural['irregular'];
378
		}
379
 
380
		if (!isset(static::$_plural['merged']['uninflected'])) {
381
			static::$_plural['merged']['uninflected'] = array_merge(static::$_plural['uninflected'], static::$_uninflected);
382
		}
383
 
384
		if (!isset(static::$_plural['cacheUninflected']) || !isset(static::$_plural['cacheIrregular'])) {
385
			static::$_plural['cacheUninflected'] = '(?:' . implode('|', static::$_plural['merged']['uninflected']) . ')';
386
			static::$_plural['cacheIrregular'] = '(?:' . implode('|', array_keys(static::$_plural['merged']['irregular'])) . ')';
387
		}
388
 
389
		if (preg_match('/(.*?(?:\\b|_))(' . static::$_plural['cacheIrregular'] . ')$/i', $word, $regs)) {
390
			static::$_cache['pluralize'][$word] = $regs[1] .
391
				substr($regs[2], 0, 1) .
392
				substr(static::$_plural['merged']['irregular'][strtolower($regs[2])], 1);
393
			return static::$_cache['pluralize'][$word];
394
		}
395
 
396
		if (preg_match('/^(' . static::$_plural['cacheUninflected'] . ')$/i', $word, $regs)) {
397
			static::$_cache['pluralize'][$word] = $word;
398
			return $word;
399
		}
400
 
401
		foreach (static::$_plural['rules'] as $rule => $replacement) {
402
			if (preg_match($rule, $word)) {
403
				static::$_cache['pluralize'][$word] = preg_replace($rule, $replacement, $word);
404
				return static::$_cache['pluralize'][$word];
405
			}
406
		}
407
	}
408
 
409
/**
410
 * Return $word in singular form.
411
 *
412
 * @param string $word Word in plural
413
 * @return string Word in singular
414
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::singularize
415
 */
416
	public static function singularize($word) {
417
		if (isset(static::$_cache['singularize'][$word])) {
418
			return static::$_cache['singularize'][$word];
419
		}
420
 
421
		if (!isset(static::$_singular['merged']['uninflected'])) {
422
			static::$_singular['merged']['uninflected'] = array_merge(
423
				static::$_singular['uninflected'],
424
				static::$_uninflected
425
			);
426
		}
427
 
428
		if (!isset(static::$_singular['merged']['irregular'])) {
429
			static::$_singular['merged']['irregular'] = array_merge(
430
				static::$_singular['irregular'],
431
				array_flip(static::$_plural['irregular'])
432
			);
433
		}
434
 
435
		if (!isset(static::$_singular['cacheUninflected']) || !isset(static::$_singular['cacheIrregular'])) {
436
			static::$_singular['cacheUninflected'] = '(?:' . implode('|', static::$_singular['merged']['uninflected']) . ')';
437
			static::$_singular['cacheIrregular'] = '(?:' . implode('|', array_keys(static::$_singular['merged']['irregular'])) . ')';
438
		}
439
 
440
		if (preg_match('/(.*?(?:\\b|_))(' . static::$_singular['cacheIrregular'] . ')$/i', $word, $regs)) {
441
			static::$_cache['singularize'][$word] = $regs[1] .
442
				substr($regs[2], 0, 1) .
443
				substr(static::$_singular['merged']['irregular'][strtolower($regs[2])], 1);
444
			return static::$_cache['singularize'][$word];
445
		}
446
 
447
		if (preg_match('/^(' . static::$_singular['cacheUninflected'] . ')$/i', $word, $regs)) {
448
			static::$_cache['singularize'][$word] = $word;
449
			return $word;
450
		}
451
 
452
		foreach (static::$_singular['rules'] as $rule => $replacement) {
453
			if (preg_match($rule, $word)) {
454
				static::$_cache['singularize'][$word] = preg_replace($rule, $replacement, $word);
455
				return static::$_cache['singularize'][$word];
456
			}
457
		}
458
		static::$_cache['singularize'][$word] = $word;
459
		return $word;
460
	}
461
 
462
/**
463
 * Returns the given lower_case_and_underscored_word as a CamelCased word.
464
 *
465
 * @param string $lowerCaseAndUnderscoredWord Word to camelize
466
 * @return string Camelized word. LikeThis.
467
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::camelize
468
 */
469
	public static function camelize($lowerCaseAndUnderscoredWord) {
470
		if (!($result = static::_cache(__FUNCTION__, $lowerCaseAndUnderscoredWord))) {
471
			$result = str_replace(' ', '', Inflector::humanize($lowerCaseAndUnderscoredWord));
472
			static::_cache(__FUNCTION__, $lowerCaseAndUnderscoredWord, $result);
473
		}
474
		return $result;
475
	}
476
 
477
/**
478
 * Returns the given camelCasedWord as an underscored_word.
479
 *
480
 * @param string $camelCasedWord Camel-cased word to be "underscorized"
481
 * @return string Underscore-syntaxed version of the $camelCasedWord
482
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::underscore
483
 */
484
	public static function underscore($camelCasedWord) {
485
		if (!($result = static::_cache(__FUNCTION__, $camelCasedWord))) {
486
			$underscoredWord = preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $camelCasedWord);
487
			$result = mb_strtolower($underscoredWord);
488
			static::_cache(__FUNCTION__, $camelCasedWord, $result);
489
		}
490
		return $result;
491
	}
492
 
493
/**
494
 * Returns the given underscored_word_group as a Human Readable Word Group.
495
 * (Underscores are replaced by spaces and capitalized following words.)
496
 *
497
 * @param string $lowerCaseAndUnderscoredWord String to be made more readable
498
 * @return string Human-readable string
499
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::humanize
500
 */
501
	public static function humanize($lowerCaseAndUnderscoredWord) {
502
		if (!($result = static::_cache(__FUNCTION__, $lowerCaseAndUnderscoredWord))) {
503
			$result = explode(' ', str_replace('_', ' ', $lowerCaseAndUnderscoredWord));
504
			foreach ($result as &$word) {
505
				$word = mb_strtoupper(mb_substr($word, 0, 1)) . mb_substr($word, 1);
506
			}
507
			$result = implode(' ', $result);
508
			static::_cache(__FUNCTION__, $lowerCaseAndUnderscoredWord, $result);
509
		}
510
		return $result;
511
	}
512
 
513
/**
514
 * Returns corresponding table name for given model $className. ("people" for the model class "Person").
515
 *
516
 * @param string $className Name of class to get database table name for
517
 * @return string Name of the database table for given class
518
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::tableize
519
 */
520
	public static function tableize($className) {
521
		if (!($result = static::_cache(__FUNCTION__, $className))) {
522
			$result = Inflector::pluralize(Inflector::underscore($className));
523
			static::_cache(__FUNCTION__, $className, $result);
524
		}
525
		return $result;
526
	}
527
 
528
/**
529
 * Returns Cake model class name ("Person" for the database table "people".) for given database table.
530
 *
531
 * @param string $tableName Name of database table to get class name for
532
 * @return string Class name
533
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::classify
534
 */
535
	public static function classify($tableName) {
536
		if (!($result = static::_cache(__FUNCTION__, $tableName))) {
537
			$result = Inflector::camelize(Inflector::singularize($tableName));
538
			static::_cache(__FUNCTION__, $tableName, $result);
539
		}
540
		return $result;
541
	}
542
 
543
/**
544
 * Returns camelBacked version of an underscored string.
545
 *
546
 * @param string $string String to convert.
547
 * @return string in variable form
548
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::variable
549
 */
550
	public static function variable($string) {
551
		if (!($result = static::_cache(__FUNCTION__, $string))) {
552
			$camelized = Inflector::camelize(Inflector::underscore($string));
553
			$replace = strtolower(substr($camelized, 0, 1));
554
			$result = preg_replace('/\\w/', $replace, $camelized, 1);
555
			static::_cache(__FUNCTION__, $string, $result);
556
		}
557
		return $result;
558
	}
559
 
560
/**
561
 * Returns a string with all spaces converted to underscores (by default), accented
562
 * characters converted to non-accented characters, and non word characters removed.
563
 *
564
 * @param string $string the string you want to slug
565
 * @param string $replacement will replace keys in map
566
 * @return string
567
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/inflector.html#Inflector::slug
568
 */
569
	public static function slug($string, $replacement = '_') {
570
		$quotedReplacement = preg_quote($replacement, '/');
571
 
572
		$merge = array(
573
			'/[^\s\p{Zs}\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu' => ' ',
574
			'/[\s\p{Zs}]+/mu' => $replacement,
575
			sprintf('/^[%s]+|[%s]+$/', $quotedReplacement, $quotedReplacement) => '',
576
		);
577
 
578
		$map = static::$_transliteration + $merge;
579
		return preg_replace(array_keys($map), array_values($map), $string);
580
	}
581
 
582
}
583
 
584
// Store the initial state
585
Inflector::reset();