api.morph.php 5.7 KB

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