Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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