Guest User

Untitled

a guest
Jun 24th, 2018
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.22 KB | None | 0 0
  1. <?php
  2. /**
  3. * Gemstone::framework app/lib/utils/inflector.lib.php
  4. *
  5. * Library to provide a framework for various inflections.
  6. *
  7. * @author Pavel Lisa <thepablick@gemstonewebdesign.eu>
  8. * @copyright 2010 Gemstone Webdesign
  9. * @package framework
  10. * @subpackage library
  11. */
  12.  
  13. namespace Gemstone\Utils;
  14.  
  15. use Gemstone;
  16.  
  17. final class Inflector
  18. {
  19. /**
  20. * Initialized boolean flag
  21. * @var bool
  22. */
  23. private static $initialized = false;
  24.  
  25. /**
  26. * Hash of plurals => singulars
  27. * @var hash
  28. */
  29. private static $singulars = array();
  30.  
  31. /**
  32. * Caching hash of already singularized strings
  33. * @var hash
  34. */
  35. private static $singularized_cache = array();
  36.  
  37. /**
  38. * Hash of singulars => plurals
  39. * @var hash
  40. */
  41. private static $plurals = array();
  42.  
  43. /**
  44. * Caching hash of already pluralized strings
  45. * @var hash
  46. */
  47. private static $pluralized_cache = array();
  48.  
  49. /**
  50. * Array of uncountable words
  51. * @var array
  52. */
  53. private static $uncountable = array();
  54.  
  55. /**
  56. * Hash of shortcuts to convert to uppercase
  57. * @var hash
  58. */
  59. private static $shortcuts = array();
  60.  
  61. /**
  62. * Hash of already camelized strings (generic mode)
  63. * @var hash
  64. */
  65. private static $camelized_generic_cache = array();
  66.  
  67. /**
  68. * Hash of already camelized strings (className mode)
  69. * @var hash
  70. */
  71. private static $camelized_className_cache = array();
  72.  
  73. /**
  74. * Hash of already decamelized strings
  75. * @var hash
  76. */
  77. private static $decamelized_cache = array();
  78.  
  79. /**
  80. * Initialize inflections for a particular language, or the default set
  81. * @param string $inflections The inflections set
  82. */
  83. public static function initialize( $inflections = 'default' )
  84. {
  85. self::$singulars = array();
  86. self::$plurals = array();
  87. self::$uncountable = array();
  88. include Gemstone\Core::$config_libs_dir.'inflector.lib/'.$inflections.'.inflections.php';
  89. self::$initialized = true;
  90. }
  91.  
  92. /**
  93. * Set a singularization rule
  94. * @param string $pattern The plural to match
  95. * @param string $replacement The singular to replace plural
  96. */
  97. public static function singular($pattern, $replacement )
  98. {
  99. array_unshift(self::$singulars, array($pattern, $replacement ));
  100. }
  101.  
  102. /**
  103. * Set a pluralization rule
  104. * @param string $pattern The singular to match
  105. * @param string $replacement The plural to replace singular
  106. */
  107. public static function plural($pattern, $replacement)
  108. {
  109. array_unshift(self::$plurals, array($pattern, $replacement));
  110. }
  111.  
  112. /**
  113. * Add an uncountable word
  114. * @param string $word Uncountable word
  115. * @param string $...
  116. */
  117. public static function uncountable()
  118. {
  119. $uncountable_input = func_get_args();
  120. for ( $i = 0; $i < count($uncountable_input); $i++)
  121. {
  122. self::$uncountable[] = $uncountable_input[$i];
  123. }
  124. }
  125.  
  126. /**
  127. * Cross add irregular word
  128. * @param string $singular_in Singular form of the irregular word
  129. * @param string $plural_in Plural form of the irregular word
  130. */
  131. public static function irregular($singular_in, $plural_in)
  132. {
  133. array_unshift(self::$plurals, array($singular_in, $plural_in));
  134. array_unshift(self::$singulars, array($plural_in, $singular_in));
  135. }
  136.  
  137. /**
  138. * Add shortcuts for camelize
  139. * @param array $input
  140. */
  141. public static function shortcuts( array $input )
  142. {
  143. self::$shortcuts = array_merge( self::$shortcuts, $input );
  144. }
  145.  
  146. /**
  147. * Get the singular of a plural word
  148. * @param string $word Plural
  149. */
  150. public static function singularize( $word )
  151. {
  152. if (is_null($word) or ( ! is_string($word)) or (strlen($word) == 0) )
  153. {
  154. return null;
  155. }
  156. elseif (in_array($word, self::$uncountable))
  157. {
  158. return $word;
  159. }
  160. elseif ( isset( self::$singularized_cache[ $word ] ) )
  161. {
  162. return self::$singularized_cache[ $word ];
  163. }
  164. else
  165. {
  166. for ( $i = 0; $i < count(self::$singulars); $i++)
  167. {
  168. # add a '$' for irregular patterns at the end of regex
  169. $regexp_end = ( strpos(self::$singulars[$i][0], '$') === false ) ? '$' : '';
  170.  
  171. # test the words
  172. if (preg_match('/'.self::$singulars[$i][0].$regexp_end.'/i', $word))
  173. {
  174. return self::$singularized_cache[ $word ] = preg_replace('/'.self::$singulars[$i][0].$regexp_end.'/i', self::$singulars[$i][1], $word);
  175. }
  176. }
  177. return self::$singularized_cache[ $word ] = $word; # not detected
  178. }
  179. }
  180.  
  181. /**
  182. * Get the plural of a singular word
  183. * @param string $word Singular
  184. */
  185. public static function pluralize( $word )
  186. {
  187. if (is_null($word) or ( ! is_string($word)) or (strlen($word) == 0) )
  188. {
  189. return null;
  190. }
  191. elseif (in_array($word, self::$uncountable))
  192. {
  193. return $word;
  194. }
  195. elseif ( isset( self::$pluralized_cache[ $word ] ) )
  196. {
  197. return self::$pluralized_cache[ $word ];
  198. }
  199. else
  200. {
  201. for ( $i = 0; $i < count(self::$plurals); $i++)
  202. {
  203. # add a '$' for irregular patterns at the end of regex
  204. $regexp_end = ( strpos(self::$plurals[$i][0], '$') === false ) ? '$' : '';
  205.  
  206. # test the words
  207. if (preg_match('/'.self::$plurals[$i][0].$regexp_end.'/i', $word))
  208. {
  209. return self::$pluralized_cache[ $word ] = preg_replace('/'.self::$plurals[$i][0].$regexp_end.'/i', self::$plurals[$i][1], $word);
  210. }
  211. }
  212. return self::$pluralized_cache[ $word ] = $word; # not detected
  213. }
  214. }
  215.  
  216. /**
  217. * Convert decamelized expression to camelized
  218. * @param string $input Decamelized
  219. * @throws InflectorException
  220. */
  221. public static function camelize( $input, $mode = 0 )
  222. {
  223. try
  224. {
  225. if ( is_string($input) )
  226. {
  227. if ( $mode === 0 ) // generic mode
  228. {
  229. # cache hit
  230. if ( isset( self::$camelized_generic_cache[ $input ] ) )
  231. {
  232. return self::$camelized_generic_cache[ $input ];
  233. }
  234.  
  235. # cache miss
  236.  
  237. # split input string into chunks by delimiter '_'
  238. $tokenized = explode('_', $input);
  239.  
  240. for ( $i=0; $i < count($tokenized); $i++ )
  241. {
  242. if ( isset( self::$shortcuts[ $tokenized[$i] = strtolower($tokenized[$i]) ] ) )
  243. {
  244. $tokenized[$i] = self::$shortcuts[ $tokenized[$i] ] . '_';
  245. }
  246. elseif ( strlen( $tokenized[$i] ) >= 1 )
  247. {
  248. # and each first letter of chunk uppercase
  249. $tokenized[$i] = ucfirst($tokenized[$i]);
  250. }
  251. }
  252.  
  253. # return camelized expression
  254. return self::$camelized_generic_cache[ $input ] = implode('', $tokenized);
  255. }
  256. elseif ( $mode === 1 ) // className mode
  257. {
  258. # cache hit
  259. if ( isset( self::$camelized_className_cache[ $input ] ) )
  260. {
  261. return self::$camelized_className_cache[ $input ];
  262. }
  263.  
  264. # cache miss
  265.  
  266. # split input string into chunks by delimiters
  267. $tokenized = preg_split( '~(_|\\\\|/)~', $input, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  268.  
  269. for ( $i=0; $i < count($tokenized); $i++ )
  270. {
  271. if ( isset( self::$shortcuts[ $tokenized[$i] = strtolower($tokenized[$i]) ] ) )
  272. {
  273. $tokenized[$i] = self::$shortcuts[ $tokenized[$i] ];
  274. }
  275. elseif ( strlen( $tokenized[$i] ) >= 1 )
  276. {
  277. # and each first letter of chunk uppercase
  278. $tokenized[$i] = ucfirst($tokenized[$i]);
  279. }
  280.  
  281. $tokenized[$i] = strtr($tokenized[$i], array( '/' => '\\' )); // for namespaces support
  282. }
  283.  
  284. # return camelized expression
  285. return self::$camelized_className_cache[ $input ] = implode('', $tokenized);
  286. }
  287. }
  288. elseif ( is_array($input) )
  289. {
  290. # enables to camelize an array of decamelized strings
  291. # note: it may recursively decamelize nested arrays
  292. $reply = array();
  293.  
  294. # camelize each string in input array
  295. foreach ( $input as $camelized )
  296. {
  297. $reply[] = self::camelize($camelized);
  298. # note that this may throw an exception if just a one entry of input array is not a string or array
  299. }
  300.  
  301. return $reply;
  302. }
  303. else
  304. {
  305. throw new \InvalidArgumentException( 'Argument must be either string or an array of strings' );
  306. }
  307. }
  308. catch ( \InvalidArgumentException $e )
  309. {
  310. throw new InflectorException(300, $e);
  311. }
  312. }
  313.  
  314. /**
  315. * Convert camelized expression to decamelized
  316. * @param string $input Camelized
  317. * @throws InflectorException
  318. */
  319. public static function decamelize( $input )
  320. {
  321. try
  322. {
  323. if ( is_string($input) )
  324. {
  325. # cache hit
  326. if ( isset( self::$decamelized_cache[ $input ] ) )
  327. {
  328. return self::$decamelized_cache[ $input ];
  329. }
  330.  
  331. # cache miss
  332.  
  333. # split input string into chunks defined as one uppercase letter and any lowercase letters
  334. $tokenized = preg_split('/([A-Z]+[a-z]+)/', $input, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  335.  
  336. for ( $i=0; $i < count($tokenized); $i++ )
  337. {
  338. # make each chunk lowercase
  339. $tokenized[$i] = strtr(strtolower($tokenized[$i]), array('_' => ''));
  340. }
  341.  
  342. # glue the chunks together by '_'
  343. return self::$decamelized_cache[ $input ] = implode('_', $tokenized);
  344. }
  345. elseif ( is_array($input) )
  346. {
  347. # the same as with camelize method - enables decamelization of array of strings
  348. # note: recursively as well
  349. $reply = array();
  350.  
  351. foreach ( $input as $decamelized )
  352. {
  353. $reply[] = self::decamelize($decamelized);
  354. }
  355.  
  356. return $reply;
  357. }
  358. else
  359. {
  360. throw new \InvalidArgumentException( 'Argument must be either string or an array of strings' );
  361. }
  362. }
  363. catch ( \InvalidArgumentException $e )
  364. {
  365. throw new InflectorException(300, $e);
  366. }
  367. }
  368. }
  369. ?>
Add Comment
Please, Sign In to add comment