[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Horde Inflector class. 4 * 5 * Copyright 2007-2014 Horde LLC (http://www.horde.org/) 6 * 7 * @todo Add the locale-bubbling pattern from 8 * Horde_Date_Parser/Horde_Support_Numerizer 9 * 10 * @category Horde 11 * @package Support 12 * @license http://www.horde.org/licenses/bsd 13 */ 14 class Horde_Support_Inflector 15 { 16 /** 17 * Inflection cache 18 * 19 * @var array 20 */ 21 protected $_cache = array(); 22 23 /** 24 * Rules for pluralizing English nouns. 25 * 26 * @var array 27 */ 28 protected $_pluralizationRules = array( 29 '/move$/i' => 'moves', 30 '/sex$/i' => 'sexes', 31 '/child$/i' => 'children', 32 '/man$/i' => 'men', 33 '/foot$/i' => 'feet', 34 '/person$/i' => 'people', 35 '/(quiz)$/i' => '$1zes', 36 '/^(ox)$/i' => '$1en', 37 '/(m|l)ouse$/i' => '$1ice', 38 '/(matr|vert|ind)ix|ex$/i' => '$1ices', 39 '/(x|ch|ss|sh)$/i' => '$1es', 40 '/([^aeiouy]|qu)ies$/i' => '$1y', 41 '/([^aeiouy]|qu)y$/i' => '$1ies', 42 '/(?:([^f])fe|([lr])f)$/i' => '$1$2ves', 43 '/sis$/i' => 'ses', 44 '/([ti])um$/i' => '$1a', 45 '/(buffal|tomat)o$/i' => '$1oes', 46 '/(bu)s$/i' => '$1ses', 47 '/(alias|status)$/i' => '$1es', 48 '/(octop|vir)us$/i' => '$1i', 49 '/(ax|test)is$/i' => '$1es', 50 '/s$/i' => 's', 51 '/$/' => 's', 52 ); 53 54 /** 55 * Rules for singularizing English nouns. 56 * 57 * @var array 58 */ 59 protected $_singularizationRules = array( 60 '/cookies$/i' => 'cookie', 61 '/moves$/i' => 'move', 62 '/sexes$/i' => 'sex', 63 '/children$/i' => 'child', 64 '/men$/i' => 'man', 65 '/feet$/i' => 'foot', 66 '/people$/i' => 'person', 67 '/databases$/i'=> 'database', 68 '/(quiz)zes$/i' => '\1', 69 '/(matr)ices$/i' => '\1ix', 70 '/(vert|ind)ices$/i' => '\1ex', 71 '/^(ox)en/i' => '\1', 72 '/(alias|status)es$/i' => '\1', 73 '/([octop|vir])i$/i' => '\1us', 74 '/(cris|ax|test)es$/i' => '\1is', 75 '/(shoe)s$/i' => '\1', 76 '/(o)es$/i' => '\1', 77 '/(bus)es$/i' => '\1', 78 '/([m|l])ice$/i' => '\1ouse', 79 '/(x|ch|ss|sh)es$/i' => '\1', 80 '/(m)ovies$/i' => '\1ovie', 81 '/(s)eries$/i' => '\1eries', 82 '/([^aeiouy]|qu)ies$/i' => '\1y', 83 '/([lr])ves$/i' => '\1f', 84 '/(tive)s$/i' => '\1', 85 '/(hive)s$/i' => '\1', 86 '/([^f])ves$/i' => '\1fe', 87 '/(^analy)ses$/i' => '\1sis', 88 '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', 89 '/([ti])a$/i' => '\1um', 90 '/(n)ews$/i' => '\1ews', 91 '/(.*)s$/i' => '\1', 92 ); 93 94 /** 95 * An array of words with the same singular and plural spellings. 96 * 97 * @var array 98 */ 99 protected $_uncountables = array( 100 'aircraft', 101 'cannon', 102 'deer', 103 'equipment', 104 'fish', 105 'information', 106 'money', 107 'moose', 108 'rice', 109 'series', 110 'sheep', 111 'species', 112 'swine', 113 ); 114 115 /** 116 * Constructor. 117 * 118 * Stores a map of the uncountable words for quicker checks. 119 */ 120 public function __construct() 121 { 122 $this->_uncountables_keys = array_flip($this->_uncountables); 123 } 124 125 /** 126 * Adds an uncountable word. 127 * 128 * @param string $word The uncountable word. 129 */ 130 public function uncountable($word) 131 { 132 $this->_uncountables[] = $word; 133 $this->_uncountables_keys[$word] = true; 134 } 135 136 /** 137 * Singular English word to pluralize. 138 * 139 * @param string $word Word to pluralize. 140 * 141 * @return string Plural form of $word. 142 */ 143 public function pluralize($word) 144 { 145 if ($plural = $this->getCache($word, 'pluralize')) { 146 return $plural; 147 } 148 149 if (isset($this->_uncountables_keys[$word])) { 150 return $word; 151 } 152 153 foreach ($this->_pluralizationRules as $regexp => $replacement) { 154 $plural = preg_replace($regexp, $replacement, $word, -1, $matches); 155 if ($matches > 0) { 156 return $this->setCache($word, 'pluralize', $plural); 157 } 158 } 159 160 return $this->setCache($word, 'pluralize', $word); 161 } 162 163 /** 164 * Plural English word to singularize. 165 * 166 * @param string $word Word to singularize. 167 * 168 * @return string Singular form of $word. 169 */ 170 public function singularize($word) 171 { 172 if ($singular = $this->getCache($word, 'singularize')) { 173 return $singular; 174 } 175 176 if (isset($this->_uncountables_keys[$word])) { 177 return $word; 178 } 179 180 foreach ($this->_singularizationRules as $regexp => $replacement) { 181 $singular = preg_replace($regexp, $replacement, $word, -1, $matches); 182 if ($matches > 0) { 183 return $this->setCache($word, 'singularize', $singular); 184 } 185 } 186 187 return $this->setCache($word, 'singularize', $word); 188 } 189 190 /** 191 * Camel-cases a word. 192 * 193 * @param string $word The word to camel-case. 194 * @param string $firstLetter Whether to upper or lower case the first. 195 * letter of each slash-separated section. 196 * 197 * @return string Camelized $word 198 */ 199 public function camelize($word, $firstLetter = 'upper') 200 { 201 if ($camelized = $this->getCache($word, 'camelize' . $firstLetter)) { 202 return $camelized; 203 } 204 205 $camelized = $word; 206 if (strtolower($camelized) != $camelized && 207 strpos($camelized, '_') !== false) { 208 $camelized = str_replace('_', '/', $camelized); 209 } 210 if (strpos($camelized, '/') !== false) { 211 $camelized = str_replace('/', '/ ', $camelized); 212 } 213 if (strpos($camelized, '_') !== false) { 214 $camelized = strtr($camelized, '_', ' '); 215 } 216 217 $camelized = str_replace(' ', '', ucwords($camelized)); 218 219 if ($firstLetter == 'lower') { 220 $parts = array(); 221 foreach (explode('/', $camelized) as $part) { 222 $part[0] = strtolower($part[0]); 223 $parts[] = $part; 224 } 225 $camelized = implode('/', $parts); 226 } 227 228 return $this->setCache($word, 'camelize' . $firstLetter, $camelized); 229 } 230 231 /** 232 * Capitalizes all the words and replaces some characters in the string to 233 * create a nicer looking title. 234 * 235 * Titleize is meant for creating pretty output. 236 * 237 * See: 238 * - http://daringfireball.net/2008/05/title_case 239 * - http://daringfireball.net/2008/08/title_case_update 240 * 241 * Examples: 242 * 1. titleize("man from the boondocks") => "Man From The Boondocks" 243 * 2. titleize("x-men: the last stand") => "X Men: The Last Stand" 244 */ 245 public function titleize($word) 246 { 247 throw new Exception('not implemented yet'); 248 } 249 250 /** 251 * The reverse of camelize(). 252 * 253 * Makes an underscored form from the expression in the string. 254 * 255 * Examples: 256 * 1. underscore("ActiveRecord") => "active_record" 257 * 2. underscore("ActiveRecord_Errors") => "active_record_errors" 258 */ 259 public function underscore($camelCasedWord) 260 { 261 $word = $camelCasedWord; 262 if ($result = $this->getCache($word, 'underscore')) { 263 return $result; 264 } 265 $result = strtolower(preg_replace('/([a-z])([A-Z])/', "\$1}_\$2}", $word)); 266 return $this->setCache($word, 'underscore', $result); 267 } 268 269 /** 270 * Replaces underscores with dashes in the string. 271 * 272 * Example: 273 * 1. dasherize("puni_puni") => "puni-puni" 274 */ 275 public function dasherize($underscoredWord) 276 { 277 if ($result = $this->getCache($underscoredWord, 'dasherize')) { 278 return $result; 279 } 280 281 $result = str_replace('_', '-', $this->underscore($underscoredWord)); 282 return $this->setCache($underscoredWord, 'dasherize', $result); 283 } 284 285 /** 286 * Capitalizes the first word and turns underscores into spaces and strips 287 * _id. 288 * 289 * Like titleize(), this is meant for creating pretty output. 290 * 291 * Examples: 292 * 1. humanize("employee_salary") => "Employee salary" 293 * 2. humanize("author_id") => "Author" 294 */ 295 public function humanize($lowerCaseAndUnderscoredWord) 296 { 297 $word = $lowerCaseAndUnderscoredWord; 298 if ($result = $this->getCache($word, 'humanize')) { 299 return $result; 300 } 301 302 $result = ucfirst(str_replace('_', ' ', $this->underscore($word))); 303 if (substr($result, -3, 3) == ' id') { 304 $result = str_replace(' id', '', $result); 305 } 306 return $this->setCache($word, 'humanize', $result); 307 } 308 309 /** 310 * Removes the module part from the expression in the string. 311 * 312 * Examples: 313 * 1. demodulize("Fax_Job") => "Job" 314 * 1. demodulize("User") => "User" 315 */ 316 public function demodulize($classNameInModule) 317 { 318 $result = explode('_', $classNameInModule); 319 return array_pop($result); 320 } 321 322 /** 323 * Creates the name of a table like Rails does for models to table names. 324 * 325 * This method uses the pluralize() method on the last word in the string. 326 * 327 * Examples: 328 * 1. tableize("RawScaledScorer") => "raw_scaled_scorers" 329 * 2. tableize("egg_and_ham") => "egg_and_hams" 330 * 3. tableize("fancyCategory") => "fancy_categories" 331 */ 332 public function tableize($className) 333 { 334 if ($result = $this->getCache($className, 'tableize')) { 335 return $result; 336 } 337 338 $result = $this->pluralize($this->underscore($className)); 339 $result = str_replace('/', '_', $result); 340 return $this->setCache($className, 'tableize', $result); 341 } 342 343 /** 344 * Creates a class name from a table name like Rails does for table names 345 * to models. 346 * 347 * Examples: 348 * 1. classify("egg_and_hams") => "EggAndHam" 349 * 2. classify("post") => "Post" 350 */ 351 public function classify($tableName) 352 { 353 if ($result = $this->getCache($tableName, 'classify')) { 354 return $result; 355 } 356 $result = $this->camelize($this->singularize($tableName)); 357 358 // classes use underscores instead of slashes for namespaces 359 $result = str_replace('/', '_', $result); 360 return $this->setCache($tableName, 'classify', $result); 361 } 362 363 /** 364 * Creates a foreign key name from a class name. 365 * 366 * $separateClassNameAndIdWithUnderscore sets whether the method should put 367 * '_' between the name and 'id'. 368 * 369 * Examples: 370 * 1. foreignKey("Message") => "message_id" 371 * 2. foreignKey("Message", false) => "messageid" 372 * 3. foreignKey("Fax_Job") => "fax_job_id" 373 */ 374 public function foreignKey($className, $separateClassNameAndIdWithUnderscore = true) 375 { 376 throw new Exception('not implemented yet'); 377 } 378 379 /** 380 * Turns a number into an ordinal string used to denote the position in an 381 * ordered sequence such as 1st, 2nd, 3rd, 4th. 382 * 383 * Examples: 384 * 1. ordinalize(1) => "1st" 385 * 2. ordinalize(2) => "2nd" 386 * 3. ordinalize(1002) => "1002nd" 387 * 4. ordinalize(1003) => "1003rd" 388 */ 389 public function ordinalize($number) 390 { 391 throw new Exception('not implemented yet'); 392 } 393 394 /** 395 * Clears the inflection cache. 396 */ 397 public function clearCache() 398 { 399 $this->_cache = array(); 400 } 401 402 /** 403 * Retuns a cached inflection. 404 * 405 * @return string | false 406 */ 407 public function getCache($word, $rule) 408 { 409 return isset($this->_cache[$word . '|' . $rule]) ? 410 $this->_cache[$word . '|' . $rule] : false; 411 } 412 413 /** 414 * Caches an inflection. 415 * 416 * @param string $word The word being inflected. 417 * @param string $rule The inflection rule. 418 * @param string $value The inflected value of $word. 419 * 420 * @return string The inflected value 421 */ 422 public function setCache($word, $rule, $value) 423 { 424 $this->_cache[$word . '|' . $rule] = $value; 425 return $value; 426 } 427 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |