api.morph.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /**
  3. * Class usage example :
  4. *
  5. * $morph=new UBMorph();
  6. * deb($morph->sum2str('10,21')); // десять гривень 21 копійка
  7. * $morph->setType('RUR'); // and russian locale selected by admin...
  8. * deb($morph->sum2str('300')); //триста рублей 00 копеек
  9. */
  10. class UBMorph {
  11. protected $currencyType = 'UAH';
  12. protected $usCfg = array();
  13. public function __construct() {
  14. $this->loadCfg();
  15. $this->initType();
  16. }
  17. /**
  18. * Loads userstats.ini into protected property for further usage
  19. *
  20. * @return void
  21. */
  22. protected function loadCfg() {
  23. $this->usCfg = zbs_LoadConfig();
  24. }
  25. /**
  26. * Inits default currency type at startup, handles TEMPLATE_CURRENCY option
  27. *
  28. * @return void
  29. */
  30. protected function initType() {
  31. if (isset($this->usCfg['TEMPLATE_CURRENCY'])) {
  32. $this->currencyType = $this->usCfg['TEMPLATE_CURRENCY'];
  33. } else {
  34. $this->currencyType = 'UAH';
  35. }
  36. }
  37. /**
  38. * Returns current currency
  39. *
  40. * @return string
  41. */
  42. public function getType() {
  43. return ($this->currencyType);
  44. }
  45. /**
  46. * Sets current currency type like UAH or RUR
  47. *
  48. * @param string $type
  49. *
  50. * @return void
  51. */
  52. public function setType($type) {
  53. $this->currencyType = $type;
  54. }
  55. /**
  56. * Returns localized and literated sum for cash
  57. *
  58. * @param float $sum
  59. * @param bool $strippenny
  60. * @return string
  61. */
  62. public function sum2str($sum, $strippenny = false) {
  63. $zero = __('zero');
  64. $str[100] = array('', __('one hundred'), __('two hundred'), __('three hundred'), __('four hundred'), __('five hundred'), __('six hundred'), __('seven hundred'), __('eight hundred'), __('nine hundred'));
  65. $str[11] = array('', __('ten'), __('eleven'), __('twelve'), __('thirteen'), __('fourteen'), __('fifteen'), __('sixteen'), __('seventeen'), __('eightteen'), __('nineteen'), __('twenty'));
  66. $str[10] = array('', __('ten'), __('twenty'), __('thirty'), __('fourty'), __('fifty'), __('sixty'), __('seventy'), __('eighty'), __('ninety'));
  67. $sex = array(
  68. array('', __('one male'), __('two male'), __('three male'), __('four male'), __('five male'), __('six male'), __('seven male'), __('eight male'), __('nine male')), // m
  69. array('', __('one female'), __('two female'), __('three female'), __('four female'), __('five female'), __('six female'), __('seven female'), __('eight female'), __('nine female')) // f
  70. );
  71. if ($this->currencyType == 'UAH') {
  72. $nowCurrency = array(__('hryvna'), __('hryvnax'), __('hryvnas'), 0);
  73. }
  74. if ($this->currencyType == 'RUR') {
  75. $nowCurrency = array(__('ruble'), __('rublex'), __('rubles'), 0);
  76. }
  77. $forms = array(
  78. array(__('penny'), __('pennyx'), __('pennies'), 1), // 10^-2
  79. $nowCurrency, // 10^ 0
  80. array(__('thousand'), __('thousandx'), __('thousands'), 1), // 10^ 3
  81. array(__('million'), __('millionx'), __('millions'), 0), // 10^ 6
  82. array(__('billion'), __('billionx'), __('billions'), 0), // 10^ 9
  83. array(__('trillion'), __('trillionx'), __('trillions'), 0), // 10^12
  84. );
  85. $out = $tmp = array();
  86. $tmp = explode('.', str_replace(',', '.', $sum));
  87. $currency = number_format($tmp[0], 0, '', '-');
  88. if ($currency == 0) {
  89. $out[] = $zero;
  90. }
  91. // normalize penny
  92. $penny = isset($tmp[1]) ? substr(str_pad($tmp[1], 2, '0', STR_PAD_RIGHT), 0, 2) : '00';
  93. $segments = explode('-', $currency);
  94. $offset = sizeof($segments);
  95. if ((int) $currency == 0) { // if 0 money
  96. $o[] = $zero;
  97. $o[] = $this->morph(0, $forms[1][0], $forms[1][1], $forms[1][2]);
  98. } else {
  99. foreach ($segments as $k => $lev) {
  100. $sexi = (int) $forms[$offset][3]; // detect sex
  101. $ri = (int) $lev; // current segment
  102. if ($ri == 0 && $offset > 1) {
  103. $offset--;
  104. continue;
  105. }
  106. // normalization
  107. $ri = str_pad($ri, 3, '0', STR_PAD_LEFT);
  108. //extract digits
  109. $r1 = (int) substr($ri, 0, 1); //first digit
  110. $r2 = (int) substr($ri, 1, 1); //second digit
  111. $r3 = (int) substr($ri, 2, 1); //third digit
  112. $r22 = (int) $r2 . $r3; //second and third digit
  113. //extract limits
  114. if ($ri > 99)
  115. $o[] = $str[100][$r1]; // hundreds
  116. if ($r22 > 20) {// >20
  117. $o[] = $str[10][$r2];
  118. $o[] = $sex[$sexi][$r3];
  119. } else { // <=20
  120. if ($r22 > 9)
  121. $o[] = $str[11][$r22 - 9]; // 10-20
  122. elseif ($r22 > 0)
  123. $o[] = $sex[$sexi][$r3]; // 1-9
  124. }
  125. // rounded cash
  126. $o[] = $this->morph($ri, $forms[$offset][0], $forms[$offset][1], $forms[$offset][2]);
  127. $offset--;
  128. }
  129. }
  130. // pennies
  131. if (!$strippenny) {
  132. $o[] = $penny;
  133. $o[] = $this->morph($penny, $forms[0][0], $forms[0][1], $forms[0][2]);
  134. }
  135. return preg_replace("/\s{2,}/", ' ', implode(' ', $o));
  136. }
  137. /**
  138. * Brutal morph here
  139. *
  140. * @param int $n
  141. * @param int $f1
  142. * @param int $f2
  143. * @param int $f5
  144. * @return int
  145. */
  146. protected function morph($n, $f1, $f2, $f5) {
  147. $n = abs($n) % 100;
  148. $n1 = $n % 10;
  149. if ($n > 10 && $n < 20)
  150. return $f5;
  151. if ($n1 > 1 && $n1 < 5)
  152. return $f2;
  153. if ($n1 == 1)
  154. return $f1;
  155. return $f5;
  156. }
  157. }