Inflector.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <?php
  2. /**
  3. * Inflector helper class. Inflection is changing the form of a word based on
  4. * the context it is used in. For example, changing a word into a plural form.
  5. *
  6. * [!!] Inflection is only tested with English, and is will not work with other languages.
  7. *
  8. * @package Kohana
  9. * @category Helpers
  10. * @author Kohana Team
  11. * @copyright (c) Kohana Team
  12. * @license https://koseven.ga/LICENSE.md
  13. */
  14. class Kohana_Inflector {
  15. /**
  16. * @var array cached inflections
  17. */
  18. protected static $cache = [];
  19. /**
  20. * @var array uncountable words
  21. */
  22. protected static $uncountable;
  23. /**
  24. * @var array irregular words
  25. */
  26. protected static $irregular;
  27. /**
  28. * Checks if a word is defined as uncountable. An uncountable word has a
  29. * single form. For instance, one "fish" and many "fish", not "fishes".
  30. *
  31. * Inflector::uncountable('fish'); // TRUE
  32. * Inflector::uncountable('cat'); // FALSE
  33. *
  34. * If you find a word is being pluralized improperly, it has probably not
  35. * been defined as uncountable in `config/inflector.php`. If this is the
  36. * case, please report [an issue](http://dev.kohanaphp.com/projects/kohana3/issues).
  37. *
  38. * @param string $str word to check
  39. * @return boolean
  40. */
  41. public static function uncountable($str)
  42. {
  43. if (Inflector::$uncountable === NULL)
  44. {
  45. // Cache uncountables
  46. Inflector::$uncountable = Kohana::$config->load('inflector')->uncountable;
  47. // Make uncountables mirrored
  48. Inflector::$uncountable = array_combine(Inflector::$uncountable, Inflector::$uncountable);
  49. }
  50. return isset(Inflector::$uncountable[strtolower($str)]);
  51. }
  52. /**
  53. * Makes a plural word singular.
  54. *
  55. * echo Inflector::singular('cats'); // "cat"
  56. * echo Inflector::singular('fish'); // "fish", uncountable
  57. *
  58. * You can also provide the count to make inflection more intelligent.
  59. * In this case, it will only return the singular value if the count is
  60. * greater than one and not zero.
  61. *
  62. * echo Inflector::singular('cats', 2); // "cats"
  63. *
  64. * [!!] Special inflections are defined in `config/inflector.php`.
  65. *
  66. * @param string $str word to make singular
  67. * @param integer $count count of thing
  68. * @return string
  69. * @uses Inflector::uncountable
  70. */
  71. public static function singular($str, $count = NULL)
  72. {
  73. // $count should always be a float
  74. $count = ($count === NULL) ? 1.0 : (float) $count;
  75. // Do nothing when $count is not 1
  76. if ($count != 1)
  77. return $str;
  78. // Remove garbage
  79. $str = strtolower(trim($str));
  80. // Cache key name
  81. $key = 'singular_'.$str.$count;
  82. if (isset(Inflector::$cache[$key]))
  83. return Inflector::$cache[$key];
  84. if (Inflector::uncountable($str))
  85. return Inflector::$cache[$key] = $str;
  86. if (empty(Inflector::$irregular))
  87. {
  88. // Cache irregular words
  89. Inflector::$irregular = Kohana::$config->load('inflector')->irregular;
  90. }
  91. if ($irregular = array_search($str, Inflector::$irregular))
  92. {
  93. $str = $irregular;
  94. }
  95. elseif (preg_match('/us$/', $str))
  96. {
  97. // http://en.wikipedia.org/wiki/Plural_form_of_words_ending_in_-us
  98. // Already singular, do nothing
  99. }
  100. elseif (preg_match('/[sxz]es$/', $str) OR preg_match('/[^aeioudgkprt]hes$/', $str))
  101. {
  102. // Remove "es"
  103. $str = substr($str, 0, -2);
  104. }
  105. elseif (preg_match('/[^aeiou]ies$/', $str))
  106. {
  107. // Replace "ies" with "y"
  108. $str = substr($str, 0, -3).'y';
  109. }
  110. elseif (substr($str, -1) === 's' AND substr($str, -2) !== 'ss')
  111. {
  112. // Remove singular "s"
  113. $str = substr($str, 0, -1);
  114. }
  115. return Inflector::$cache[$key] = $str;
  116. }
  117. /**
  118. * Makes a singular word plural.
  119. *
  120. * echo Inflector::plural('fish'); // "fish", uncountable
  121. * echo Inflector::plural('cat'); // "cats"
  122. *
  123. * You can also provide the count to make inflection more intelligent.
  124. * In this case, it will only return the plural value if the count is
  125. * not one.
  126. *
  127. * echo Inflector::singular('cats', 3); // "cats"
  128. *
  129. * [!!] Special inflections are defined in `config/inflector.php`.
  130. *
  131. * @param string $str word to pluralize
  132. * @param integer $count count of thing
  133. * @return string
  134. * @uses Inflector::uncountable
  135. */
  136. public static function plural($str, $count = NULL)
  137. {
  138. // $count should always be a float
  139. $count = ($count === NULL) ? 0.0 : (float) $count;
  140. // Do nothing with singular
  141. if ($count == 1)
  142. return $str;
  143. // Remove garbage
  144. $str = trim($str);
  145. // Cache key name
  146. $key = 'plural_'.$str.$count;
  147. // Check uppercase
  148. $is_uppercase = ctype_upper($str);
  149. if (isset(Inflector::$cache[$key]))
  150. return Inflector::$cache[$key];
  151. if (Inflector::uncountable($str))
  152. return Inflector::$cache[$key] = $str;
  153. if (empty(Inflector::$irregular))
  154. {
  155. // Cache irregular words
  156. Inflector::$irregular = Kohana::$config->load('inflector')->irregular;
  157. }
  158. if (isset(Inflector::$irregular[$str]))
  159. {
  160. $str = Inflector::$irregular[$str];
  161. }
  162. elseif (in_array($str, Inflector::$irregular))
  163. {
  164. // Do nothing
  165. }
  166. elseif (preg_match('/[sxz]$/', $str) OR preg_match('/[^aeioudgkprt]h$/', $str))
  167. {
  168. $str .= 'es';
  169. }
  170. elseif (preg_match('/[^aeiou]y$/', $str))
  171. {
  172. // Change "y" to "ies"
  173. $str = substr_replace($str, 'ies', -1);
  174. }
  175. else
  176. {
  177. $str .= 's';
  178. }
  179. // Convert to uppercase if necessary
  180. if ($is_uppercase)
  181. {
  182. $str = strtoupper($str);
  183. }
  184. // Set the cache and return
  185. return Inflector::$cache[$key] = $str;
  186. }
  187. /**
  188. * Makes a phrase camel case. Spaces and underscores will be removed.
  189. *
  190. * $str = Inflector::camelize('mother cat'); // "motherCat"
  191. * $str = Inflector::camelize('kittens in bed'); // "kittensInBed"
  192. *
  193. * @param string $str phrase to camelize
  194. * @return string
  195. */
  196. public static function camelize($str)
  197. {
  198. $str = 'x'.strtolower(trim($str));
  199. $str = ucwords(preg_replace('/[\s_]+/', ' ', $str));
  200. return substr(str_replace(' ', '', $str), 1);
  201. }
  202. /**
  203. * Converts a camel case phrase into a spaced phrase.
  204. *
  205. * $str = Inflector::decamelize('houseCat'); // "house cat"
  206. * $str = Inflector::decamelize('kingAllyCat'); // "king ally cat"
  207. *
  208. * @param string $str phrase to camelize
  209. * @param string $sep word separator
  210. * @return string
  211. */
  212. public static function decamelize($str, $sep = ' ')
  213. {
  214. return strtolower(preg_replace('/([a-z])([A-Z])/', '$1'.$sep.'$2', trim($str)));
  215. }
  216. /**
  217. * Makes a phrase underscored instead of spaced.
  218. *
  219. * $str = Inflector::underscore('five cats'); // "five_cats";
  220. *
  221. * @param string $str phrase to underscore
  222. * @return string
  223. */
  224. public static function underscore($str)
  225. {
  226. return preg_replace('/\s+/', '_', trim($str));
  227. }
  228. /**
  229. * Makes an underscored or dashed phrase human-readable.
  230. *
  231. * $str = Inflector::humanize('kittens-are-cats'); // "kittens are cats"
  232. * $str = Inflector::humanize('dogs_as_well'); // "dogs as well"
  233. *
  234. * @param string $str phrase to make human-readable
  235. * @return string
  236. */
  237. public static function humanize($str)
  238. {
  239. return preg_replace('/[_-]+/', ' ', trim($str));
  240. }
  241. }