1<?php 2/** 3 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org) 4 * Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org) 11 * @link https://cakephp.org CakePHP(tm) Project 12 * @since 0.2.9 13 * @license https://opensource.org/licenses/mit-license.php MIT License 14 */ 15namespace Cake\Utility; 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 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html 24 */ 25class Inflector 26{ 27 /** 28 * Plural inflector rules 29 * 30 * @var array 31 */ 32 protected static $_plural = [ 33 '/(s)tatus$/i' => '\1tatuses', 34 '/(quiz)$/i' => '\1zes', 35 '/^(ox)$/i' => '\1\2en', 36 '/([m|l])ouse$/i' => '\1ice', 37 '/(matr|vert|ind)(ix|ex)$/i' => '\1ices', 38 '/(x|ch|ss|sh)$/i' => '\1es', 39 '/([^aeiouy]|qu)y$/i' => '\1ies', 40 '/(hive)$/i' => '\1s', 41 '/(chef)$/i' => '\1s', 42 '/(?:([^f])fe|([lre])f)$/i' => '\1\2ves', 43 '/sis$/i' => 'ses', 44 '/([ti])um$/i' => '\1a', 45 '/(p)erson$/i' => '\1eople', 46 '/(?<!u)(m)an$/i' => '\1en', 47 '/(c)hild$/i' => '\1hildren', 48 '/(buffal|tomat)o$/i' => '\1\2oes', 49 '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin)us$/i' => '\1i', 50 '/us$/i' => 'uses', 51 '/(alias)$/i' => '\1es', 52 '/(ax|cris|test)is$/i' => '\1es', 53 '/s$/' => 's', 54 '/^$/' => '', 55 '/$/' => 's', 56 ]; 57 58 /** 59 * Singular inflector rules 60 * 61 * @var array 62 */ 63 protected static $_singular = [ 64 '/(s)tatuses$/i' => '\1\2tatus', 65 '/^(.*)(menu)s$/i' => '\1\2', 66 '/(quiz)zes$/i' => '\\1', 67 '/(matr)ices$/i' => '\1ix', 68 '/(vert|ind)ices$/i' => '\1ex', 69 '/^(ox)en/i' => '\1', 70 '/(alias)(es)*$/i' => '\1', 71 '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us', 72 '/([ftw]ax)es/i' => '\1', 73 '/(cris|ax|test)es$/i' => '\1is', 74 '/(shoe)s$/i' => '\1', 75 '/(o)es$/i' => '\1', 76 '/ouses$/' => 'ouse', 77 '/([^a])uses$/' => '\1us', 78 '/([m|l])ice$/i' => '\1ouse', 79 '/(x|ch|ss|sh)es$/i' => '\1', 80 '/(m)ovies$/i' => '\1\2ovie', 81 '/(s)eries$/i' => '\1\2eries', 82 '/([^aeiouy]|qu)ies$/i' => '\1y', 83 '/(tive)s$/i' => '\1', 84 '/(hive)s$/i' => '\1', 85 '/(drive)s$/i' => '\1', 86 '/([le])ves$/i' => '\1f', 87 '/([^rfoa])ves$/i' => '\1fe', 88 '/(^analy)ses$/i' => '\1sis', 89 '/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', 90 '/([ti])a$/i' => '\1um', 91 '/(p)eople$/i' => '\1\2erson', 92 '/(m)en$/i' => '\1an', 93 '/(c)hildren$/i' => '\1\2hild', 94 '/(n)ews$/i' => '\1\2ews', 95 '/eaus$/' => 'eau', 96 '/^(.*us)$/' => '\\1', 97 '/s$/i' => '', 98 ]; 99 100 /** 101 * Irregular rules 102 * 103 * @var array 104 */ 105 protected static $_irregular = [ 106 'atlas' => 'atlases', 107 'beef' => 'beefs', 108 'brief' => 'briefs', 109 'brother' => 'brothers', 110 'cafe' => 'cafes', 111 'child' => 'children', 112 'cookie' => 'cookies', 113 'corpus' => 'corpuses', 114 'cow' => 'cows', 115 'criterion' => 'criteria', 116 'ganglion' => 'ganglions', 117 'genie' => 'genies', 118 'genus' => 'genera', 119 'graffito' => 'graffiti', 120 'hoof' => 'hoofs', 121 'loaf' => 'loaves', 122 'man' => 'men', 123 'money' => 'monies', 124 'mongoose' => 'mongooses', 125 'move' => 'moves', 126 'mythos' => 'mythoi', 127 'niche' => 'niches', 128 'numen' => 'numina', 129 'occiput' => 'occiputs', 130 'octopus' => 'octopuses', 131 'opus' => 'opuses', 132 'ox' => 'oxen', 133 'penis' => 'penises', 134 'person' => 'people', 135 'sex' => 'sexes', 136 'soliloquy' => 'soliloquies', 137 'testis' => 'testes', 138 'trilby' => 'trilbys', 139 'turf' => 'turfs', 140 'potato' => 'potatoes', 141 'hero' => 'heroes', 142 'tooth' => 'teeth', 143 'goose' => 'geese', 144 'foot' => 'feet', 145 'foe' => 'foes', 146 'sieve' => 'sieves', 147 'cache' => 'caches', 148 ]; 149 150 /** 151 * Words that should not be inflected 152 * 153 * @var array 154 */ 155 protected static $_uninflected = [ 156 '.*[nrlm]ese', '.*data', '.*deer', '.*fish', '.*measles', '.*ois', 157 '.*pox', '.*sheep', 'people', 'feedback', 'stadia', '.*?media', 158 'chassis', 'clippers', 'debris', 'diabetes', 'equipment', 'gallows', 159 'graffiti', 'headquarters', 'information', 'innings', 'news', 'nexus', 160 'pokemon', 'proceedings', 'research', 'sea[- ]bass', 'series', 'species', 'weather', 161 ]; 162 163 /** 164 * Default map of accented and special characters to ASCII characters 165 * 166 * @var array 167 */ 168 protected static $_transliteration = [ 169 'ä' => 'ae', 170 'æ' => 'ae', 171 'ǽ' => 'ae', 172 'ö' => 'oe', 173 'œ' => 'oe', 174 'ü' => 'ue', 175 'Ä' => 'Ae', 176 'Ü' => 'Ue', 177 'Ö' => 'Oe', 178 'À' => 'A', 179 'Á' => 'A', 180 'Â' => 'A', 181 'Ã' => 'A', 182 'Å' => 'A', 183 'Ǻ' => 'A', 184 'Ā' => 'A', 185 'Ă' => 'A', 186 'Ą' => 'A', 187 'Ǎ' => 'A', 188 'à' => 'a', 189 'á' => 'a', 190 'â' => 'a', 191 'ã' => 'a', 192 'å' => 'a', 193 'ǻ' => 'a', 194 'ā' => 'a', 195 'ă' => 'a', 196 'ą' => 'a', 197 'ǎ' => 'a', 198 'ª' => 'a', 199 'Ç' => 'C', 200 'Ć' => 'C', 201 'Ĉ' => 'C', 202 'Ċ' => 'C', 203 'Č' => 'C', 204 'ç' => 'c', 205 'ć' => 'c', 206 'ĉ' => 'c', 207 'ċ' => 'c', 208 'č' => 'c', 209 'Ð' => 'D', 210 'Ď' => 'D', 211 'Đ' => 'D', 212 'ð' => 'd', 213 'ď' => 'd', 214 'đ' => 'd', 215 'È' => 'E', 216 'É' => 'E', 217 'Ê' => 'E', 218 'Ë' => 'E', 219 'Ē' => 'E', 220 'Ĕ' => 'E', 221 'Ė' => 'E', 222 'Ę' => 'E', 223 'Ě' => 'E', 224 'è' => 'e', 225 'é' => 'e', 226 'ê' => 'e', 227 'ë' => 'e', 228 'ē' => 'e', 229 'ĕ' => 'e', 230 'ė' => 'e', 231 'ę' => 'e', 232 'ě' => 'e', 233 'Ĝ' => 'G', 234 'Ğ' => 'G', 235 'Ġ' => 'G', 236 'Ģ' => 'G', 237 'Ґ' => 'G', 238 'ĝ' => 'g', 239 'ğ' => 'g', 240 'ġ' => 'g', 241 'ģ' => 'g', 242 'ґ' => 'g', 243 'Ĥ' => 'H', 244 'Ħ' => 'H', 245 'ĥ' => 'h', 246 'ħ' => 'h', 247 'І' => 'I', 248 'Ì' => 'I', 249 'Í' => 'I', 250 'Î' => 'I', 251 'Ї' => 'Yi', 252 'Ï' => 'I', 253 'Ĩ' => 'I', 254 'Ī' => 'I', 255 'Ĭ' => 'I', 256 'Ǐ' => 'I', 257 'Į' => 'I', 258 'İ' => 'I', 259 'і' => 'i', 260 'ì' => 'i', 261 'í' => 'i', 262 'î' => 'i', 263 'ï' => 'i', 264 'ї' => 'yi', 265 'ĩ' => 'i', 266 'ī' => 'i', 267 'ĭ' => 'i', 268 'ǐ' => 'i', 269 'į' => 'i', 270 'ı' => 'i', 271 'Ĵ' => 'J', 272 'ĵ' => 'j', 273 'Ķ' => 'K', 274 'ķ' => 'k', 275 'Ĺ' => 'L', 276 'Ļ' => 'L', 277 'Ľ' => 'L', 278 'Ŀ' => 'L', 279 'Ł' => 'L', 280 'ĺ' => 'l', 281 'ļ' => 'l', 282 'ľ' => 'l', 283 'ŀ' => 'l', 284 'ł' => 'l', 285 'Ñ' => 'N', 286 'Ń' => 'N', 287 'Ņ' => 'N', 288 'Ň' => 'N', 289 'ñ' => 'n', 290 'ń' => 'n', 291 'ņ' => 'n', 292 'ň' => 'n', 293 'ʼn' => 'n', 294 'Ò' => 'O', 295 'Ó' => 'O', 296 'Ô' => 'O', 297 'Õ' => 'O', 298 'Ō' => 'O', 299 'Ŏ' => 'O', 300 'Ǒ' => 'O', 301 'Ő' => 'O', 302 'Ơ' => 'O', 303 'Ø' => 'O', 304 'Ǿ' => 'O', 305 'ò' => 'o', 306 'ó' => 'o', 307 'ô' => 'o', 308 'õ' => 'o', 309 'ō' => 'o', 310 'ŏ' => 'o', 311 'ǒ' => 'o', 312 'ő' => 'o', 313 'ơ' => 'o', 314 'ø' => 'o', 315 'ǿ' => 'o', 316 'º' => 'o', 317 'Ŕ' => 'R', 318 'Ŗ' => 'R', 319 'Ř' => 'R', 320 'ŕ' => 'r', 321 'ŗ' => 'r', 322 'ř' => 'r', 323 'Ś' => 'S', 324 'Ŝ' => 'S', 325 'Ş' => 'S', 326 'Ș' => 'S', 327 'Š' => 'S', 328 'ẞ' => 'SS', 329 'ś' => 's', 330 'ŝ' => 's', 331 'ş' => 's', 332 'ș' => 's', 333 'š' => 's', 334 'ſ' => 's', 335 'Ţ' => 'T', 336 'Ț' => 'T', 337 'Ť' => 'T', 338 'Ŧ' => 'T', 339 'ţ' => 't', 340 'ț' => 't', 341 'ť' => 't', 342 'ŧ' => 't', 343 'Ù' => 'U', 344 'Ú' => 'U', 345 'Û' => 'U', 346 'Ũ' => 'U', 347 'Ū' => 'U', 348 'Ŭ' => 'U', 349 'Ů' => 'U', 350 'Ű' => 'U', 351 'Ų' => 'U', 352 'Ư' => 'U', 353 'Ǔ' => 'U', 354 'Ǖ' => 'U', 355 'Ǘ' => 'U', 356 'Ǚ' => 'U', 357 'Ǜ' => 'U', 358 'ù' => 'u', 359 'ú' => 'u', 360 'û' => 'u', 361 'ũ' => 'u', 362 'ū' => 'u', 363 'ŭ' => 'u', 364 'ů' => 'u', 365 'ű' => 'u', 366 'ų' => 'u', 367 'ư' => 'u', 368 'ǔ' => 'u', 369 'ǖ' => 'u', 370 'ǘ' => 'u', 371 'ǚ' => 'u', 372 'ǜ' => 'u', 373 'Ý' => 'Y', 374 'Ÿ' => 'Y', 375 'Ŷ' => 'Y', 376 'ý' => 'y', 377 'ÿ' => 'y', 378 'ŷ' => 'y', 379 'Ŵ' => 'W', 380 'ŵ' => 'w', 381 'Ź' => 'Z', 382 'Ż' => 'Z', 383 'Ž' => 'Z', 384 'ź' => 'z', 385 'ż' => 'z', 386 'ž' => 'z', 387 'Æ' => 'AE', 388 'Ǽ' => 'AE', 389 'ß' => 'ss', 390 'IJ' => 'IJ', 391 'ij' => 'ij', 392 'Œ' => 'OE', 393 'ƒ' => 'f', 394 'Þ' => 'TH', 395 'þ' => 'th', 396 'Є' => 'Ye', 397 'є' => 'ye', 398 ]; 399 400 /** 401 * Method cache array. 402 * 403 * @var array 404 */ 405 protected static $_cache = []; 406 407 /** 408 * The initial state of Inflector so reset() works. 409 * 410 * @var array 411 */ 412 protected static $_initialState = []; 413 414 /** 415 * Cache inflected values, and return if already available 416 * 417 * @param string $type Inflection type 418 * @param string $key Original value 419 * @param string|false $value Inflected value 420 * @return string|false Inflected value on cache hit or false on cache miss. 421 */ 422 protected static function _cache($type, $key, $value = false) 423 { 424 $key = '_' . $key; 425 $type = '_' . $type; 426 if ($value !== false) { 427 static::$_cache[$type][$key] = $value; 428 429 return $value; 430 } 431 if (!isset(static::$_cache[$type][$key])) { 432 return false; 433 } 434 435 return static::$_cache[$type][$key]; 436 } 437 438 /** 439 * Clears Inflectors inflected value caches. And resets the inflection 440 * rules to the initial values. 441 * 442 * @return void 443 */ 444 public static function reset() 445 { 446 if (empty(static::$_initialState)) { 447 static::$_initialState = get_class_vars(__CLASS__); 448 449 return; 450 } 451 foreach (static::$_initialState as $key => $val) { 452 if ($key !== '_initialState') { 453 static::${$key} = $val; 454 } 455 } 456 } 457 458 /** 459 * Adds custom inflection $rules, of either 'plural', 'singular', 460 * 'uninflected', 'irregular' or 'transliteration' $type. 461 * 462 * ### Usage: 463 * 464 * ``` 465 * Inflector::rules('plural', ['/^(inflect)or$/i' => '\1ables']); 466 * Inflector::rules('irregular', ['red' => 'redlings']); 467 * Inflector::rules('uninflected', ['dontinflectme']); 468 * Inflector::rules('transliteration', ['/å/' => 'aa']); 469 * ``` 470 * 471 * @param string $type The type of inflection, either 'plural', 'singular', 472 * 'uninflected' or 'transliteration'. 473 * @param array $rules Array of rules to be added. 474 * @param bool $reset If true, will unset default inflections for all 475 * new rules that are being defined in $rules. 476 * @return void 477 */ 478 public static function rules($type, $rules, $reset = false) 479 { 480 $var = '_' . $type; 481 482 if ($reset) { 483 static::${$var} = $rules; 484 } elseif ($type === 'uninflected') { 485 static::$_uninflected = array_merge( 486 $rules, 487 static::$_uninflected 488 ); 489 } else { 490 static::${$var} = $rules + static::${$var}; 491 } 492 493 static::$_cache = []; 494 } 495 496 /** 497 * Return $word in plural form. 498 * 499 * @param string $word Word in singular 500 * @return string Word in plural 501 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-plural-singular-forms 502 */ 503 public static function pluralize($word) 504 { 505 if (isset(static::$_cache['pluralize'][$word])) { 506 return static::$_cache['pluralize'][$word]; 507 } 508 509 if (!isset(static::$_cache['irregular']['pluralize'])) { 510 $words = array_keys(static::$_irregular); 511 static::$_cache['irregular']['pluralize'] = '/(.*?(?:\\b|_))(' . implode('|', $words) . ')$/i'; 512 513 $upperWords = array_map('ucfirst', $words); 514 static::$_cache['irregular']['upperPluralize'] = '/(.*?(?:\\b|[a-z]))(' . implode('|', $upperWords) . ')$/'; 515 } 516 517 if ( 518 preg_match(static::$_cache['irregular']['pluralize'], $word, $regs) || 519 preg_match(static::$_cache['irregular']['upperPluralize'], $word, $regs) 520 ) { 521 static::$_cache['pluralize'][$word] = $regs[1] . substr($regs[2], 0, 1) . 522 substr(static::$_irregular[strtolower($regs[2])], 1); 523 524 return static::$_cache['pluralize'][$word]; 525 } 526 527 if (!isset(static::$_cache['uninflected'])) { 528 static::$_cache['uninflected'] = '/^(' . implode('|', static::$_uninflected) . ')$/i'; 529 } 530 531 if (preg_match(static::$_cache['uninflected'], $word, $regs)) { 532 static::$_cache['pluralize'][$word] = $word; 533 534 return $word; 535 } 536 537 foreach (static::$_plural as $rule => $replacement) { 538 if (preg_match($rule, $word)) { 539 static::$_cache['pluralize'][$word] = preg_replace($rule, $replacement, $word); 540 541 return static::$_cache['pluralize'][$word]; 542 } 543 } 544 } 545 546 /** 547 * Return $word in singular form. 548 * 549 * @param string $word Word in plural 550 * @return string Word in singular 551 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-plural-singular-forms 552 */ 553 public static function singularize($word) 554 { 555 if (isset(static::$_cache['singularize'][$word])) { 556 return static::$_cache['singularize'][$word]; 557 } 558 559 if (!isset(static::$_cache['irregular']['singular'])) { 560 $wordList = array_values(static::$_irregular); 561 static::$_cache['irregular']['singular'] = '/(.*?(?:\\b|_))(' . implode('|', $wordList) . ')$/i'; 562 563 $upperWordList = array_map('ucfirst', $wordList); 564 static::$_cache['irregular']['singularUpper'] = '/(.*?(?:\\b|[a-z]))(' . 565 implode('|', $upperWordList) . 566 ')$/'; 567 } 568 569 if ( 570 preg_match(static::$_cache['irregular']['singular'], $word, $regs) || 571 preg_match(static::$_cache['irregular']['singularUpper'], $word, $regs) 572 ) { 573 static::$_cache['singularize'][$word] = $regs[1] . substr($regs[2], 0, 1) . 574 substr(array_search(strtolower($regs[2]), static::$_irregular, true), 1); 575 576 return static::$_cache['singularize'][$word]; 577 } 578 579 if (!isset(static::$_cache['uninflected'])) { 580 static::$_cache['uninflected'] = '/^(' . implode('|', static::$_uninflected) . ')$/i'; 581 } 582 583 if (preg_match(static::$_cache['uninflected'], $word, $regs)) { 584 static::$_cache['pluralize'][$word] = $word; 585 586 return $word; 587 } 588 589 foreach (static::$_singular as $rule => $replacement) { 590 if (preg_match($rule, $word)) { 591 static::$_cache['singularize'][$word] = preg_replace($rule, $replacement, $word); 592 593 return static::$_cache['singularize'][$word]; 594 } 595 } 596 static::$_cache['singularize'][$word] = $word; 597 598 return $word; 599 } 600 601 /** 602 * Returns the input lower_case_delimited_string as a CamelCasedString. 603 * 604 * @param string $string String to camelize 605 * @param string $delimiter the delimiter in the input string 606 * @return string CamelizedStringLikeThis. 607 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms 608 */ 609 public static function camelize($string, $delimiter = '_') 610 { 611 $cacheKey = __FUNCTION__ . $delimiter; 612 613 $result = static::_cache($cacheKey, $string); 614 615 if ($result === false) { 616 $result = str_replace(' ', '', static::humanize($string, $delimiter)); 617 static::_cache($cacheKey, $string, $result); 618 } 619 620 return $result; 621 } 622 623 /** 624 * Returns the input CamelCasedString as an underscored_string. 625 * 626 * Also replaces dashes with underscores 627 * 628 * @param string $string CamelCasedString to be "underscorized" 629 * @return string underscore_version of the input string 630 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-camelcase-and-under-scored-forms 631 */ 632 public static function underscore($string) 633 { 634 return static::delimit(str_replace('-', '_', $string), '_'); 635 } 636 637 /** 638 * Returns the input CamelCasedString as an dashed-string. 639 * 640 * Also replaces underscores with dashes 641 * 642 * @param string $string The string to dasherize. 643 * @return string Dashed version of the input string 644 */ 645 public static function dasherize($string) 646 { 647 return static::delimit(str_replace('_', '-', $string), '-'); 648 } 649 650 /** 651 * Returns the input lower_case_delimited_string as 'A Human Readable String'. 652 * (Underscores are replaced by spaces and capitalized following words.) 653 * 654 * @param string $string String to be humanized 655 * @param string $delimiter the character to replace with a space 656 * @return string Human-readable string 657 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-human-readable-forms 658 */ 659 public static function humanize($string, $delimiter = '_') 660 { 661 $cacheKey = __FUNCTION__ . $delimiter; 662 663 $result = static::_cache($cacheKey, $string); 664 665 if ($result === false) { 666 $result = explode(' ', str_replace($delimiter, ' ', $string)); 667 foreach ($result as &$word) { 668 $word = mb_strtoupper(mb_substr($word, 0, 1)) . mb_substr($word, 1); 669 } 670 $result = implode(' ', $result); 671 static::_cache($cacheKey, $string, $result); 672 } 673 674 return $result; 675 } 676 677 /** 678 * Expects a CamelCasedInputString, and produces a lower_case_delimited_string 679 * 680 * @param string $string String to delimit 681 * @param string $delimiter the character to use as a delimiter 682 * @return string delimited string 683 */ 684 public static function delimit($string, $delimiter = '_') 685 { 686 $cacheKey = __FUNCTION__ . $delimiter; 687 688 $result = static::_cache($cacheKey, $string); 689 690 if ($result === false) { 691 $result = mb_strtolower(preg_replace('/(?<=\\w)([A-Z])/', $delimiter . '\\1', $string)); 692 static::_cache($cacheKey, $string, $result); 693 } 694 695 return $result; 696 } 697 698 /** 699 * Returns corresponding table name for given model $className. ("people" for the model class "Person"). 700 * 701 * @param string $className Name of class to get database table name for 702 * @return string Name of the database table for given class 703 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-table-and-class-name-forms 704 */ 705 public static function tableize($className) 706 { 707 $result = static::_cache(__FUNCTION__, $className); 708 709 if ($result === false) { 710 $result = static::pluralize(static::underscore($className)); 711 static::_cache(__FUNCTION__, $className, $result); 712 } 713 714 return $result; 715 } 716 717 /** 718 * Returns Cake model class name ("Person" for the database table "people".) for given database table. 719 * 720 * @param string $tableName Name of database table to get class name for 721 * @return string Class name 722 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-table-and-class-name-forms 723 */ 724 public static function classify($tableName) 725 { 726 $result = static::_cache(__FUNCTION__, $tableName); 727 728 if ($result === false) { 729 $result = static::camelize(static::singularize($tableName)); 730 static::_cache(__FUNCTION__, $tableName, $result); 731 } 732 733 return $result; 734 } 735 736 /** 737 * Returns camelBacked version of an underscored string. 738 * 739 * @param string $string String to convert. 740 * @return string in variable form 741 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-variable-names 742 */ 743 public static function variable($string) 744 { 745 $result = static::_cache(__FUNCTION__, $string); 746 747 if ($result === false) { 748 $camelized = static::camelize(static::underscore($string)); 749 $replace = strtolower(substr($camelized, 0, 1)); 750 $result = $replace . substr($camelized, 1); 751 static::_cache(__FUNCTION__, $string, $result); 752 } 753 754 return $result; 755 } 756 757 /** 758 * Returns a string with all spaces converted to dashes (by default), accented 759 * characters converted to non-accented characters, and non word characters removed. 760 * 761 * @deprecated 3.2.7 Use Text::slug() instead. 762 * @param string $string the string you want to slug 763 * @param string $replacement will replace keys in map 764 * @return string 765 * @link https://book.cakephp.org/3/en/core-libraries/inflector.html#creating-url-safe-strings 766 */ 767 public static function slug($string, $replacement = '-') 768 { 769 deprecationWarning( 770 'Inflector::slug() is deprecated. ' . 771 'Use Text::slug() instead.' 772 ); 773 $quotedReplacement = preg_quote($replacement, '/'); 774 775 $map = [ 776 '/[^\s\p{Zs}\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]/mu' => ' ', 777 '/[\s\p{Zs}]+/mu' => $replacement, 778 sprintf('/^[%s]+|[%s]+$/', $quotedReplacement, $quotedReplacement) => '', 779 ]; 780 781 $string = str_replace( 782 array_keys(static::$_transliteration), 783 static::$_transliteration, 784 $string 785 ); 786 787 return preg_replace(array_keys($map), array_values($map), $string); 788 } 789} 790