cake/libs/inflector.php

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